PowerShell - Adding New User to Selection of AD Groups - powershell

I've created a form to create new AD Accounts. Part of the script determines which groups the new user will be added to based on their role (Doctor, Nurse, Admin or Other) which is captured in the following code in the form of a drop down pick box:
Write-Host "Based on this information" $FFN "has been added to the following Active Directory Groups:"
Write-Host
$ADGroup01 = Get-ADGroup "_XA_App_XenApp" |select -expandproperty name -first 1
Write-Host $ADGroup01
$ADGroup02 = Get-ADGroup "Web Proxy Users" |select -expandproperty name -first 1
Write-Host $ADGroup02
if($RadioButton1.Checked -eq $true)
{
$ADGroup03 = Get-ADGroup "allrot" |select -expandproperty name -first 1
Write-Host $ADGroup03
}
Else
{
$ADGroup03 = Get-ADGroup "alltpo" |select -expandproperty name -first 1
Write-Host $ADGroup03
}
if ($Role -eq "Doctor" -Or $Role -eq "Nurse")
{
$ADGroup04 = Get-ADGroup "PACS Web Access" |select -expandproperty name -first 1
Write-Host $ADGroup04
}
if ($Role -eq "Doctor")
{
$ADGroup05 = Get-ADGroup "CH-MFD" |select -expandproperty name -first 1
Write-Host $ADGroup05
$ADGroup06 = Get-ADGroup "ED-MFP" |select -expandproperty name -first 1
Write-Host $ADGroup06
$ADGroup07 = Get-ADGroup "SU-MFD" |select -expandproperty name -first 1
Write-Host $ADGroup07
}
Write-Host
Further on in the script this piece of code is called during the actual account creation process:
Add-ADPrincipalGroupMembership -Identity $UN -memberof $ADGroup01, $ADGroup02, $ADGroup03, $ADGroup04, $ADGroup05, $ADGroup06, $ADGroup07
The issue I'm facing is that if the user selects Nurse, Admin or Other I get the following error:
"Add-ADPrincipalGroupMembership : Cannot validate argument on parameter 'MemberO
f'. The argument is null, empty, or an element of the argument collection conta
ins a null value. Supply a collection that does not contain any null values and
then try the command again."
I know this is because there are no values being captured in the last $ADGroup[x] and short of creating a bunch of if statements to check if each $ADGroup contains data I'm wondering if there is a more elegant solution.
As always, thank you for taking the time review and happy to provide more information if required.
UPDATE - As per #Martin's advice I've implemented the following code into my script
$UN = "zooz"
$Role = "Nurse"
$Department = "Surgical"
If ($Role -eq "Doctor" -and $Department -eq "Surgical")
{
$ADGroups = #(
"PACS Web Access"
"CH-MFD"
"ED-MFP"
"SU-MFD"
)
}
If ($Role -eq "Nurse" -and $Department -eq "Surgical")
{
$ADGroups = #(
"_XA_App_XenApp"
"Web Proxy Users"
"allrot"
)
}
for ($i=0; $i -lt $ADGroups.length; $i++) {
Add-ADPrincipalGroupMembership -Identity $UN -memberof $adgroups[$i]
}

Make an object $adgroups and add your desired groups to it.
$adgroups = #()
At the end use a foreach Loop:
$adgroups | Add-ADPrincipalGroupMembership -Identity $UN or (weather or not the cmdlet likes pipelined Input)
$adgroups | % { Add-ADPrincipalGroupMembership -Identity $UN -memberof $_ }

Related

Get-ADUser - Filter child OU's and users where surname is empty

