Public/Set-ServiceAccountHousekeeping.ps1
Function Set-ServiceAccountHousekeeping { <# .SYNOPSIS Manages housekeeping tasks for service accounts within specified organizational units. .DESCRIPTION This function performs housekeeping operations on service accounts (SA) and managed service accounts (MSA) within a specified OU. It ensures that all accounts in the OU are members of a specified group and sets their 'employeeID' attribute to 'ServiceAccount'. .PARAMETER ServiceAccountDN Specifies the distinguished name of the organizational unit containing service accounts. .PARAMETER ServiceAccountGroupName Specifies the name of the group to which all service accounts from the specified OU should belong. .EXAMPLE Set-ServiceAccountHousekeeping -ServiceAccountDN 'OU=T0SA,OU=Service Accounts,OU=Admin,DC=EguibarIT,DC=local' -ServiceAccountGroupName 'SG_T0SA' -Verbose Adds all service accounts in the "OU=T0SA,OU=Service Accounts,OU=Admin,DC=EguibarIT,DC=local" OU to the "SG_T0SA" group and sets their 'employeeID' to 'ServiceAccount'. .NOTES Used Functions: Name | Module ---------------------------------------|-------------------------- Get-ADGroup | ActiveDirectory Get-ADGroupMember | ActiveDirectory Add-ADGroupMember | ActiveDirectory Set-AdObject | ActiveDirectory Import-Module | Microsoft.PowerShell.Core Write-Verbose | Microsoft.PowerShell.Utility Get-FunctionToDisplay | EguibarIT.DelegationPS & EguibarIT.HousekeepingPS Test-IsValidDN | EguibarIT.DelegationPS & EguibarIT.HousekeepingPS Get-AdObjectType | EguibarIT.DelegationPS & EguibarIT.HousekeepingPS .NOTES Version: 1.0 DateModified: 20/Jul/2017 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([void])] Param ( #Param1 [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $true, HelpMessage = 'Service Account OU Distinguished Name.', Position = 0)] [ValidateScript({ Test-IsValidDN -ObjectDN $_ }, ErrorMessage = 'DistinguishedName provided is not valid! Please Check.')] [Alias('DN', 'DistinguishedName', 'LDAPPath')] [String] $ServiceAccountDN, #Param2 [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $true, HelpMessage = 'Name of the corresponding tier service account group (For tier0: SG_T0SA; for Tier1: SG_T1SA; for Tier2: SG_T2SA)', Position = 1)] [ValidateNotNullOrEmpty()] $ServiceAccountGroupName ) Begin { $txt = ($Variables.HeaderHousekeeping -f (Get-Date).ToShortDateString(), $MyInvocation.Mycommand, (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False) ) Write-Verbose -Message $txt Import-MyModule ActiveDirectory ############################## # Variables Definition # parameters variable for splatting CMDlets [hashtable]$Splat = [hashtable]::New([StringComparer]::OrdinalIgnoreCase) # Get the group of the corresponding service accounts $ServiceAccountGroup = Get-AdObjectType -Identity $PsBoundParameters['ServiceAccountGroupName'] Write-Verbose -Message 'Get the group of the corresponding service accounts' # Define an empty array $Members = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) } #end Begin Process { # Fill the array with current group members Get-ADGroupMember -Identity $ServiceAccountGroup | ForEach-Object { [void]$Members.add($_) } # get all users and managed service accounts in the OU $Splat = @{ Filter = '*' SearchBase = $ServiceAccountDN Properties = 'SamAccountName', 'DistinguishedName', 'employeeType', 'employeeID' } $objects = @(Get-ADUser @Splat) + @(Get-ADServiceAccount @Splat) # Step 1: Add users/MSAs from the OU to the group if they are not already members # iterate all users & MSA/gMSA in the OU foreach ($obj in $objects) { # Add to group if not already a member if (-not $Members.Contains($obj.SamAccountName)) { if ($PSCmdlet.ShouldProcess($obj.Name, 'Add to group')) { try { Add-ADGroupMember -Identity $serviceAccountGroup -Members $obj } catch { Write-Error -Message ('Failed to add {0} to group: {1}' -f $obj.sAMAccountName, $_) } #end Try-Catch } #end If } #end If # Update employeeType attribute if necessary if ( ($obj.employeeID -ne 'ServiceAccount') -and ($PSCmdlet.ShouldProcess($obj.Name, 'Update employeeID attribute')) ) { try { Set-ADObject -Identity $obj.DistinguishedName -Replace @{ employeeID = 'ServiceAccount' } } catch { Write-Error -Message ('Failed to update employeeID for {0}: {1}' -f $obj.sAMAccountName, $_) } #end Try-Catch } #end If } #end ForEach # Step 2: Remove users that are in the group but do not belong to the OU # Iterate all members of the given group Foreach ($item in $Members) { # Check if group member has the corresponding object in the OU If (-not $objects.DistinguishedName.Contains($item)) { if ($PSCmdlet.ShouldProcess($Item, 'Remove from group')) { try { Remove-ADGroupMember -Identity $ServiceAccountGroup -Members $Item -Confirm:$false } catch { Write-Error -Message ('Failed to remove {0} from group: {1}' -f $Item, $_) } #end Try-Catch } #end If ShouldProcess } #end If } #end Foreach } #end Process End { $txt = ($Variables.FooterHousekeeping -f $MyInvocation.InvocationName, 'setting Service Account housekeeping.' ) Write-Verbose -Message $txt } #end End } |