Cannot set manager attribute using ADSI in PowerShell - powershell

I update some user information in AD from an HR database.
Text fields or the photo works fine:
$user.Put("telephoneNumber", "1234")
$user.Put("thumbnailPhoto", $binaryfile)
$user.SetInfo()
But I also have to set the manager and tried
$user.Put("manager", "MYDOMAIN\MYUSERNAME")
or
$user.Put("manager", "MYUSERNAME")
That gives the following error:
Exception calling "setinfo" with "0" argument(s): "An invalid dn syntax has been specified."
What's the correct syntax to update the manager using ADSI?

As the error message suggests: the manager attribute expects a distinguished name (dn), not a user logon name, so you need to get the manager's dn first and then put that value into the manager attribute.
$manager = 'MYUSERNAME'
#...
$searcher = New-Object DirectoryServices.DirectorySearcher(([adsi]''))
$searcher.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=${manager}))"
$dn = $searcher.FindOne().Properties['distinguishedName'][0]
#...
$user.Put('manager', $dn)
$user.SetInfo()

Related

How to modify field properties in content type using PnP PowerShell?

I need to change validation for one column from optional to required in a specific content type only, using PnP PowerShell.
I have found Set-PnPField command but not sure how to use this to update properties in a specific content type only. Following is the code that I have written so far:
$FieldName = "<Internal Name of the Field>"
$ListName = "<Name of the List>"
# connect to the portal using client id and client secret key
Connect-PnPOnline -Url <SharePoint Site Collecton URL> -ClientId <Client ID> -ClientSecret <Client Secret Key>
# get the current web
$spWeb = Get-PnPWeb -ErrorAction SilentlyContinue
if($spWeb -ne $null)
{
#Get the Field from List
$Field = Get-PnPField -List $ListName -Identity $FieldName -ErrorAction Stop
#Set the Field Required
$Field.Required = $True
$Field.Update()
$Field.Context.ExecuteQuery()
}
This code is updating the validation for field only at list level. Kindly help me if there is any way to meet the requirement. Thanks in advance.
Below one is working for me - It updates in content type:
# Get Context
$clientContext = Get-PnPContext
# Give target content type name over here
$targetContentType = Get-PnPContentType -Identity "ContentTypeName"
# Load target content type and content type fields
$clientContext.Load($targetContentType)
$clientContext.Load($targetContentType.Fields)
$clientContext.ExecuteQuery()
# Get required field from the target content type
# Mention field internal name or display name over here
$targetField = $targetContentType.Fields.GetByInternalNameOrTitle("TestColumnName")
$clientContext.Load($targetField)
$clientContext.ExecuteQuery()
# Make content type field required
$targetContentType.FieldLinks.GetById($targetField.Id).Required = 1
# Update(UpdateChildren – bool), this value indicates whether the children content type(inheriting from this Content Type) needs to be updated. 0 = False, 1 = True
$targetContentType.Update(0)
$clientContext.ExecuteQuery()
Disconnect-PnPOnline

Adding a PC to a Security Group in AD via Powershell without having to install RSAT