I am trying to run a command where I get all active directory users in the parent OU (Users) and filter out the child OU's (Admin accounts, service accounts, disabled accounts) as well as filter out any user account that does not have a surname in the surname field.
At the moment I have
Get-ADUser -Filter{enabled -eq $true} -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' | Where-Object { $_.DistinguishedName -notlike "*,$Disabled" } | Where {$_.Surname -notlike "$Null"} | select samAccountName
When I add another child OU after 'Disabled' there is an error
Where-Object : A positional parameter cannot be found that accepts argument 'Where'.
Please may someone advise on how to filter out additional child OU's?
Good day Smoore
The problem is you are using multiple Where-object cmdlets but you only need one and separate them using () and adding the -and option, also to refer to $null value you don't need to use the "" marks
Get-ADUser -Filter {Enabled -eq $true} -SearchBase "OU=Users,OU=Company,DC=CompanyName,DC=local" | Where-Object {($_.DistinguishedName -notlike "*,$Disabled*") -and ($_.Surname -notlike $Null)} | select samAccountName
With this options you should be able to get all the users you want
Have a nice day!
I would use a regex -notmatch so it would be possible to combine all OU Distinguished names in just one variable.
Something like this:
$Admins = 'OU=Administrators,OU=Company,DC=CompanyName,DC=local'
$Service = 'OU=ServiceAccounts,OU=Company,DC=CompanyName,DC=local'
$Disabled = 'OU=DisabledUsers,OU=Company,DC=CompanyName,DC=local'
# build a regex string from the above OU DistinguishedNames
$Exclude = '({0}|{1}|{2})$' -f [regex]::Escape($Admins), [regex]::Escape($Service), [regex]::Escape($Disabled)
Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' |
Where-Object { ![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude } |
Select-Object SamAccountName
As per your comment:
$Admins = 'OU=Administrators,OU=Company,DC=CompanyName,DC=local'
$Service = 'OU=ServiceAccounts,OU=Company,DC=CompanyName,DC=local'
$Disabled = 'OU=DisabledUsers,OU=Company,DC=CompanyName,DC=local'
# the group you want to add the users to
$TargetGroup = 'Company Team'
# build a regex string from the above OU DistinguishedNames
$Exclude = '({0}|{1}|{2})$' -f [regex]::Escape($Admins), [regex]::Escape($Service), [regex]::Escape($Disabled)
$users = Get-ADUser -Filter 'Enabled -eq $true' -SearchBase 'OU=Users,OU=Company,DC=CompanyName,DC=local' |
Where-Object { ![string]::IsNullOrWhiteSpace($_.Surname) -and $_.DistinguishedName -notmatch $Exclude }
# get the AD group as object
$GroupObject = Get-ADGroup -Filter "Name -eq '$TargetGroup'"
# now add these users that have Surnames to the security group all in one go
try {
Write-Host "Adding $(#($users).Count) users to group $TargetGroup"
$GroupObject | Add-ADGroupMember -Members $users -ErrorAction Stop -Verbose
}
catch {
Write-Warning "Error: $($_.Exception.Message)"
}
# or if you prefer loop through the users and add each one individually then use this instead
# foreach ($user in $users) {
# try {
# Write-Host "Adding user $($users.Name) to group $TargetGroup"
# $GroupObject | Add-ADGroupMember -Members $user -ErrorAction Stop -Verbose
# }
# catch {
# Write-Warning "Error adding user $($users.Name) to group $($TargetGroup): $($_.Exception.Message)"
# }
# }

How to list users with logonhours denied

I need a list of users with the logonhours set to denied. I found another question (68558481) that partially got me there but I seem to be doing something wrong when trying to loop through my group.
$userToFind = Get-ADGroupMember -identity "AD group" | Sort-Object samAccountName | Select SamAccountName
# try and find the user also gathering its LogonHours property
Foreach ($username in $userToFind){
$user = Get-ADUser -Filter "SamAccountName -eq '$username'" -Properties LogonHours -ErrorAction SilentlyContinue
if ($user) {
# test if the property has been set. If not set, the user is allowed to login anytime of the week
if ($null -ne $user.LogonHours -and #($user.LogonHours).Count) {
# initialize a variable
$loginAllowed = $false
# loop through the 21 bytes and exit the loop if we found a non-zero byte
foreach ($byte in $user.LogonHours) {
if ($byte -ne 0) {
$loginAllowed = $true # set the flag to $true
break # and exit the loop
}
}
if (!$loginAllowed) {
"User $username - Login disabled"
}
}
}
else {
Write-Warning "User $username does not exist.."
}
}
My results for this is all users do not exist. Where am I going wrong?
|
The main issue is that $userToFind is an object or array of objects which's property is SamAccountName, so when you use it in your filter "SamAccountName -eq '$username'", the result is the stringification of each object:
$username = [pscustomobject]#{
samAccountName = 'someuser'
}
"SamAccountName -eq '$username'" # => SamAccountName -eq '#{samAccountName=someuser}'
What you want to do instead is get the value of each object, a string or array of strings in this case:
$username = [pscustomobject]#{
samAccountName = 'someuser'
} | Select-Object -ExpandProperty samAccountName
"SamAccountName -eq '$username'" # => SamAccountName -eq 'someuser'
You can also use member-access enumeration instead of Select-Object, so in your code it would be:
$userToFind = (Get-ADGroupMember -Identity "AD group" | Sort-Object samAccountName).SamAccountName
As for the current code, you could make an improvement by only searching for users member of the group which's logonHours attribute is populated. That way, there is no need to check if the user has the attribute set and no need to check if the user was found or not.
# get the DN of the group
$group = (Get-ADGroup -Identity "AD group").DistinguishedName
$param = #{
LDAPFilter = "(&(memberof=$group)(logonhours=*))"
Properties = "logonHours"
}
# enumerate all users members of this group which's attribute `LogonHours` is set
foreach($user in Get-ADUser #param) {
$loginAllowed = $false
foreach($byte in $user.LogonHours) {
if ($byte -ne 0) {
$loginAllowed = $true
break
}
}
if (-not $loginAllowed) {
"User {0} - Login disabled" -f $user.SamAccountName
}
}

