Copy users from a series of groups based on a filter to another series of groups based on a separate filter - powershell

Thanks for taking a minute to look at this.
Scenario: Copy users from a series of groups based on a filter to another series of groups based on a separate filter. Essentially a one for one copy of group memberships.
I created some code that grabs all the groups based on the filter and can get all of the users but am having a hard time translating that into the individual pieces. For each group I want just that groups members and then add them to a group with the same name but of a different type (one is OKTA_GROUP and the other is APP_GROUP).
Any help on this would be appreciated. Getting the groups and members works but putting those into variables and passing them into the PUT is not working.
Here is what I have so far.
function get-oktaInvokeGroupMembers () {
$groups = Invoke-Method GET "/api/v1/groups?filter=type+eq+%22APP_GROUP%22&q=test"
Write-Output $groups
foreach ($group in $groups) {
$members = Get-OktaGroupMember $group.id
Write-Output $members
}
$oktagroups = Invoke-Method GET "/api/v1/groups?filter=type+eq+%22OKTA_GROUP%22&q=Test"
Write-Output $oktagroups
foreach ($okta in $oktagroups) {
Invoke-Method PUT "/api/v1/groups/$okta.id/users/$members.id"
}
}

You have to get your APP_GROUP.
Then for each group, you loop to get the members with Get-OktaGroupMember. Each member has normally an id.
You need to retrieve the OKTA_GROUP which has the same name than the group you are currently processing to get its group id.
Then finally for each member, you put the member.
Something like that will be a good starting point.
function get-oktaInvokeGroupMembers ($groupName) {
$sourceGroups = Invoke-Method GET "/api/v1/groups?filter=type+eq+%22APP_GROUP%22&q=$groupName"
foreach ($sourceGroup in $sourceGroups) {
$sourceMembers = Get-OktaGroupMember $sourceGroup.id
$targetGroups = Invoke-Method GET "/api/v1/groups?filter=type+eq+%22OKTA_GROUP%22&q=$groupName"
foreach($targetGroup in $targetGroups) {
foreach($sourceMember in $sourceMembers) {
Invoke-Method PUT "/api/v1/groups/$($targetGroup.id)/users/$($sourceMember.id)"
}
}
}
}
I've defined a parameter $groupName.
I don't know your API but difficulty is that for a specific groupName, you may get zero, one or many groups as result.
So you need to handle all these cases. I've handled multiple results nesting foreach loop but in such case for one APP_GROUP, the script will set members on all OKTA_GROUP that have the same name than APP_GROUP. There may be zero, one or many OKTA_GROUP groups returned by the API.
Another point, you will probably need to handle errors when adding a member. Calling the API with PUT when the member is already in the OKTA_GROUP may return an error.
And last, the script will only append members to a group, but it will never "synchronize" both groups. Meaning deleting members isn't handled. If you need to synchronize members this is bit more complexe.

Related

PowerShell script to get distribution group report

I am looking for a PowerShell script to get a export Distribution Group with following Information.
Group Display Name
Group Owner
Group Member
Last Activity Date
Member Count
Received Email Count
Group ID
I am working on a script but it is returning error
$groupmembers = foreach ($i in Get-DistributionGroup)
{
Get-DistributionGroupMember $i | select Display Name, #{n='Member';e={$i.DisplayName}}
}
Get-DistributionGroupMember returns an object of type ReducedRecipient which does not contain a fields called Display or Name - but it does contain a field called DisplayName - i think this is probably your issue.
If you dont want to read the docs, an easy way of seeing the members of an object is to use ConvertTo-Json. Temporarily add the line Get-DistributionGroupMember $i | ConvertTo-Json inside your foreach loop above the command that is failing. It will output the entire ReducedRecipient Object in JSON format so you can easily read the available property names and their current values.

PowerShell script to apply next available number to a user

Total noob here and i have a dilema... I need to apply Microsoft Calling Plan numbers to users based on region. Now what i want to do is import a .csv file of all the users and have powershell run a command that looks up available calling plan numbers in that region and then assign one to a user. then onto the next user, then the next and so on using the next available number each time.
As i have said i am not great with opwershell and i have thrown this togeth.
$Users = Import-CSV c:\filelocation\users.csv
$loc= (Get-CsOnlineLisLocation -City <city>)
$usernumber = (Get-CsPhoneNumberAssignment -isocountrycode GB -LocationId $loc.LocationId -NumberType CallingPlan -CapabilitiesContain UserAssignment -PstnAssignmentStatus Unassigned)
Foreach($user in $users)
{
Set-CsPhoneNumberAssignment -Identity $_.UPN -PhoneNumber $usernumber -PhoneNumberType CallingPlan
}
I have recently been scolded for using back ticks so that is something i need to ammend here but what i want it to do is lookup unassigned calling plan numbers for the $usernumber parameter and apply it in the set-CsPhoneNumberAssignment.
I have no idea how i loop it to apply the first available number and then move onto the next..
please help.
This script has not yet been run but i dont think it will work.
For matched loops like this you can use regular for($index = 0; $index -le $users.Length; $index++) {} syntax.
Then pass the index to both $Users and $UserNumber lists: $Users[$index].
Check for appropriate sizes first if necessary (especially if there are more users than there are available plans) to avoid ArrayOutOfBoundsExceptions.

