Security Accounts Manager attributes - powershell

I would like to create user in AD using the attributes defined for other user from the same OU. But I do have issue with SAM protected items.
For do that I am creating an instance of user already defined in AD with all the properties. After I am using New-AdUser command to create a new user using the created instance. However in the properties there are elements which are managed by Security Accounts Manager - I tried to find which parameters belong to SAM but with no results. Can anyone help me to determinate the parameters I am able to copy acctualy. So I can define which parameters I would like to copy form the created instance.
PS C:\Users\xxx> $userInstance = Get-ADUser $accountIdentifier -properties *
PS C:\Users\xxx> New-ADUser -GivenName "John" -Instance $userInstance -Surname "Smith" -Title "Salesman" -EmailAddress "John.Smith#yahoo.com" -UserPrincipalName smithj#yahoo.com -Name "John Smith"
As a reslut I have the folowing errro message:
New-ADUser : Access to the attribute is not permitted because the attribute is owned by the Security Accounts Manager (SAM)

You can use the following to determine which attributes can be copied:
$searchBase = "CN=Schema,$((Get-ADRootDSE).configurationNamingContext)"
$Attributes = Get-ADObject -SearchBase $searchBase -Filter * -Properties searchflags,ldapdisplayname |
Where-Object {$_.SearchFlags -band 16} | Select ldapdisplayname
$Attributes
Then you can use the attributes listed in the output as a guide for what you feed into the -Properties parameter of the New-ADUser command.
Essentially, this goes through every schema attribute in AD and returns the attributes where the searchflags attribute has the 16 decimal bit turned on. Depending on your display, you may see this as a hex representation (0x00000010). You cannot just rely on the value of 16 because if other flags are turned on, that value will change if other bits are turned on. The decimal values for the bits are summed. For this reason, we use the -band (bitwise and) operator. You can read more about the Search-Flags attribute here.

Related

Add AD user to group when creating the user?

I've seen multiple examples on adding a user to a group after creation, but not at the time of creation. Is that possible? Currently, I have something like this: (most attributes removed for simplicity)
$user = New-ADUser -Name "person" -Path "OU=test,OU=myorg" -Office "home" -samAccountName "snuffy.john" -PassThru
if ($user){
Add-ADGroupMember -Identity mygroup -Members $user.samAccountName
}
This causes two calls to the ldap server for each user added and I'm trying to prevent that as I have many thousands of users and the script takes a long time to run. I've checked MS docs but didn't see anything. If it's not possible, it is what it is. Thought I'd try asking at least. I also just started using powershell last week.
You may turn your thinking. with thousands of users I would do it like this.
First create all users.
Then get them by Get-ADUser -Filter * -SearchBase "OU=test,OU=myorg" (or maybe Filter the CreatedDate Attribute to get all new users)
After getting the users try to filter them for the groups you want to put them into and use the Add-ADGroupMember cmdlet, which accepts an array of ADPrincipals for parameter "-members".
This will speed up your code.

how to take users off ad groups user is part of