a few weeks ago I started setting up my MDT(Microsoft Deployment Toolkit) custom Image. Nearly everything works fine so far except my recent Powershell script which is meant for adding a computer to a specific security group without RSAT Tools. I tested it on a newly installed OS but I keep on getting the Exception as in the Powershell Exception link shown below. I'm not really into Powershell programming and I tested several scripts to get it to work and I ended up with this one but I think I didn't fully get the hang of it.
Any help/advice or alternative is highly appreciated :).
My Powershell Code:
<#
PowerShell to join computer object to Active Directory Group without AD module being imported
This finds the computer object anywhere in AD and adds it to a security group in a known location
#>
#Get computer name
$ComputerName = gc env:computername
#Check to see if computer is already a member of the group
$isMember = new-object DirectoryServices.DirectorySearcher([ADSI]"NameofMYSecurityGroup")
$ismember.filter = “(&(objectClass=computer)(sAMAccountName= $Computername$)(memberof=CN=Computers,DC=MY_DOMAIN,DC=LOCAL))”
$isMemberResult = $isMember.FindOne()
#If the computer is already a member of the group, just exit.
If ($isMemberResult) {exit}
else
#If the computer is NOT a member of the group, add it.
{
$searcher = new-object DirectoryServices.DirectorySearcher([ADSI]"NameofMYSecurityGroup")
$searcher.filter = “(&(objectClass=computer)(sAMAccountName= $Computername$))”
$FoundComputer = $searcher.FindOne()
$P = $FoundComputer | select path
$ComputerPath = $p.path
$GroupPath = "LDAP://CN=Computers,DC=MY_DOMAIN,DC=LOCAL"
$Group = [ADSI]"$GroupPath"
$Group.Add("$ComputerPath")
$Group.SetInfo()
}
it's german by the way but it basically says:
Exception calling "Add" with 1 Arguments: "Unknown Name. (Exception From HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))
AT F:\"SourcePath"
+ $Group.Add("$ComputerPath")
+CategoryInfo :NotSpecified: (:) [], MethodInvocationException
+FullyQuallifiedErrord :CatchFromBaseAdapterMethodInvoke
Exception Link:
Powershell Exception
Untested, but this may help you in the right direction:
$ComputerName = $env:COMPUTERNAME
$GroupDN = 'CN=Computers,DC=MY_DOMAIN,DC=LOCAL'
# initialize the DirectorySearcher
$root = New-Object System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
$searcher = New-Object System.DirectoryServices.DirectorySearcher($root.defaultNamingContext)
$searcher.SearchScope = 'SubTree'
# Check to see if computer is already a member of the group
$searcher.Filter = "(&(objectCategory=Computer)(objectClass=User)(samaccountname=$ComputerName$)(memberof=$GroupDN))"
$isMember = $searcher.FindOne()
# If the computer is already a member of the group, just exit.
if ($isMember) { exit }
# get the computer object
$searcher.Filter = "(&(objectCategory=Computer)(objectClass=User)(samaccountname=$ComputerName$))"
$ComputerDN = $searcher.FindOne().Properties['distinguishedname']
$ComputerObject = [ADSI]"LDAP://$ComputerDN"
# get the group object
$GroupObject = [ADSI]"LDAP://$GroupDN"
# add the computer to the group
$GroupObject.Add($ComputerObject.AdsPath)
# no need for this $Group.SetInfo()

How to look for members of a group or object with adsi

The company has an AD structure that I need to search for the groupnames where the user is member.
I do know it should be in the "memberof" attribute for the users, let's just say that is not always correct.
I tried the below code to find the username (or objectname) within the "members" attribute for all of the groups within an OU and then bring back the name of the group.
Unfortunately I think I am missing something.
Reverse search (IE: listing the members of a group) is working, but in my case I do not know the name of the groups. Also I need all of the groups, not just a single.
uname ="*anyoldusername*"
$Searcher = [ADSISearcher]"(member=$uname)"
$Searcher.SearchRoot = [ADSI] "LDAP://mydomainsearchroot"
$Searcher.PageSize = 10000
$result = $Searcher.FindAll().Properties.cn
echo $result
This should do it:
$UserName ="TestUser"
$Searcher = [ADSISearcher]""
$Searcher.SearchRoot = [ADSI]"LDAP://mydomainsearchroot"
$Searcher.Filter = "Name=$UserName"
$UserDN = $Searcher.FindOne().properties.distinguishedname
$Searcher.Filter = "(member:1.2.840.113556.1.4.1941:=$UserDN)"
$Searcher.PageSize = 10000
$result = $Searcher.FindAll().Properties.cn
$result
The first search is to find the DN of the user, since that's required for the filter in the next search. To read more about the "1.2.840.113556.1.4.1941" filter see this documentation.
Oh, and echo is an alias for Write-Output in Powershell, better to use that directly or even omit it entirely since a string or variable on it's own will default to Write-Output anyway as you can see when $result is run at the end.

Using Powershell and ADSI to set local passwords