Add An AD Attribute To All Users In an AD Group

We have a few groups that we are playing with. We'll call it Group1 Group2 Group3. We then have a custom AD Attribute called "team". We need to take all the users of Group1 and change their AD Attribute to "Group1" etc etc. I've looked at a few ways to do this but am drawing up a blank. Any suggestion is greatly appreciated.
There are a few functions to work with here, and this will require that you have the AD module installed for PowerShell.
First, you'll need to get all of the members of the group, and you likely want to do it recursively. So that's:
Get-ADGroupMember -Identity "Group A" -Recursive
Running that on its own should give you all the members. But now you want to do something with what you got back from that function, so you want to loop over them
Get-ADGroupMember | ForEach-Object {
# You'll do something with each member here.
}
And what you want to do it set the AD attribute, which you can do with Set-ADUser. While most attributes can be set easily as they're all properties of the function, yours appears to be custom so you need to use -replace. That looks like this:
Get-ADGroupMember | ForEach-Object {
Set-ADUser -Identity $_ -Replace #{"Team"="Group A"} -WhatIf
}
The -WhatIf on the end makes the function tell you what it would do, but it doesn't actually do it. I've left it there so you don't accidentally run the code without testing it out first. When you want this to actually do something, remove that text.
You should try this on a small group with one or two people to make sure it works the way you want, and then when you're ready, hit the larger group

How can I find all nested Active Directory groups within a group in Powershell?

I am wanting to see all nested groups inside a particular AD group. Doing this one level down is easy, but what I am needing is to see all nested groups. This means say we have an AD group and it has two groups inside of it that are nested and Im wanting to see all of the nested groups inside of these and then the nested groups inside of those nested groups. So in the end if I input it tells me every group that is nested and subnested inside of ,GroupA>.
Here is my code so far.
function get-nestedgroups{
[cmdletbinding()]
param(
[Parameter(Mandatory = $true)]
[string]$group
)
Begin{
$ADGrp = Get-ADGroup -identity $group
$NestedGroups = Get-ADGroup -LDAPFilter "(&(objectCategory=group)(memberof=$($ADGrp.DistinguishedName)))"
}
Process{
if($NestedGroups.name -ne $null){
return $NestedGroups.SamAccountName
}
}
END{}
}
My thought is to create another function that takes in a group and runs this function on that group. then it takes the output groups from that function and does the same thing over and over until all of the nested groups are found but everytime I try and map it out I cannot figure out a solution to handle all of the foreach loops in a way that it will work with a while loop.

O365 Powershell | Breaking up a long list into two sets of 100

I am looking to create a rule in Office 365 applied to all of the members in our org.
I would like this rule to append a warning on all incoming email from outside the organization with the same Display Names as our users.
When I attempt to apply it to all of the users in our org I get an error stating that the rule is too long.
In order to solve that I pulled a group, but I am still about 1000 characters over the limit.
I would like to make two variables, that each hold one half of the list, created by this command:
(Get-DistibutionGroupMember -Identity email#contoso.com -ResultSize Unlimited).DisplayName
I have attempted to modify the ResultSize parameter, but what I would need is result 1-100 and then 100-200 from the same list.
Another caveat to this problem is that the list cannot be static. It is something that the script will have to update every time it is run.
There is a sub-string command that you can use on a particular username that I have utilized when I made something for AD, but I am not aware of any way to break up a list like this.
If anyone has any other ways to solve this issue I would be more than open to any suggestion.
Thanks for taking the time to read this!
There are many ways of doing it. I found it very readable.
My favorite one is this one:
$ObjectList = 1..1000
$Step = 100
$counter = [pscustomobject] #{ Value = 0 }
$ObjectListSplitted = $ObjectList | Group-Object -Property { math]::Floor($counter.Value++ / $step) }
Then if you want to show the third subset just use this format :
$ObjectListSplitted[3].Group
Have a look to this solution already explained.
As a note other languages are capable of slicing an array of object with a start, stop and a step, have a look here if you're curious.