Command to check specific user is a part of certain group or not

List all users that have mailboxes but are not in a group called Metalogix*. I need a PowerShell script that will check whether specific user is a part of certain group or not and if the user is part of any of those groups.
I already have working script:
Import-Module ActiveDirectory
$Users = Get-Mailbox -ResultSize "unlimited"
$Group = "Metalogix*"
foreach ($user in $Users) {
$Check = Get-ADPrincipalGroupMembership -Identity $User.sAMAccountName |
? { $_.Name -like $Group }
if ($Check -eq $null) {
Write-Output "$User.sAMAccountName is NOT part of this group"
} else {
$Results = Get-Mailbox -Identity $User.sAMAccountName |
select Name, sAMAccountName, PrimarySmtpAddress, Database |
Export-csv "c:\results1.csv" -NTI -Append
}
}
But script doesn't list groups recursively, e.g tester4-6 are members of 'Test Group 2', which is a member of 'Test Group 1'. The rest are direct. Just I can see direct membership, not recursive membership.
2nd question : I want to get all users with samaccountname that begins with "STR" prefix.
Test Group 1
tester1
tester2
-> Test Group 2
tester4
tester6
I'd probably use a recursive function. Something like this:
function Test-GroupMembership {
Param(
[Parameter(Mandatory=$true)]
[string]$Identity,
[Parameter(Mandatory=$true)]
[string]$Name
)
$groups = Get-ADPrincipalGroupMembership -Identity $Identity
if ($groups | Where-Object { $_.Name -like $Name }) {
return $true
} elseif ($groups -ne $null) {
foreach ($g in $groups) {
if (Test-GroupMembership -Identity $g -Name $Name) {
return $true
}
}
}
return $false
}
Get-ADPrincipalGroupMembership isn't recursive, but Get-ADGroupMember is.
$Users = Get-Mailbox -ResultSize "unlimited"
$Group = 'Metalogix*'
$GroupMembers = Get-ADGroupMember -Identity $Group | Get-ADGroupMember -Recursive | Select-Object -ExpandProperty samAccountName
foreach ($User in $Users) {
if ($User -in $GroupMembers) {
Write-Output "User $User is in group $Group."
}
else {
Write-Output "User $User is not in group $Group."
}
}
This is also more efficient because you're only fetching group membership once.
I'm away from my servers, so treat the above as pseudocode.

Export nested groups a contact is a memberOf