I'm trying to automate setting a bunch of local user accounts' password on a Windows 2008 server. I've tried a few things and this works if I don't use a variable for the username like this:
$user = [adsi]"WinNT://$computer/SomeUserName"
My script block is below... any ideas what I'm doing wrong?
$accounts = Get-Content c:\userlist.txt
$computer = SomeComputerName
$password = "MyPassword"
Foreach($account in $accounts)
{
$user = [adsi]"WinNT://$computer/$account"
$user.SetPassword("$Password")
$user.SetInfo()
}
The error I get when I use the $account variable for the user (from the text file list) is:
The following exception occurred while retrieving member "SetInfo": "The group name could not be found.
Thanks for any help...
It seems that your machine tries to resolve the $account value to a local group name.
You can specify that it is a User object you want, by following the account name with a comma and the string user:
$user = [adsi]"WinNT://$computer/$account,user"

Powershell: How do you set the Read/Write Service Principal Name AD Permissions?

In Powershell, how do you set the Read/Write Service Principal Name AD user permissions?
Normally during my build process, I use ADSIedit to navigate to that object, and then go through all the security tabs to get down to put a checkmark next to:
Read Service Principal Name
Write Service Principal Name
But navigating through ADSIedit can take a long time so I'm trying to script the process. If I have a PowerShell LDAP bind with a new user created, how can I use PowerShell to set both of these properties for this user account?
The following is a hacked out code-snippet of the possible pertinent portions of my install script:
$strDomain = "dc=my,dc=com"
$objDomain = [ADSI] "LDAP://" + strDomain
$strSCCMSQLPW = Read-Host -assecurestring "Please enter a password for the " + $strSCCMSQL + " account: "
New-ADUser -SamAccountName $strSCCMSQL + -Name $strSCCMSQL -AccountPassword $strSCCMSQLPW -Enabled $true -Path $strUsersOU + "," + $strDomain -PasswordNeverExpires $true
You need to add an ActiveDirectoryAccessRule object to the ACL of the target object. For setting property specific rigths the trick is to pass in the schemaIDGUID to the attribute. So first we need to find the schemaIDGUID from the Service-Principal-Name schema entry. In the sample code i statically refer to the Service-Principal-Name, better yet would have been to search for the ldapDisplayname to find the entry but I'm sure you can sort that out. In any case this code should do the job:
Function Set-SpnPermission {
param(
[adsi]$TargetObject,
[Security.Principal.IdentityReference]$Identity,
[switch]$Write,
[switch]$Read
)
if(!$write -and !$read){
throw "Missing either -read or -write"
}
$rootDSE = [adsi]"LDAP://RootDSE"
$schemaDN = $rootDSE.psbase.properties["schemaNamingContext"][0]
$spnDN = "LDAP://CN=Service-Principal-Name,$schemaDN"
$spnEntry = [adsi]$spnDN
$guidArg=#("")
$guidArg[0]=$spnEntry.psbase.Properties["schemaIDGUID"][0]
$spnSecGuid = new-object GUID $guidArg
if($read ){$adRight=[DirectoryServices.ActiveDirectoryRights]"ReadProperty" }
if($write){$adRight=[DirectoryServices.ActiveDirectoryRights]"WriteProperty"}
if($write -and $read){$adRight=[DirectoryServices.ActiveDirectoryRights]"readproperty,writeproperty"}
$accessRuleArgs = $identity,$adRight,"Allow",$spnSecGuid,"None"
$spnAce = new-object DirectoryServices.ActiveDirectoryAccessRule $accessRuleArgs
$TargetObject.psbase.ObjectSecurity.AddAccessRule($spnAce)
$TargetObject.psbase.CommitChanges()
return $spnAce
}
Sample lines for calling the function...
$TargetObject = "LDAP://CN=User,OU=My User Org,DC=domain,DC=net"
$Identity = [security.principal.ntaccount]"domain\user"
Set-SpnPermission -TargetObject $TargetObject -Identity $Identity -write -read
Here is an example using Quest to set the permissions on the service principal name attributes.
First, add Quest:
Add-PSSnapin Quest.ActiveRoles.ADManagement;
Set the permission (using Add-QADPermission):
Get-QADUser UserName | Add-QADPermission -Account 'SELF' -Rights 'ReadProperty,WriteProperty' -Property 'servicePrincipalName' -ApplyTo 'ThisObjectOnly';
You can use Quest AD cmdlets. It makes AD permission stuff very easy in PowerShell.
Read this blog for some examples on how to add AD permissions or even copy the AD permissions.
Just lookup Add-QADPermission and it should do your job.