powershell script add-adgroupmember - powershell

I'm writing a script which is supposed to show me security groups by matching an input e.g. 'marketing'.
Afterwards I want to add a user to this security group. Since the exchange-powershell can search for user via -anr it's much easier to find the right person.
Here is the part of my script:
$grparray = get-adgroup -filter * | where { $_.name -match "marketing" -and $_.GroupCategory -eq 'Security' }
$potentarray = get-mailbox -anr Julia | select SamAccoutName
$grparray[1] | add-adgroupmember -members $potentarray[1]
But I get the error:
CannotConvertArgumentNoMessage,Microsoft.AcitveDirectory.Management.Commands.AddAdGroupMember
Seems like the ad-modules can't handle the Exchange input.
Does anyone know how I can solve this issue, or got another idea how to?

Ambiguous Name Resolution is available with Get-ADUser, this is preferable over Get-Mailbox as it returns an AD Object which can be used as an input for Add-ADGroupmember.
Try $potentarray = Get-ADUser -LDAPFilter "(anr=Julia)" instead of Get-Mailbox.

Related

Powershell AD user group member

Is there any simple way to just filter user group member like this:
$abcgroup = (Get-ADUser -Identity username –Properties MemberOf) | where {$_.MemberOf -like "*ABC*"}| Select-Object -ExpandProperty MemberOf | FT MemberOf -AutoSize
And return user group just the ABC-XYZ instead of every single group as output, otherwise any easy method to process all the group name and just extract the any group name start with ABC-*
Thanks
I would make it a little bit simpler, both in server and local processing:
Get-ADGroup -LDAPFilter "(&(member=$((Get-ADUser username).distinguishedName))(sAMAccountName=abc-*))"
This would get all the groups that include selected user and their name matches the pattern. This would only include two LDAP requests (one for getting user DN, one for getting all the groups). All the selection will be done on the server and only interesting values will be returned, meaning less data transfer and less post-processing (i.e. filtering) on the client side.
Untested, but this might work:
$abcgroup = (Get-ADUser -Identity username –Properties MemberOf).MemberOf |
Where-Object {$_ -match '^cn=ABC-'} | ForEach-Object {(Get-ADGroup -Identity $_).Name}
$abcgroup | Format-Table

How to move multiple users to multiple OUs importing users from CSV and filtering by department