I'm using Exchange 2010 and Powershell.
I'm looking to export all 'nested' distribution groups that a exchange contact is a part of.
For example, if a contact is a memberOf two DG, A and B. And group A is also a memberOf Group C. I'd like a list the show all three groups.
Group C
----|-----------|
Group A Group B
|
Contact
Here is my very noob attempt at this. I guess it needs to be done recursively?
$contact = get-contact email#domain.com.au
$members = Get-ADObject -Identity $contact.Guid -Properties 'MemberOf'
foreach ($group in $members.MemberOf) {
foreach ($_ in $group.memberof ){
get-distributiongroup $_
}
}
Must be able to do this for a 'contact', not a user.
Thanks in advance!
You don't really need Exchange to get distribution groups.
Here's my example to retrieve names of groups assuming your contact is AD user with mail property filled:
function Get-GroupsRec
{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
$Identity
)
BEGIN {}
PROCESS{
if($Identity -eq $null){return}
Write-Output $Identity | select -ExpandProperty samaccountname
$Identity | Get-ADPrincipalGroupMembership | ?{$_.GroupCategory -eq "Distribution"} | Get-GroupsRec}
END{}
}
Get-ADUser -Filter {mail -eq 'email#domain.com.au'} | Get-ADPrincipalGroupMembership | ?{$_.GroupCategory -eq "Distribution"} | Get-GroupsRec
But as long as you can retrieve AD user, this solution is valid.
UPDATE:
Version basing on Get-ADObject only. (Same structure, only different selectors. Left ObjectClass in filter for readability):
function Get-GroupsRec
{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
$Identity
)
BEGIN {}
PROCESS{
if($Identity -eq $null){return}
Write-Output $Identity | select -ExpandProperty Name
$Identity | select -ExpandProperty MemberOf | Get-ADObject -Properties GroupType,MemberOf |?{$_.GroupType -gt 0 -and $_.ObjectClass -eq 'group'} | Get-GroupsRec }
END{}
}
Get-ADObject -Filter {mail -eq 'email#domain.com.au'} -Properties MemberOf | select -ExpandProperty MemberOf | Get-ADObject -Properties GroupType,MemberOf |?{$_.GroupType -gt 0 -and $_.ObjectClass -eq 'group'} | Get-GroupsRec
If you want restrict group type to a specific type, you may modify GroupType in code to any value with -band operator. The enumerator values are available at: https://msdn.microsoft.com/en-us/library/aa772263(v=vs.85).aspx
You are on the right track. You indeed need recursion for this. I quickly put something together which should recusively resvolves membership. Hope this helps!
Function Get-Groups {
Param(
[string]$Identity
)
$members = Get-ADObject -Identity $Identity -Properties "MemberOf"
$members.MemberOf | % {
if($(Get-ADObject $_ -Properties "GroupType").grouptype -gt 0) {
Write-Host $_
}
Get-Nestedmember $_ "->"
}
}
Function Get-Nestedmember {
Param(
[String]$Identity,
[string]$Depth
)
$members = (Get-ADobject -Identity $Identity -Properties "MemberOf").memberof
$count = $members | measure
if($count -ne 0) {
$members | % {
if($(Get-ADObject $_ -Properties "GroupType").grouptype -gt 0) {
Write-host "$Depth $_"
}
Get-Nestedmember $_ "-$Depth"
}
}
}
Get-Groups -Identity '<Your Identity goes here>'
It gets a MemberOf relationships and does that again for the resulting set. If MemberOf returns 0 that means there are no more MemberOf relationships so we stop.

Find out if a Security Account Manager (SAM) name is a user or a group

