PSAdsi.psm1
# ipmo .\RDS.DragonFly.psd1 -Force; rds LOGEXI@OPEN.ADDS # https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx function Get-AllADs { <# .SYNOPSIS Liste toutes le Foret accessible .DESCRIPTION les ForestName : Current + AllTrustRelationships Prefer to Use $global:ADs .EXAMPLE Get-AllADs | ?{Test-TcpPort $_ -port 53,389,445,5985} .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> begin { } process { if (!$global:ADs){ $global:ADs = @() try { $global:ADs += ([System.DirectoryServices.ActiveDirectory.Domain]::getCurrentDomain()).Forest.name $global:ADs += ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().GetAllTrustRelationships()).targetName $global:ADs += ([System.DirectoryServices.ActiveDirectory.Domain]::getCurrentDomain().GetAllTrustRelationships()).targetName } catch { Write-LogStep 'Chargement [Domain-Forest] ',$_ error } [array]::sort($global:ADs) } } end { return $global:ADs } } function Get-ADSIGroup { <# .SYNOPSIS liste tous les Groups qui correcponde a un pattern .DESCRIPTION recherche dans toute les AD .PARAMETER NtGroupName pattern de recherche .EXAMPLE Get-ADSIGroup 'MyDomain\Groupe *' .EXAMPLE 'Groupe *@Domain.tld' | Get-ADSIGroup .EXAMPLE Get-ADSIGroup 'Groupe admin@*.tld' .EXAMPLE Get-ADSIGroup '*\*' .EXAMPLE 'OU=compta,DC=open,DC=tld' | Get-ADSIGroup .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [alias("NtAccountName")] $NtGroupName ) begin { $Searcher = New-Object DirectoryServices.DirectorySearcher } process { foreach ($Item in $NtGroupName) { if($item -like '*\*'){ $domain,$SamAccountName = $item.split('\') $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "NtAccount > $Item" } elseif($item -like '*@*') { $SamAccountName,$domain = $item.split('@') $domain=$domain.Split('.')[0] $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "UPN > $Item" } elseif($item -match '((CN=[^,]+,)?(OU=[^,]+,)?DC=([^,]+),DC=(\w+))$') { $SamAccountName = '*' $SearchRoot = ($item -replace ('LDAP://')) Write-Verbose "DN > $($item -replace ('LDAP://'))" } else { $SamAccountName = $item $domain = '*' $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "FULL > $Item" } $Searcher.Filter = "(objectCategory=group)" if($SamAccountName) { $Searcher.Filter = "(&(objectCategory=group)(samAccountName=$SamAccountName))" } # (&(objectClass=group)(email=*)) foreach($AD in $Searchroot){ $Searcher.SearchRoot = "LDAP://$($AD -replace('^(.+)\.(.+)$','DC=$1,DC=$2'))" try { $out = $Searcher.FindAll() | ?{$_} # | ForEach-Object {[adsi]$_.path}).Properties if (!$out) { throw "Aucune Correspondance [$item] !" } Write-Verbose "Collecte ADSI [$AD] $samAccountName[$($out.count)] match" # Write-LogStep "Collecte ADSI [$AD]",$samAccountName,"[$($out.count)] match" ok $Out } catch { Write-LogStep "Collecte ADSI [$SamAccountName@$AD]",$_ error } } } } end {} } function Get-ADSIUser { <# .SYNOPSIS liste tous les Users d'une par le pattern ntaccountName .DESCRIPTION Retoune tous les Objet ADSI Users d'un ensemble d'OU et qui .PARAMETER NtAccountName pattern de recherche de type : - SamAccountName (Pattern) - UserPrincipalName (Pattern) - chemin OU (strict) - chemin LDAP (strict) .EXAMPLE Get-ADSIUser (whoami) .EXAMPLE Get-ADSIUser 'jDoe@domain.tld' .EXAMPLE '*\jDoe' | Get-ADSIUser .EXAMPLE 'OU=paris,OU=User,DC=open,DC=tld' | Get-ADSIUser .EXAMPLE 'LDAP:\\OU=MyOU,DC=open,DC=tld' | Get-ADSIUser .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)]$NtAccountName ) begin { $Searcher = New-Object DirectoryServices.DirectorySearcher } process { foreach ($Item in $NtAccountName) { if($item -like '*\*'){ $domain,$SamAccountName = $item.split('\') $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "NtAccount > $Item" } elseif($item -like '*@*') { $SamAccountName,$domain = $item.split('@') $domain=$domain.Split('.')[0] $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "UPN > $Item" } elseif($item -match '((CN=[^,]+,)?(OU=[^,]+,)?DC=([^,]+),DC=(\w+))$') { $SamAccountName = '*' $SearchRoot = ($item -replace ('LDAP://')) Write-Verbose "DN > $($item -replace ('LDAP://'))" } else { $SamAccountName = $item $domain = '*' $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "FULL > $Item" } $Searcher.Filter = "(objectCategory=user)" if($SamAccountName) { $Searcher.Filter = "(&(objectCategory=user)(samAccountName=$SamAccountName))" } # (&(objectClass=user)(email=*)) foreach($AD in $Searchroot){ $Searcher.SearchRoot = "LDAP://$($AD -replace('^(.+)\.(.+)$','DC=$1,DC=$2'))" try { $out = $Searcher.FindAll() | ?{$_} # | ForEach-Object {[adsi]$_.path}).Properties if (!$out) { throw "Aucune Correspondance [$item] !" } Write-Verbose "Collecte ADSI [$AD] $samAccountName[$($out.count)] match" # Write-LogStep "Collecte ADSI [$AD]",$samAccountName ok $Out } catch { Write-LogStep "Collecte ADSI [$SamAccountName@$AD]",$_ error } } } } end {} } function Get-ADSIComputer { <# .SYNOPSIS liste tous les Ordineteur d'une OU .DESCRIPTION Retoune tous les Objet ADSI Ordinateur d'un ensemble d'OU et qui .PARAMETER Searchroot liste des DistingishedName a parcourir .PARAMETER ComputerName pattern de recherche .EXAMPLE Get-ADSIComputer 'open\PC01' .EXAMPLE 'OU=portable,OU=ordi,DC=open,DC=tld' | Get-ADSIComputer .EXAMPLE '*\PC*' | Get-ADSIComputer .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)]$ComputerName ) begin { $Searcher = New-Object DirectoryServices.DirectorySearcher } process { foreach ($Item in $ComputerName) { if($item -like '*\*'){ $domain,$Name = $item.split('\') $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "NtAccount > $Item" } elseif($item -like '*@*') { $Name,$domain = $item.split('@') $domain=$domain.Split('.')[0] $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "UPN > $Item" } elseif($item -match '((CN=[^,]+,)?(OU=[^,]+,)?DC=([^,]+),DC=(\w+))$') { $Name = '*' $SearchRoot = ($item -replace ('LDAP://')) Write-Verbose "DN > $($item -replace ('LDAP://'))" } else { $Name = $item $domain = '*' $Searchroot = (Get-AllADs) -like "$domain.*" Write-Verbose "FULL > $Item" } $Searcher.Filter = "(objectCategory=computer)" if($name) { $Searcher.Filter = "(&(objectCategory=computer)(name=$name))" } foreach($AD in $Searchroot){ $Searcher.SearchRoot = "LDAP://$($AD -replace('^(.+)\.(.+)$','DC=$1,DC=$2'))" try { $out = $Searcher.FindAll() | ?{$_} # | ForEach-Object {[adsi]$_.path}).Properties if (!$out) { throw "Aucune Correspondance [$item] !" } Write-Verbose "Collecte ADSI [$AD] $samAccountName[$($out.count)] match" # Write-LogStep "Collecte ADSI [$AD]",$name ok $Out } catch { Write-LogStep "Collecte ADSI [$name@$AD]",$_ error } } } } end { } } # function Get-ADSIPwdPolicy { # <# # .SYNOPSIS # liste toutes les strategies de Pwd # .DESCRIPTION # Retoune tous les Objet ADSI Password Settings # .PARAMETER Name # pattern de recherche # .EXAMPLE # Get-ADSIPwdPolicy 'open\*' # .EXAMPLE # Get-ADSIPwdPolicy # .NOTES # Alban LOPEZ 2019 # alban.lopez@gmail.com # #> # [CmdletBinding()] # param ( # [Parameter(ValueFromPipeline = $true)]$NtAccountName # ) # begin { # $Searcher = New-Object DirectoryServices.DirectorySearcher # } # process { # foreach ($Item in $NtAccountName) { # if($item -like '*\*'){ # $domain,$SamAccountName = $item.split('\') # $Searchroot = (Get-AllADs) -like "$domain.*" # } elseif($item -like '*@*') { # $SamAccountName,$domain = $item.split('@') # $domain=$domain.Split('.')[0] # $Searchroot = (Get-AllADs) -like "$domain.*" # } else { # $SamAccountName = $item # $domain = '*' # $Searchroot = (Get-AllADs) -like "$domain.*" # } # $Searcher.Filter = "(Name=$SamAccountName)" # foreach($AD in $Searchroot){ # $Searcher.SearchRoot = "LDAP://CN=Password Settings Container,CN=System,$($AD -replace('^(.+)\.(.+)$','DC=$1,DC=$2'))" # try { # $Searcher.FindAll() | ?{$_} # | ForEach-Object {[adsi]$_.path}).Properties # Write-LogStep "Collecte ADSI [$AD]",$samAccountName ok # } catch { # Write-LogStep "Collecte ADSI [$SamAccountName@$AD]",$_ error # } # } # } # } # end {} # } # function Get-ADSIUserPwdPolicy { # <# # .SYNOPSIS # recherche la strategies de Pwd # .DESCRIPTION # Retoune user Password Settings # .PARAMETER Name # pattern de recherche # .EXAMPLE # Get-ADSIObject (whoami) # .EXAMPLE # Get-ADSIPwdPolicy # .EXAMPLE # '*\jDoe' | Get-ADSIObject # .EXAMPLE # 'OU=paris,OU=User,DC=open,DC=tld' | Get-ADSIObject # .NOTES # Alban LOPEZ 2019 # alban.lopez@gmail.com # #> # [CmdletBinding()] # param ( # [Parameter(ValueFromPipeline = $true)]$NtAccountName # ) # begin { # $Searcher = New-Object DirectoryServices.DirectorySearcher # } # process { # foreach ($Item in $NtAccountName) { # $users = Get-ADSIUser $item # foreach ($user in $users) { # $AllMemberOf = @() # $memberOf = ($user | Get-ADSIMemberOf -Recurse) # $AllMemberOf += $memberOf.MemberOf.distinguishedName # $AllMemberOf += $MemberOf.NestedMemberOf.distinguishedName # # $AllMemberOf | Write-Object -backGroundColor Black -foreGroundColor Cyan # Get-ADSIPwdPolicy "$(($user.properties.distinguishedname -split(',DC='))[-2])\*" | ?{ # # $_.properties.'msds-psoappliesto' | Write-Object -backGroundColor Black -foreGroundColor red # $AllMemberOf -contains $_.properties.'msds-psoappliesto' # } # } # } # } # end {} # } function Set-AdsiProperties { <# .SYNOPSIS Modifie un ensemble de proprietes sur chacun des objets .DESCRIPTION selement les propriete accessible en ecriture directe .PARAMETER AdsiItems Liste des compte AD .PARAMETER ExtraParameters Password Disable / Enable PasswordNeverExpire CantChangePassword TsAllow / AllowLogon / BalOnly AddMemberOf SetMemberOf mstsallowlogon givenname codepage objectcategory description usnchanged instancetype logoncount name badpasswordtime msds-supportedencryptiontypes badpwdcount lastlogontimestamp usncreated sn company userparameters objectguid memberof whencreated adspath useraccountcontrol cn countrycode primarygroupid dscorepropagationdata lastlogon msexchomaadminwirelessenable extensionattribute1 [...] extensionattribute15 othermailbox samaccountname lastlogoff displayname accountexpires userprincipalname .EXAMPLE Set-AdsiProperties -displayname 'Jhon Doe' .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> param ( [Parameter(ValueFromPipeline = $true)] $AdsiItems = $null, [Parameter(ValueFromRemainingArguments=$true)]$ExtraParameters, [switch]$PassThru ) begin { $Properties = @{} $UnnamedParams = @() $Name = $null $ExtraParameters | ForEach-Object -Process { if ($_ -match "^-") { if ($Name) { $Properties.$Name = $true } $Name = $_ -replace "^-|:$" # Write-Verbose $name } else { if ($Name) { $Properties.$Name += $_ $Name = $null } else { $UnnamedParams += $_ } # Write-Verbose $name } # Write-Verbose $_ } -End { if ($Name) { $Properties.$Name = $true } } # $properties | Write-Object -back black -fore Yellow } process { foreach ($item in $AdsiItems) { # $whenchanged = $item.properties.whenchanged # $item | Write-Object -back black -fore DarkYellow if ($item -is [System.DirectoryServices.SearchResult]) { $item = [adsi]$item.path } # elseif ($item -is [string]) { # if ($item -match '^LDAP:\/\/CN=(.+),(OU=([\w\d\s_-]+))*,DC=([\w\d\s_-]+),DC=(com|adds)$') { # $item = [adsi]$item # } elseif ($item -match '^CN=(.+),(OU=([\w\d\s_-]+))*,DC=([\w\d\s_-]+),DC=(com|adds)$') { # $item = [adsi]"LDAP://$item" # } elseif ($item -match '^S-1-5-21-') { # $item = [adsi]"LDAP://<SID=$item>" # } else { if ($item -isnot [System.DirectoryServices.DirectoryEntry]) { Write-LogStep "Format de parametre","[ADSI] required !" error break; } Write-Verbose $item.path # $Item.Properties | ft * # %{$_.PropertyName;$_.Value} $Changed = @() foreach ($Property in $Properties.GetEnumerator()) { $item.GetInfo() | Out-Null # ceci reset la fille d'attente des autre .Put() try { if ($Property.name -match '^Password$') { # $pwdlastset = $item.properties.pwdlastset $item.setpassword($Property.Value) | Out-Null } else { switch -regex ($Property.name) { '^useraccountcontrol$' { if ($($Property.Value) -is [int32]) { $Item.Put('useraccountcontrol',$($Property.Value)) | Out-Null Write-Verbose "Set All useraccountcontrol = $($Property.Value)" # } else { # Write-Error "All useraccountcontrol = $($Property.Value) -is [$($Property.Value.gettype())]" } } '^Disabled?$' { if (!($item.Properties.useraccountcontrol.value -band 2) -eq $Property.Value) { # write-host $Item.Properties.useraccountcontrol.value,' > ' -NoNewline -fore Red $Item.Put('useraccountcontrol', $item.Properties.useraccountcontrol.value -bxor 2) | Out-Null # write-host ($Item.Properties.useraccountcontrol.value -bxor 2) -fore Red Write-Verbose "Set Disable = $($Property.Value)" } } '^Enabled?$' { if ([bool]($item.Properties.useraccountcontrol.value -band 2) -eq $Property.Value) { # write-host $Item.Properties.useraccountcontrol.value,' > ' -NoNewline -fore green $Item.Put('useraccountcontrol', $item.Properties.useraccountcontrol.value -bxor 2) | Out-Null # write-host ($Item.Properties.useraccountcontrol.value -bxor 2) -fore green Write-Verbose "Set Enable = $($Property.Value)" } } '^PasswordNeverExpire$' { if (!($item.Properties.useraccountcontrol.value -band 65536) -eq $Property.Value) { # write-host $Item.Properties.useraccountcontrol.value,' > ' -NoNewline -fore green $Item.Put('useraccountcontrol', $item.Properties.useraccountcontrol.value -bxor 65536) | Out-Null # write-host ($Item.Properties.useraccountcontrol.value -bxor 65536) -fore green Write-Verbose "Set Password Never Expire = $($Property.Value)" } } '^CantChangePassword$' { Write-logstep 'Propriete en lecture seule ','Non modifiable en ADSI!' warn # if (!($item.Properties.useraccountcontrol.value -band 64) -eq $Property.Value) { # # write-host $Item.Properties.useraccountcontrol.value,' > ' -NoNewline -fore green # $Item.Put('useraccountcontrol', $item.Properties.useraccountcontrol.value -bxor 64) | Out-Null # # write-host ($Item.Properties.useraccountcontrol.value -bxor 64) -fore green # Write-Verbose "Set Can't Change Password = $($Property.Value)" # } } '^(TsAllow|AllowLogon)$' { # write-host 'TsAllow' -fore red $Item.InvokeSet('allowlogon', [int]($Property.Value)) | Out-Null Write-Verbose "Set Ts Session Allowed = $($Property.Value)" } '^BalOnly$' { # write-host 'BalOnly' -fore red $Item.InvokeSet('allowlogon',[int](!$Property.Value)) | Out-Null Write-Verbose "Set Bal Only = $($Property.Value)" } '^AddMemberOf$' { $groups = $Property.Value | ?{$_} | Get-ADSIGroup | %{[adsi]$_.Path} # $groups = Get-ADSIGroup -NtGroupName 'open\groupe sotrima *' | %{[adsi]$_.Path} foreach ($group in $groups) { try { if ($group.properties.member -notcontains $item.distinguishedName){ $group.add($item.path) | Out-Null # $group.members.add($item.path) Write-Verbose "Set Add MemberOf = $($group.Name)" } else { Write-Verbose "Already Exist = $($group.Name)" } } catch { # write-color '[',($error[0].Exception.innerException.gettype().BaseType),']' -ForeGroundColor Red,Gray,Red -ea 0 Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber)" "",$_ error } } } '^(Set)?MemberOf$' { $groups = $Property.Value | ?{$_} | Get-ADSIGroup | %{[adsi]$_.Path} ($item | Get-ADSIMemberOf).memberOf | ?{ # Write-host "filter MemberOf = $($_.ADsPath)" -fore cyan $groups.ADsPath -notcontains $_.ADsPath } | %{ # Write-host "filtered MemberOf = $($_.Name)" -fore Red try { $_.Remove($item.Path) | Out-Null Write-Verbose "Set Remove MemberOf = $($_.Name)" } catch { # write-color '[',($error[0].Exception.innerException.gettype().BaseType),']' -ForeGroundColor Red,Gray,Red -ea 0 Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber)" "",$_ error } } # $groups = Get-ADSIGroup -NtGroupName 'open\groupe sotrima *' | %{[adsi]$_.Path} foreach ($group in $groups) { try { # $group.properties.member, $item.distinguishedName | Write-Object -backGroundColor Black -fore Red if ($group.properties.member -notcontains $item.distinguishedName){ $group.add($item.path) | Out-Null # $group.members.add($item.path) Write-Verbose "Set MemberOf = $($group.Name)" } else { Write-Verbose "Already Exist = $($group.Name)" } } catch { # $_ | Write-Object -backGroundColor Black -fore Red # write-color '[',($error[0].Exception.innerException.gettype().BaseType),']' -ForeGroundColor Red,Gray,Red -ea 0 Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber)" "",$_ error } } } '^(AccountExpirationDate|Expiration|Expire)$' { $Item.AccountExpirationDate = $Property.Value # (Get-Date).AddDays(60) #.ToShortDateString() Write-Verbose "$($Property.name) = $($Property.Value)" } '^office$'{ $Item.Put('physicalDeliveryOfficeName', @($Property.Value)) | Out-Null Write-Verbose "$($Property.name) = $($Property.Value)" } default { $Item.Put($Property.name, @($Property.Value)) | Out-Null Write-Verbose "$($Property.name) = $($Property.Value)" } } $Item.CommitChanges() | Out-Null $Item.SetInfo() | Out-Null } $Changed += $Property.name } catch { Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber) %caller%" '',"[$($Property.name)]",$_ Error } } if ($PassThru -and $Changed) { # try { $Item.refreshcache() | Out-Null # } catch { # Write-LogStep -prefix "L.$($_.InvocationInfo.ScriptLineNumber) %caller%" '',"[$($Property.name)]",$_ Error # $item.GetInfo() | Out-Null # ceci reset la fille d'attente des autre .Put() # } $item } } } end {} } # -mstsallowlogon $true -givenname 'Jh0n' -codepage 1 -objectcategory 'CN=Group,CN=Schema,CN=Configuration,DC=open,DC=adds' -description 'kjg321' -usnchanged '102267828' -instancetype '5' -mail 'kjg3@f21.fr' # -logoncount 3 -name 'J Doe' -badpasswordtime 131941170462578977 -badpwdcount '0' -lastlogontimestamp 132018623536360111 -usncreated 39795111 -sn 'JOE' -company 'kjg321' # -userparameters 'kjg321' -objectguid 'kjg321' -memberof @('CN=Groupe SOTRIMA Global,OU=Sotrima,DC=open,DC=adds') -whencreated 'kjg321' -adspath 'kjg321' -useraccountcontrol 'kjg321' -cn 'kjg321' -countrycode 'kjg321' -primarygroupid 'kjg321' -dscorepropagationdata 'kjg321' -lastlogon 'kjg321' -msexchomaadminwirelessenable 'kjg321' -extensionattribute15 'kjg321' -othermailbox 'kjg321' -samaccountname 'kjg321' -lastlogoff 'kjg321' -displayname 'kjg321' -accountexpires 136080899111100000 -userprincipalname 'jhondhoe@open.adds' Function Get-ADSIMemberOf{ <# .SYNOPSIS Identifi les groupe dont est membre un Object .DESCRIPTION Membre direct et indirect (sans doublon) .PARAMETER ADSIObject Object a analyser .PARAMETER Recurse Mode recursif pour les groupe indirect .PARAMETER Groups Ne pas utiliser, reservé pour le mode recursif .EXAMPLE Get-ADSIMemberOf .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> Param( [Parameter(ValueFromPipeline=$true)]$ADSIObject, [switch]$Recurse, $Groups = $null ) begin { } process { # Write-verbose $ADSIObject.Path if($null -eq $Groups){ $Groups = [PSCustomObject]@{ MemberOf = @() NestedMemberOf = @() } Foreach($Memberof in $ADSIObject.properties.memberof){ $Group = [adsi]"LDAP://$MemberOf" $Groups.Memberof += $group if($Group.properties.memberof -and $Recurse){ $Groups = $group | Get-ADSIMemberOf -Groups $Groups -Recurse } } } else { Foreach($Memberof in $ADSIObject.properties.memberof){ $path = "LDAP://$MemberOf" if($Groups.MemberOf.path -contains $path){ # write-verbose "Deja [DirectMemberOf] $path" }elseif($Groups.NestedMemberOf.path -contains $path){ # write-verbose "Deja [NestedMemberOf] $path" } else { # write-verbose "Nouveau [NestedMemberOf] $path" $Group = [adsi]$path $Groups.NestedMemberof += $group $Groups = $group | Get-ADSIMemberOf -Groups $Groups -Recurse } } } # Write-Object $Groups.memberOf.Path -Depth 1 -backGroundColor Black -foreGroundColor darkGreen # Write-Object $Groups.NestedMemberOf.Path -Depth 1 -backGroundColor Black -foreGroundColor Green $Groups } end { } } Function Get-ADSIMembers{ <# .SYNOPSIS Identifi les groupe dont est membre un Object .DESCRIPTION Membre direct et indirect (sans doublon) .PARAMETER ADSIObject Object a analyser .PARAMETER Recurse Mode recursif pour les groupe indirect .PARAMETER Items Ne pas utiliser, reservé pour le mode recursif .EXAMPLE Get-ADSIMembers .NOTES Alban LOPEZ 2019 alban.lopez@gmail.com #> Param( [Parameter(ValueFromPipeline=$true)]$AdsiGroup, [switch]$Recurse, $Items = $null ) begin { } process { # Write-Object $AdsiGroup.Path,$AdsiGroup.properties.member if($null -eq $Items){ $Items = [PSCustomObject]@{ Members = @() Groups = @() NestedMembers = @() NestedGroups = @() } Foreach($Member in $AdsiGroup.properties.member){ $item = [adsi]"LDAP://$Member" if ($item.properties.objectcategory -eq 'CN=Group,CN=Schema,CN=Configuration,DC=open,DC=adds' -and $Recurse) { $Items.groups += $item } else { $Items.Members += $item } } foreach ($Group in $Items.groups) { $Items = $Group | Get-ADSIMembers -Items $Items -Recurse # -Unique:$Unique } } else { Foreach($Member in $AdsiGroup.properties.member){ $item = [adsi]"LDAP://$Member" if ($item.properties.objectcategory -eq 'CN=Group,CN=Schema,CN=Configuration,DC=open,DC=adds'){ # Write-Host ' -> ',$item.path -fore DarkYellow if ($Items.NestedGroups.path -notcontains $item.path -and $Items.Groups.path -notcontains $item.path) { $Items.NestedGroups += $item $Items = $item | Get-ADSIMembers -Items $Items -Recurse # -Unique:$Unique } } elseif($Items.NestedMembers.path -notcontains $item.path -and $Items.Members.path -notcontains $item.path) { # Write-Host ' -> ',$item.path -fore Yellow $Items.NestedMembers += $item } else { # Write-Host ' -X ',$item.path -fore Red } } } $Items } end { } } # function Get-ADSIObject { # <# # .SYNOPSIS # liste tous les Objects qui correcponde a un pattern # .DESCRIPTION # recherche dans toute les AD # .PARAMETER NtGroupName # pattern de recherche # .EXAMPLE # Get-ADSIGroup 'MyDomain\Groupe *' # .EXAMPLE # 'Groupe *@Domain.tld' | Get-ADSIGroup # .EXAMPLE # Get-ADSIGroup 'Groupe admin@*.tld' # .EXAMPLE # Get-ADSIGroup '*\*' # .EXAMPLE # 'OU=compta,DC=open,DC=tld' | Get-ADSIGroup # .NOTES # Alban LOPEZ 2019 # alban.lopez@gmail.com # #> # [CmdletBinding()] # param ( # [Parameter(ValueFromPipeline = $true)] # [alias("NtAccountName")] # $Identity ='*', # [validateset('user','group','computer','Container','Domain-Policy','Organizational-Unit',$null)][string]$type = $null # ) # begin { # $Searcher = New-Object DirectoryServices.DirectorySearcher # switch ($type) { # # 'group' { $filterProperty = 'samAccountName' } # 'user' { $filterProperty = 'samAccountName' } # # 'computer' { } # Default { $filterProperty = 'name' } # } # } # process { # # } # end {} # } function Add-ADSIMemberOf { <# .SYNOPSIS [Descriptif en quelques mots] .DESCRIPTION [Descriptif en quelques lignes] .PARAMETER ADSIObject .PARAMETER Groups .EXAMPLE Add-ADSIMemberOf .NOTES Alban LOPEZ 2020 alban.lopez@gmail.com http://git/PowerTech/ #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] $ADSIObject = $null, $Groups = $null ) begin { $AdsiGroup = @() foreach ($group in $Groups) { if ($Group -is [System.DirectoryServices.DirectoryEntry]){ $AdsiGroup += $Groups } elseif ($group -is [string]) { $AdsiGroup += $Groups | Get-ADSIGroup | %{[adsi]$_.Path} } } } process { if ($ADSIObject -is [string]) { $ADSIObject = $ADSIObject | Get-ADSIUser } foreach ($item in $ADSIObject) { if ($item -is [System.DirectoryServices.SearchResult]) { $item = [adsi]$item.Path } foreach ($Group in $AdsiGroup) { try { $Group.add($item.Path) Write-LogStep "To [$($Group.Name)]","[$($item.Name)] est maintenant dans ce groupe" ok } catch { if($group.member -contains $item.distinguishedName){ Write-LogStep "To [$($Group.Name)]","[$($item.Name)] est deja membre !" Warn } else { Write-LogStep "To [$($Group.Name)]","[$($item.Name)] n'as pu etre Ajoute !" error } Write-Verbose $_ # $_ | Write-Object -back black -fore red # write-color '[',($_.Exception.innerException.gettype().BaseType),']' -ForeGroundColor Red,Gray,Red -ea 0 } } } } end {} } function Remove-ADSIMemberOf { <# .SYNOPSIS [Descriptif en quelques mots] .DESCRIPTION [Descriptif en quelques lignes] .PARAMETER ADSIObject .PARAMETER Groups .EXAMPLE Remove-ADSIMemberOf .NOTES Alban LOPEZ 2020 alban.lopez@gmail.com http://git/PowerTech/ #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] $ADSIObject = $null, $Groups = $null ) begin { $AdsiGroup = @() foreach ($group in $Groups) { if ($Group -is [System.DirectoryServices.DirectoryEntry]){ $AdsiGroup += $Groups } elseif ($group -is [string]) { $AdsiGroup += $Groups | Get-ADSIGroup | %{[adsi]$_.Path} } } } process { if ($ADSIObject -is [string]) { $ADSIObject = $ADSIObject | Get-ADSIUser } foreach ($item in $ADSIObject) { if ($item -is [System.DirectoryServices.SearchResult]) { $item = [adsi]$item.Path } foreach ($Group in $AdsiGroup) { try { $Group.remove($item.Path) Write-LogStep "From [$($Group.Name)]","[$($item.Name)] n'est plus dans ce groupe" ok } catch { if($group.member -contains $item.distinguishedName){ Write-LogStep "To [$($Group.Name)]","[$($item.Name)] n'a pu etre retire !" Warn } else { Write-LogStep "From [$($Group.Name)]","[$($item.Name)] n'est pas dans ce groupe !" warn } Write-Verbose $_ # $_ | Write-Object -back black -fore red # write-color '[',($_.Exception.innerException.gettype().BaseType),']' -ForeGroundColor Red,Gray,Red -ea 0 } } } } end {} } $global:current = (get-Module ($PSCommandPath -replace('.psm1$','.psd1')) -ListAvailable) Get-AllADs | Out-Null if (Get-Module PsWrite) { # Export-ModuleMember -Function Convert-RdSession, Get-RdSession Write-LogStep 'Chargement du module ',$PSCommandPath ok } else { function Script:Write-logstep { param ( [string[]]$messages, $mode, $MaxWidth, $EachLength, $prefixe, $logTrace ) Write-Verbose "$($messages -join(',')) [$mode]" } } |