New to powershell and scripting in general. Trying to improve automation in our onboarding process, we have to move multiple user accounts to multiple OUs every couple of months.
Import-Module ActiveDirectory
$dept1 = "OU=Path1,DC=SOMEWHERE,DC=OUTTHERE"
$dept2 = "OU=Path2,DC=SOMEWHERE,DC=OUTTHERE"
Import-Csv "C:\Scripts\Incoming.csv" | ForEach-Object {
$samAccountName = $_."samAccountName"
Get-ADUser -Identity $samAccountName -Filter {Department -eq "Dept1"} | Move-ADObject -TargetPath $dept1
Get-ADUser -Identity $samAccountName -Filter {Department -eq "Dept2"} | Move-ADObject -TargetPath $dept2
}
This actually moves ALL users with the department marked into the path I have set.. but I only want it to look at those users in the csv and then filter their departments from AD - not the CSV. I feel like I'm missing a step but I've searched everywhere and tried the get-help. I feel like I need to get the identity, then search/filter against something else but I'm not quite sure how. Would appreciate any help.
edit
Okay, if I run the following:
Get-ADUser -Filter {Department -eq "Dept1"} -Properties Department
It returns everyone that fits that property but how do I compare those to the $samAccountName and ONLY try to move those accounts or run the commands against the accounts on the list? When I ran the second half of the command it tried to move them all and failed.
Move-ADObject $samAccountName -Target $dept1
I feel dumb.
It's ok to feel dumb. You're not and everyone feels that way at times when trying to learn a new thing. You're also here asking for help, so you're ahead of the game compared to a lot of others.
#Lee_Daily's comment is correct that Get-ADUser doesn't support using both -Identity and -Filter in the same command. They're part of different parameter sets. You can tell from the syntax output of Get-Help Get-ADUser or the online docs. Both show 3 different sets of parameters and Identity and Filter are not in the same one. What's odd is that your original script should have thrown an error because you tried to use both in the same command. No need to worry about that now though.
Here's a typical way one might approach this task. First, you query the user's details including the department you want to make a decision on. Then, you write your condition and perform the appropriate action. Doing it this way means you're only querying AD once for each user in your CSV rather than twice like your original script which is good for script performance and load on your AD. The inside of your ForEach-Object loop might look something like this. Note the addition of -Properties department in Get-ADUser. We need to ask for it explicitly because department isn't returned in the default result set.
# all of this goes inside your existing ForEach-Object loop
$u = Get-ADUser -Identity $_.samAccountName -Properties department
if ($u.Department -eq 'Dept1') {
$u | Move-ADObject -TargetPath $dept1
} elseif ($u.Department -eq 'Dept2') {
$u | Move-ADObject -TargetPath $dept2
}
Now let's talk about some alternative ways you might approach this.
The first way sort of flips things around so you end up only calling Get-ADUser once total, but end up doing a lot more filtering/processing on the client side. It's not my favorite, but it sets things up to understand my preferred solution. In particular, the Get-ADUser call uses the -LDAPFilter parameter. LDAP filter syntax is a little strange if you've never seen it before and this particular example could use the more common -Filter syntax just as easily. But in the next example it would be much more difficult and learning LDAP filter syntax enables you to query AD from anything rather than just PowerShell.
# instead of immediately looping on the CSV we imported, save it to a variable
$incoming = Import-Csv "C:\Scripts\Incoming.csv"
# then we make a single AD query for all users in either Dept1 or Dept2
$users = Get-ADUser -LDAPFilter '(|(department=Dept1)(department=Dept2))' -Properties department
# now we filter the set of users from AD by department and whether they're in the CSV and do the moves as appropriate
$users | Where-Object { $_.department -eq 'Dept1' -and
$_.samAccountName -in $incoming.samAccountName } | Move-ADObject -TargetPath $dept1
$users | Where-Object { $_.department -eq 'Dept2' -and
$_.samAccountName -in $incoming.samAccountName } | Move-ADObject -TargetPath $dept2
The benefit of this method is the single AD round trip for users rather than one for each in the CSV. But there are a lot more local loops checking the samAccountNames in the results with the samAccountNames from the CSV which can get expensive cpu-wise if your CSV and/or AD is huge.
The final example tweaks the previous example by expanding our LDAP filter and making AD do more of the work. AD is ridiculously good at returning LDAP query results. It's been fine-tuned over decades to do exactly that. So we should take advantange of it whenever possible.
Essentially what we're going to do is create a giant 'OR' filter out of the samAccountNames from the CSV so that when we get our results, the only check we have to do is the check for department. The way I verbalize this query in my head is that we're asking AD to "Return all users where SamAccountName is A or B or C or D, etc and Department is Dept1 or Dept2. The general form of the filter will look like this (spaces included for readability).
(& <SAM FILTER> <DEPT FILTER> )
# Where <DEPT FILTER> is copied from the previous example and
# <SAM FILTER> is similar but for each entry in the CSV like this
(|(samAccountName=a)(samAccountName=b)(samAccountName=c)...)
So let's see it in action.
# save our CSV to a variable like before
$incoming = Import-Csv "C:\Scripts\Incoming.csv"
# build the SAM FILTER
$samInner = $incoming.samAccountName -join ')(samAccountName='
$samFilter = "(|(samAccountName=$samInner))"
# build the DEPT FILTER
$deptFilter = '(|(department=Dept1)(department=Dept2))'
# combine the two with an LDAP "AND"
$ldapFilter = "(&$($samFilter)$($deptFilter))"
# now make our single AD query using the final filter
$users = Get-ADUser -LDAPFilter $ldapFilter -Properties department
# and finally filter and move the users based on department
$users | Where-Object { $_.department -eq 'Dept1' } | Move-ADObject -TargetPath $dept1
$users | Where-Object { $_.department -eq 'Dept2' } | Move-ADObject -TargetPath $dept2
There are more efficient ways to build the LDAP filter string, but I wanted to keep things simple for readability. It's also a lot easier to read with better PowerShell syntax highlighting than StackOverflow's. But hopefully you get the gist.
The only limitation with using this method is when your incoming CSV file is huge. There's a maximum size that your LDAP filter can be. Though I'm not sure what it is and I've never personally reached it with roughly ~4000 users in the filter. But even if you have to split up your incoming CSV file into batches of a few thousand users, it's still likely to be more efficient than the other examples.