edited from original question because the real problem was something unrelated to the question
I got a list of trustees from NTFS permissions and now I want to expand the groups to show membership. If I have a SAM name like MyDomain\name, there's no indication of whether that is a group or not. The Get-ADobject command has an ObjectClass property which will indicate group or user if this is an Active Directory domain object. One can use:
Get-ADObject -filter 'SamAccountName -eq "My Users"' or
$sam = "My Users"
Get-ADObject -filter 'SamAccountName -eq $sam'
Thanks to JPBlanc who had an alternate form of writing that with a script block and some other suggestions.
And thanks, user2142466. That looks like a good suggestion for my original script.
You can use a variavle using :
$sam = "My Users"
Get-ADObject -Filter {(SamAccountName -eq $sam)}
But I agree that using vars in -Filter sometimes results in strange behaviours with vars (see this question), so I prefer to use -LDAPFilter.
Get-ADObject -LDAPFilter "(SamAccountName =$user)"
Be careful the -LDAPFilter use polish notation for the filter, it's a bit disconcerting at the begining, but here, it's the natural way of filtering using the underlaying protocol LDAP.
You can get more information about this syntax in Search Filter Syntax, you can also get corresponding filters in About_ActiveDirectory_Filter.
I am guessing you are getting an array of trustees. (i.e User,Group,user,user,Group). So if you get a group then you want to pull the members from it too?
So I would look to see if it is a group, like how you are doing first and then pulling those members out of it. Add it to an another array which will contain every single user for your NTFS permissions.
$arraytrustees
#Create a blank Array
$NTFSUsers =#()
for each ($object in $arraytrustees){
$ObjectClass = (Get-ADObject -filter {SamAccountName -eq $object}).ObjectClass
If ($ObjectClass -eq "group"){
$AdGroupUsers = (Get-ADGroupMember -identity $object).SamAccountName
$NTFSUsers = $NTFSUsers + $AdGroupUsers
}else{
$NTFSUsers = $NTFSUsers + $ojbect
}
}
I was asked to list all members of the groups, along with their ID, Name, and Description as well, so I added a couple of lines.
cls
$Users = #()
$Groups = #()
$list = Get-Content z:\pcm2.txt
Foreach ($o in $list)
{
$ObjectClass = (Get-ADObject -Filter {SamAccountName -eq $o}).ObjectClass
If ($ObjectClass -eq "User")
{
$U = Get-ADUser -Properties * -Identity $o
$User = "" | Select FullUserName, LoginID, Description
$User.FullUserName = $U.DisplayName
$User.LoginID = $U.SamAccountName
$User.Description = $U.description
$Users += $User
}
Else
{
If ($ObjectClass -eq "Group")
{
$G = Get-ADGroup -Properties * -Identity $o
$GM = Get-ADGroupMember -Identity $G.name -Recursive | Get-ADUser -Properties *
Foreach ($gmember in $GM)
{
$Group = "" | Select GroupName, GroupDescription, GroupMemberName, GroupMemberLoginID, GroupMemberDesc
$Group.GroupName = $G.Name
$Group.GroupDescription = $G.Description
$Group.GroupMemberName = $gmember.Name
$Group.GroupMemberLoginID = $gmember.SamAccountName
$Group.GroupMemberDesc = $gmember.Description
$Groups += $Group
}
}
}
}
$Users | Export-Csv z:\PCMUsers.csv -NoTypeInformation
$Groups | Export-Csv z:\PCMGroups.csv -NoTypeInformation
I received a list and was asked to determine whether the objects were users or group, and I came up with this. It worked!
cls
$Users = #()
$Groups = #()
$list = Get-Content z:\pcm.txt
Foreach ($o in $list)
{
$ObjectClass = (Get-ADObject -Filter {SamAccountName -eq $o}).ObjectClass
If ($ObjectClass -eq "User")
{
$U = Get-ADUser -Properties * -Identity $o
$User = "" | Select FullUserName, LoginID, Description
$User.FullUserName = $U.DisplayName
$User.LoginID = $U.SamAccountName
$User.Description = $U.description
$Users += $User
}
Else
{
If ($ObjectClass -eq "Group")
{
$G = Get-ADGroup -Properties * -Identity $o
$Group = "" | Select GroupName, Description
$Group.GroupName = $G.Name
$Group.Description = $G.Description
$Groups += $Group
}
}
}
$Users | Export-Csv z:\Users.csv -NoTypeInformation
$Groups | Export-Csv z:\Groups.csv -NoTypeInformation