We are trying to take user off all ad groups when user is termed in HR Database. I have the termination of user account figured out but how can we take that specific user our of all assigned group using powershell.
You will want to retrieve the ADUser object before deleting it from ActiveDirectory, examine its .MemberOf property, and then run through those groups with the Remove-ADGroupMember cmdlet.
To get you started you need to get the user's memberOf and the user's distinguishedName
In the following example I am getting the user by their logon name (samaccountname) You can use whatever attribute you want as long as it returns the correct user:
$testUser = "Test User"
$user = Get-ADUser -filter {Samaccountname -eq $testUser} -Properties memberof, distinguishedName
$Groups = $user.MemberOf
$DN = $user.DistinguishedName
Then in order to remove the user from their current membership, you can just put it in a foreach:
foreach($group in $groups)
{
Remove-ADGroupMember -Members $DN -Identity $group -Confirm:$false
}
The -Confirm:$false is to suppress the warning about removal. You might want to remove that part during testing
Many will tell you to look at the user's memberOf attribute. That will work just fine in most cases.
However, memberOf only shows groups with a scope of 'Universal' on any domain in the forest, or 'Global' groups on the same domain. It will not show groups with a 'Domain Local' scope (regardless of domain), or 'Global' groups on other domains.
To guarantee you find all groups the user is a member of, you need to search every domain in your forest for groups that the user is a member of:
Import-Module ActiveDirectory
$user = Get-ADUser "theuser"
$domains = (Get-ADForest).Domains
$groups = New-Object System.Collections.ArrayList
foreach ($domain in $domains) {
$groups.AddRange(#(Get-ADGroup -filter {member -eq $user.DistinguishedName} -Server $domain))
}
Then $groups has the list of groups, and you can use Remove-ADGroupMember to remove the user from those groups.
Again, this is only relevant to you if you either:
Have more than one domain in your forest, and/or
Use 'Domain Local' groups

Need to validate user input (domain user,group) and fetch detail

When I supply a string and need to extract the domain user object (name, surname, manager name) I get the desired detail through following code.
$groupdetail : gc d:\domainobject.txt
$output = Get-ADUser $GroupDetail
$output | Select Name, GivenName,SurName, #{label="Manager";expression={(Get-ADUser $_.Manager -Properties DisplayName).Displayname}}
Next thing is validate of the input if it is a domain group then extract the group member names then get the user object information again as above. The problem is I am unable to validate if the string is a group.
$groupname = Get-content D:\domainobject.txt
foreach ($group in $groupname){
$groupname = get-adgroup $group
$groupmember = Get-ADGroupMember $groupname | Format-Table Name, SamAccountName -AutoSize
foreach ($groupdetail in $groupmember){
$groupdoutput = get-aduser $groupdetail
$groupoutput | Select-Object Name, GivenName,SurName, #{label="Manager";expression={(Get-ADUser $_.Manager -Properties DisplayName).Displayname}}
}
Write-Host $groupoutput
}
Both condition should run in one code so if the input string is a domain user get the information and exit. Incase string is a domain group it will loop in get the group member name then extract the domain user information. One way I thought is to run this condition $groupname.objectclass -eq "group" or $groupname.objectclass -eq "name" so that I need to convert the input string to PowerShell object.
I tried a few things but that did not work. Please suggest what are the possible way I can achieve this.
You could always use a try-catch block
try{$group = get-adgroup $groupname}
catch{$user = get-aduser $groupname}
if($group)
{write-host "It's a group!"}
else
{Write-host "It's a user!"}
That will tell you if it's a group or a user. Just replace the write-host with your logic.
Usually when doing this sort of thing, I want one of two things:
In the first case, if I want the groups that a user is a member of directly regardless of nesting, then I specify:
Get-AdUser -Identity 'Alice' -Properties MemberOf
This will return the MemberOf property with the user, which is a string array that in each element includes the distinguished name of a group the user is a direct member of. Depending on exactly what you're doing, it may make sense to fetch all groups from AD at once to get the group details en masse, and then do a lookup for each MemberOf.
In the second case, I only care about effective group membership of user accounts. I will want Get-AdGroupMember to resolve the nested groups into the resulting set of users. In other words, if I run Get-AdGroupMember -Identity 'Foo', and the members are user Alice and group Bar, and user Bob is a member of group Bar, then I want the cmdlet to return Alice and Bob. I don't care that Bar is the reason that Bob is in Foo. To do that, I run:
Get-AdGroupMember -Identity 'Foo' -Recurse

LDAP filter syntax to compare two object's properties

I want to know if this is possible to compare two object's properties with the LDAPfilter ?
Something like (This is not working - return nothing every time): -LDAPfilter {sAMAccountName=userPrincipalName}
I tried to find a clue in this Microsoft's documentation about the LDAPfilter, but I found nothing.
Some explanations about my goal :
I want to get every user with the User logon name different than the User logon name (Pre Windows 2000).
I am using the command "Get-ADUser"
The two properties I want to compare are : "User logon name" (userPrincipalName) and "User logon name (Pre Windows 2000)" (sAMAccountName)
I don't know if this is possible with the LDAP filter, if not, is there an other way to do it ?
No, it's not possible with an LDAP filter. You can only compare an attribute with a value, not two attributes with each other. You need something like this for the latter:
Get-ADUser -Filter * -Properties * |
? { $_.SamAccountName -eq $_.UserPrincipalName }
Note that these two properties are practically guaranteed to be different, because the UPN normally includes the FQDN of the domain whereas the sAMAccountName does not. Your comparison will effectively look somewhat like this:
'user' -eq 'user#domain.example.com'
so you may want to do something like this instead:
Get-ADUser -Filter * -Properties * |
? { "$($_.SamAccountName)#$env:USERDNSDOMAIN" -eq $_.UserPrincipalName }

How to Modify Custom Attribute X of all users/groups in an OU?

I need to change Custom Attribute 1 and 2 for ~500 mailboxes in Exchange.
The user accounts linked with mailboxes are spread over 10-15 OU's within AD and each different OU needed different custom attributes.
Ideally, I dont want to run the following command twice for each mailbox
Set-Mailbox user#domain.com -CustomAttribute1 "X"
SUDO
Get a list of all users, email groups, contacts, rooms in a given OU in AD
Change each Custom attribute 1 to X
Change each Custom attribute 2 to X
Use an LDAP filter:
(|
(objectCategory=person)
(&
(objectCategory=group)
(!
(groupType:1.2.840.113556.1.4.803:=2147483648)
)
)
(msExchResourceMetaData=ResourceType:Room)
)
The above matches the following object types:
users and contacts: (objectCategory=person)
distribution groups: (&(objectCategory=group)(!(groupType:1.2.840.113556.1.4.803:=2147483648))) (technically this means: groups that are not security groups)
room resources: (msExchResourceMetaData=ResourceType:Room)
You can select the AD objects matching that filter with Get-ADObject and modify their properties with Set-ADObject:
$ou = 'OU=some unit,DC=example,DC=com'
$fltr = '(|(objectCategory=person)' +
'(&(objectCategory=group)' +
'(!(groupType:1.2.840.113556.1.4.803:=2147483648)))' +
'(msExchResourceMetaData=ResourceType:Room))'
Get-ADObject -LDAPFilter $fltr -SearchBase $ou -SearchScope Subtree |
Set-ADObject -Replace #{
'extensionAttribute1' = 'X'
'extensionAttribute2' = 'X'
}
I'm not entirely sure about the attribute names, since I don't have an Exchange at hand. You must use their LDAP names here, not any fancy alias.