How to filter out which users are allowed to log in to a computer?

I am needing to parse through user information to find which computers a specific user has access to, and then filter that out to generate txt docs for each computer listing the allowed users for that machine. However, my script isn't returning expected results and is creating incomplete lists.
Get-Content c:\temp\computers.txt | ForEach-Object {
$computername = $_
Get-ADUser -Filter "LogonWorkstations -like '*$computername'" -Properties LogonWorkstations |
Format-Table SamAccountName, Enabled |
Out-File -FilePath c:\temp\Accounts\"$computername-$fileDate".txt
}
I am fairly certain the issue lies in my filtering, because some of the files are returning info, however only ones where the username matches the computer name in some regard. Rather than listing users whose "LogonWorkstation" includes said computer, which is what I am looking to do. (If I pull a user's "LogonWorkstation" separately, that information is correct.)
I believe the issue is that the logonworkstations property stores the list of computers as a string rather than a collection. Since the -Filter parameter has limited operators, you will need to use -like in order to introduce wildcards. Then you can use whatever method to build your computer name string to include surrounding asterisks.
Get-Content c:\temp\computers.txt |
ForEach-Object {
Get-ADUser -Filter "LogonWorkstations -like '*$_*'" -Properties LogonWorkstations |
Format-Table SamAccountName, Enabled |
Out-File -FilePath c:\temp\Accounts\"$_-$fileDate".txt
}

GET not printing when there is another GET after it?

I've gt this script to automate removal of users for our workplace and I can't figure out why this Get doesn't print anything if there is another get after it. Is this a delay issue? or there a problem with my syntax"
#Requests user input username
$_Name=Read-Host "Enter account name you wish to disable"
#Lists the users AD groups and removes them
Get-ADPrincipalGroupMembership $_Name | select name
Get-ADUser -Identity $_Name -Properties MemberOf -Credential $_Creds| ForEach-Object {
$_.MemberOf | Remove-ADGroupMember -Members $_.DistinguishedName -Credential $_Creds -Confirm:$false
}
write-host "User has been removed from the listed groups..."
It just returns a blank space where the list should be.
To extrapolate what was mentioned in the comments:
You are currently running two separate Get commands. The first one, Get-ADPrincipalGroupMembership will generate output. It's a list of groups a principal is member of. The second Get command you're running (Get-ADUser) has it's output used in a loop and you're not printing that output. You'd need to do something like Write-Output $_.MemberOf to see it.
You're using $_.MemberOf as another input to the command Remove-ADGroupMember. For that command the documentation states:
Outputs
None or Microsoft.ActiveDirectory.Management.ADGroup
Returns the modified group object when the PassThru parameter is specified. By default, this cmdlet does not generate any output.
So unless you supply the parameter -PassThru it will consume the "output" of $_.MemberOf and not display anything.

How to use AD groups to assign O365 mailbox sizes

Is there a way to do the above? I've managed to follow the below link successfully but we're looking to set different limits based on the user's role.
The aforementioned link
Where is says :
Additional filters can be applied to the Get-Mailbox cmdlet or to the Get-User cmdlet to control the users for whom the change is applied. The following is an example in which three cmdlets are used to filter the command to the sales department of an organization:
Get-User | where {$_.Department -eq "Sales"} | Get-Mailbox | Set-Mailbox -ProhibitSendQuota < Value > -ProhibitSendReceiveQuota < Value > -IssueWarningQuota < Value >
Kinda got me confused as to where it's pulling the "Sales" group from?
Probably being a muppet here but any help appreciated.
You could do this, using the Active Directory PowerShell module:
Get-ADUser -Filter * -Properties Department | Where-Object { $_.Department -eq "Sales" } | [...]
But that's just pulling everybody and looking at the Department field from Active Directory. That's the example the article gives, but it doesn't answer your question about assigning quotas based on groups.
I suspect what you'll want based on your problem is this:
Get-ADGroupMember -Identity $GroupName | Get-ADUser | Get-MailBox | Set-ProhibitSendQuota [...]
I don't know if you need Get-ADUser there or if the output of Get-ADGroupMember can be piped directly to Get-MailBox. I no longer administer Exchange, so I don't have access to those cmdlets anymore. $GroupName can be the group's name, distinguished name, or even the SID, IIRC.