EguibarIT.psm1
### --- PUBLIC FUNCTIONS --- ### #Region - ConvertTo-IPv4MaskBit.ps1 function ConvertTo-IPv4MaskBit { <# .SYNOPSIS Returns the number of bits (0-32) in a network mask string (e.g., "255.255.255.0"). .DESCRIPTION Returns the number of bits (0-32) in a network mask string (e.g., "255.255.255.0"). .PARAMETER MaskString Specifies the IPv4 network mask string (e.g., "255.255.255.0"). #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([System.Int32])] Param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 1)] [ValidateScript({Test-IPv4MaskString $_})] [String] $MaskString ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { $mask = ([IPAddress] $MaskString).Address for ( $bitCount = 0; $mask -ne 0; $bitCount++ ) { $mask = $mask -band ($mask - 1) } $bitCount } End { Write-Verbose -Message ('Function {0} finished.' -f $MyInvocation.InvocationName) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function ConvertTo-IPv4MaskBit #EndRegion - ConvertTo-IPv4MaskBit.ps1 #Region - ConvertTo-IPv4MaskString.ps1 function ConvertTo-IPv4MaskString { <# .SYNOPSIS Converts a number of bits (0-32) to an IPv4 network mask string (e.g., "255.255.255.0"). .DESCRIPTION Converts a number of bits (0-32) to an IPv4 network mask string (e.g., "255.255.255.0"). .PARAMETER MaskBits Specifies the number of bits in the mask. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 1)] [ValidateRange(0,32)] [Int] $MaskBits ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { $mask = ([Math]::Pow(2, $MaskBits) - 1) * [Math]::Pow(2, (32 - $MaskBits)) $bytes = [BitConverter]::GetBytes([UInt32] $mask) (($bytes.Count - 1)..0 | ForEach-Object { [String] $bytes[$_] }) -join "." } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function ConvertTo-IPv4MaskString #EndRegion - ConvertTo-IPv4MaskString.ps1 #Region - ConvertTo-WmiFilter.ps1 function ConvertTo-WmiFilter { <# .Synopsis .DESCRIPTION .EXAMPLE ConvertTo-WmiFilter .INPUTS .NOTES Version: 1.0 DateModified: 25/Mar/2014 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( [Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { # The concept of this function has been taken directly from the GPWmiFilter.psm1 module # written by Bin Yi from Microsoft. I have modified it to allow for the challenges of # Active Directory replication. It will return the WMI filter as an object of type # "Microsoft.GroupPolicy.WmiFilter". $gpDomain = New-Object -TypeName Microsoft.GroupPolicy.GPDomain $ADObject | ForEach-Object { $path = 'MSFT_SomFilter.Domain="' + $gpDomain.DomainName + '",ID="' + $_.Name + '"' $filter = $null try { $filter = $gpDomain.GetWmiFilter($path) } catch { Write-Error -Message 'The WMI filter could not be found.' } if ($filter) { [Guid]$Guid = $_.Name.Substring(1, $_.Name.Length - 2) $filter | Add-Member -MemberType NoteProperty -Name Guid -Value $Guid -PassThru | Add-Member -MemberType NoteProperty -Name Content -Value $_.'msWMI-Parm2' -PassThru } else { Write-Warning -Message 'Waiting 5 seconds for Active Directory replication to complete.' Start-Sleep -Seconds 5 Write-Warning -Message 'Trying again to retrieve the WMI filter.' ConvertTo-WmiFilter $ADObject } } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished converting the WMI filter." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function ConvertTo-WmiFilter #EndRegion - ConvertTo-WmiFilter.ps1 #Region - Get-AdSite.ps1 function Get-AdSite { <# .Synopsis Get AD Sites from current Forest .DESCRIPTION Reads all Sites from the current Forest and store those on an array. .EXAMPLE Get-AdSites .INPUTS No input needed. .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([array])] Param () Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false } Process { Write-Verbose -Message "Get AD Site List `r" [array] $ADSites = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites } End { Return $ADSites Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished getting AD Sites." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Get-AdSite #EndRegion - Get-AdSite.ps1 #Region - Get-AllAdSiteLink.ps1 function Get-AllAdSiteLink { <# .Synopsis Get AD Site Links from current Forest .DESCRIPTION Reads all Site Links from the current Forest and store those on an array. .EXAMPLE Get-AdSiteLinks .INPUTS No input needed. .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([array])] Param () Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false $ADSiteDN = 'CN=Sites,{0}' -f ([ADSI]'LDAP://RootDSE').configurationNamingContext.ToString() #$SubnetsDN = 'CN=Subnets,{0}' -f $ADSiteDN #$ADSiteLinksDN = 'CN=IP,CN=Inter-Site Transports,{0}' -f $ADSiteDN } Process { Write-Verbose -Message "Get List of AD Site Links `r" [array] $ADSiteLinks = Get-ADObject -Filter { ObjectClass -eq 'sitelink' } -SearchBase $ADSiteDN -Properties * $ADSiteLinksCount = $ADSiteLinks.Count Write-Output -InputObject ("There are {0} AD Site Links in {1} `r" -f $ADSiteLinksCount, $env:USERDNSDOMAIN) } End { Return $ADSiteLinks Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished getting SiteLinks." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Get-AllAdSiteLink #EndRegion - Get-AllAdSiteLink.ps1 #Region - Get-AllAdSubnet.ps1 function Get-AllAdSubnet { <# .Synopsis Get AD subnets from current Forest .DESCRIPTION Reads all Subnets from the current Forest and store those on an array. .EXAMPLE Get-AdSubnets .INPUTS No input needed. .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([array])] Param () Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false } Process { #Get a reference to the RootDSE of the current domain $ADConfigurationNamingContext = ([ADSI]'LDAP://RootDSE').configurationNamingContext [array] $ADSubnets = Get-ADObject -Filter { objectclass -eq 'subnet' } -SearchBase $ADConfigurationNamingContext -Properties * } End { Return $ADSubnets Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished getting AD Subnets." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Get-AllAdSubnet #EndRegion - Get-AllAdSubnet.ps1 #Region - Get-OsBuild.ps1 Function Get-OsBuild { <# .Synopsis Function to Identify OS Build number .DESCRIPTION Function to Identify OS Build number. .INPUTS No Imputs needed .EXAMPLE Get-OsBuild .NOTES Version: 1.0 DateModified: 02/Dic/2014 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Low')] Param () Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { Try { # http://www.gaijin.at/en/lstwinver.php # http://en.wikipedia.org/wiki/Windows_NT # Get OS Information [int]$Global:OsMajorVersion = ((Get-CimInstance -ClassName Win32_OperatingSystem).Version).split('.')[0] [int]$Global:OsMinorVersion = ((Get-CimInstance -ClassName Win32_OperatingSystem).Version).split('.')[1] [int]$Global:OsBuild = ((Get-CimInstance -ClassName Win32_OperatingSystem).Version).split('.')[2] #[String]$Global:OsCaption = (Get-CimInstance -ClassName Win32_OperatingSystem).Caption [int]$Global:OsSpMajorVersion = (Get-CimInstance -ClassName Win32_OperatingSystem).ServicePackMajorVersion #[int]$Global:OsSpMinorVersion = (Get-CimInstance -ClassName Win32_OperatingSystem).ServicePackMinorVersion } catch { $error.clear() [Environment]::OSVersion.Version | ForEach-Object { [int]$Global:OsMajorVersion = $_.Major [int]$Global:OsMinorVersion = $_.Minor [int]$Global:OsBuild = $_.Build } $Global:OsSpMajorVersion = [Environment]::OSVersion.ServicePack } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished getting OS build." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Get-OsBuild #EndRegion - Get-OsBuild.ps1 #Region - Grant-NTFSPermissions.ps1 function Grant-NTFSPermissions { <# .Synopsis Function to Add NTFS permissions to a folder .DESCRIPTION Function to Add NTFS permissions to a folder .EXAMPLE Grant-NTFSPermissions path object permission .INPUTS Param1 path:......... The path to the folder Param2 object:....... the identity which will get the permissions Param3 permission:... the permissions to be modified .NOTES Version: 1.1 DateModified: 03/Oct/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # Param1 path to the resource|folder [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Absolute path to the object', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $path, # Param2 object or SecurityPrincipal [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the object', Position = 1)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $object, # Param3 permission [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Permission of the object', Position = 2)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $permission ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" # Possible values for FileSystemRights are: # ReadAndExecute, AppendData, CreateFiles, read, write, Modify, FullControl $FileSystemRights = [Security.AccessControl.FileSystemRights]$PSBoundParameters['permission'] $InheritanceFlag = [Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit' $PropagationFlag = [Security.AccessControl.PropagationFlags]::None $AccessControlType = [Security.AccessControl.AccessControlType]::Allow } Process { Try { $Account = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $PSBoundParameters['object'] $FileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $DirectorySecurity = Get-Acl -Path $PSBoundParameters['path'] $DirectorySecurity.AddAccessRule($FileSystemAccessRule) Set-Acl -Path $PSBoundParameters['path'] -AclObject $DirectorySecurity } catch { throw } } End { Write-Verbose -Message ('The User/Group {0} was given {1} to folder {2}.' -f $PSBoundParameters['object'], $PSBoundParameters['permission'], $PSBoundParameters['path']) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Grant-NTFSPermissions #EndRegion - Grant-NTFSPermissions.ps1 #Region - Import-MyModule.ps1 Function Import-MyModule { <# .Synopsis Function to Import Modules with error handling .DESCRIPTION Function to Import Modules as with Import-Module Cmdlet but with error handling on it. .INPUTS Param1 name:........String representing Module Name .EXAMPLE Import-MyModule ActiveDirectory .NOTES Version: 1.0 DateModified: 19/Feb/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # Param1 STRING for the Module Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the module to be imported', Position = 0)] [ValidateNotNullOrEmpty()] [string] $name ) Begin{ Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { if(-not(Get-Module -Name $PSBoundParameters['name'])) { if(Get-Module -ListAvailable -Name $PSBoundParameters['name']) { Import-Module -Name $PSBoundParameters['name'] -Force Write-Verbose -Message ('Imported module {0}' -f $PSBoundParameters['name']) } else { Throw ('Module {0} is not installed. Exiting...' -f $PSBoundParameters['name']) Write-Verbose -Message ('The module {0} is not installed.' -f $PSBoundParameters['name']) } } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished importing module." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Import-MyModule #EndRegion - Import-MyModule.ps1 #Region - New-AGPMobjects.ps1 Function New-AGPMObjects { <# .Synopsis Create Advanced Group Policy Management Objects and Delegations .DESCRIPTION Create the AGPM Objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-AGPMObjects .INPUTS .NOTES Version: 1.3 DateModified: 05/Feb/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name EguibarIT.Delegation -Verbose:$false ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 # Organizational Units Distinguished Names # IT Admin OU $ItAdminOu = $confXML.n.Admin.OUs.ItAdminOU.name # IT Admin OU Distinguished Name $ItAdminOuDn = 'OU={0},{1}' -f $ItAdminOu, $AdDn # It Admin ServiceAccount OU Distinguished Name $ItServiceAccountsOu = $confXML.n.Admin.OUs.ItServiceAccountsOU.name # It Admin ServiceAccount OU Distinguished Name $ItServiceAccountsOuDn = 'OU={0},{1}' -f $ItServiceAccountsOu, $ItAdminOuDn # It Admin Rights OU $ItRightsOu = $confXML.n.Admin.OUs.ItRightsOU.name # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn $parameters = $null #endregion Declarations ################################################################################ } Process { ############################################################################### #region Creating Service account # Create the new Temporary Service Account with special values # This TEMP SA will be used for AGMP Server setup. Afterwards will be replaced by a MSA $parameters = @{ Path = $ItServiceAccountsOuDn Name = 'SA_AGPM_Temp' AccountPassword = (ConvertTo-SecureString -String $confXML.n.DefaultPassword -AsPlainText -Force) ChangePasswordAtLogon = $false Enabled = $true UserPrincipalName = ('AGPM@{0}' -f $env:USERDNSDOMAIN) SamAccountName = 'SA_AGPM_Temp' DisplayName = 'SA_AGPM_Temp' Description = 'Service account used for Advanced Group Policy Management service' employeeId = '0123456' TrustedForDelegation = $false AccountNotDelegated = $true Company = $confXML.n.RegisteredOrg Country = 'MX' Department = 'IT Operations and Architecture' State = 'Puebla' EmailAddress = ('AGPM@{0}' -f $env:USERDNSDOMAIN) OtherAttributes = @{ 'employeeType' = 'ServiceAccount' 'msNpAllowDialin' = $false 'msDS-SupportedEncryptionTypes' = '24' } } New-AdUser @parameters $SA_AGPM = Get-AdUser -Filter { samAccountName -eq 'SA_AGPM_Temp' } #http://blogs.msdn.com/b/openspecification/archive/2011/05/31/windows-configurations-for-kerberos-supported-encryption-type.aspx # 'msDS-SupportedEncryptionTypes'= Kerberos DES Encryption = 2, Kerberos AES 128 = 8, Kerberos AES 256 = 16 # Make it member of Tier 0 ServiceAccount groups Add-AdGroupNesting -Identity ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name) -Members $SA_AGPM # http://blogs.msdn.com/b/muaddib/archive/2013/12/30/how-to-modify-security-inheritance-on-active-directory-objects.aspx # Remove Everyone group from Admin-User & Administrator Remove-Everyone -LDAPPath $SA_AGPM.DistinguishedName # Remove AUTHENTICATED USERS group from Admin-User & Administrator #Remove-AuthUser -LDAPPath $SA_AGPM.DistinguishedName # Remove Pre-Windows 2000 Compatible Access group from Admin-User & Administrator Remove-PreWin2000 -LDAPPath $SA_AGPM.DistinguishedName If ($Global:OsBuild -ge 9200) { $Splat = @{ Name = $confXML.n.Admin.gMSA.AGPM.Name SamAccountName = $confXML.n.Admin.gMSA.AGPM.Name DNSHostName = ('{0}.{1}' -f $confXML.n.Admin.gMSA.AGPM.Name, $env:USERDNSDOMAIN) AccountNotDelegated = $true Description = $confXML.n.Admin.gMSA.AGPM.Description DisplayName = $confXML.n.Admin.gMSA.AGPM.DisplayName KerberosEncryptionType = 'AES128,AES256' Path = 'OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT0OU.name, $ItServiceAccountsOuDn enabled = $True TrustedForDelegation = $false } $ReplaceParams = @{ Replace = @{ 'c'="MX" 'co'="Mexico" 'company'=$confXML.n.RegisteredOrg 'department'="IT" 'employeeID'='T0' 'employeeType'="ServiceAccount" 'info'=$confXML.n.Admin.gMSA.AGPM.Description 'l'="Puebla" 'title'=$confXML.n.Admin.gMSA.AGPM.DisplayName 'userPrincipalName'='{0}@{1}' -f $confXML.n.Admin.gMSA.AGPM.Name, $env:USERDNSDOMAIN } } try { New-ADServiceAccount @Splat | Set-ADServiceAccount @ReplaceParams } catch { throw } } else { $Splat = @{ name = $confXML.n.Admin.gMSA.AGPM.Name Description = $confXML.n.Admin.gMSA.AGPM.Description Path = 'OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT0OU.name, $ItServiceAccountsOuDn enabled = $True } New-ADServiceAccount @Splat } #endregion ############################################################################### ############################################################################### #region Create AGPM groups # AdminRights group is created by default on CentralItOU procedure. Is the default delegated Admin for OUs #New-ADGroup -Name "SG_AllSiteAdmins" -SamAccountName SG_AllSiteAdmins -GroupCategory Security -GroupScope Global -DisplayName "All Sites Admins" -Path $ItPGOuDn -Description "Members of this group are Site Administrators of all sites" $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.GpoApproverRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.GpoApproverRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.GpoApproverRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_GpoApproverRight = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.GpoEditorRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.GpoEditorRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.GpoEditorRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_GpoEditorRight = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.GpoReviewerRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.GpoReviewerRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.GpoReviewerRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_GpoReviewerRight = New-AdDelegatedGroup @parameters #endregion ############################################################################### # Apply the PSO to the corresponding Groups Add-ADFineGrainedPasswordPolicySubject -Identity $confXML.n.Admin.PSOs.ItAdminsPSO.Name -Subjects $SL_GpoApproverRight, $SL_GpoEditorRight, $SL_GpoReviewerRight ############################################################################### # Nest Groups - Security for RODC # Avoid having privileged or semi-privileged groups copy to RODC Add-AdGroupMember -Identity 'Denied RODC Password Replication Group' -Members $SL_GpoApproverRight, $SL_GpoEditorRight, $SL_GpoReviewerRight ############################################################################### #region Nest Groups - Delegate Rights through Builtin groups # http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-and-windows-part-1-understanding-privileged-groups-in-ad.aspx Add-AdGroupNesting -Identity 'Backup Operators' -Members $SA_AGPM Add-AdGroupNesting -Identity 'Group Policy Creator Owners' -Members $SA_AGPM #endregion ############################################################################### # Nest Groups - Extend Rights through delegation model groups # No nesting needed here ############################################################################### # START Delegation to # No delegation requiered because: # # 1.- Privileged groups are empty # 2.- AGPM will control all GPOs } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) created objects and Delegations successfully." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-AGPMobjects #EndRegion - New-AGPMobjects.ps1 #Region - New-AreaShareNTFS.ps1 function New-AreaShareNTFS { <# .Synopsis Function to create a new Area folder share .DESCRIPTION Function to create a new Area folder share .EXAMPLE New-AreaShareNTFS -ShareName 'Acounting' -ReadGroup 'SL_Accounting_Read' -ChangeGroup 'SL_Accounting_write' -SiteAdminGroup 'SG_Accounting_MNGT' -SitePath 'C:\Shares\Areas\Accounting' .INPUTS Param1...: ShareName Param2...: ReadGroup Param3...: ChangeGroup Param4...: SiteAdminGroup Param5...: SitePath .NOTES Version: 1.1 DateModified: 03/Oct/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([String])] Param ( # Param1 Sharename [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the share to be created', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $ShareName, # Param2 Read group [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the group with Read-Only permissions', Position = 1)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $readGroup, # Param3 Change Group [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the group with Change permissions', Position = 2)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $changeGroup, # Param4 All Site Admins group [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the group with Full permissions', Position = 3)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $SG_SiteAdminsGroup, # Param5 Path to the site [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'DistinguishedName where the new Groups will be created.', Position = 4)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $sitePath, # Param6 [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Absolute path to the root Share folder (e.g. "C:\Shares\")', Position = 5)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $ShareLocation, # Param7 [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'The root share name for general areas.', Position = 6)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $AreasName ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" #------------------------------------------------------------------------------ # Define the variables # Create Full Share Name $FullShareName = '{0}\{1}\{2}' -f $PSBoundParameters['ShareLocation'], $PSBoundParameters['AreasName'], $PSBoundParameters['ShareName'] $parameters = $null # END variables #--------------------- } Process { If(-not(test-path -Path $FullShareName)) { # Create the new Directory New-Item -Path $FullShareName -ItemType Directory } # Create the associated READ group $parameters = @{ Name = $PSBoundParameters['readGroup'] GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $PSBoundParameters['readGroup'] Path = $PSBoundParameters['sitePath'] Description = 'Read Access to Share {0}' -f $PSBoundParameters['ShareName'] } New-AdDelegatedGroup @parameters # Create the associated Modify group $parameters = @{ Name = $PSBoundParameters['changeGroup'] GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $PSBoundParameters['changeGroup'] Path = $PSBoundParameters['sitePath'] Description = 'Read Access to Share {0}' -f $PSBoundParameters['ShareName'] } New-AdDelegatedGroup @parameters Start-Sleep -Seconds 2 Grant-NTFSPermissions -path $FullShareName -object $PSBoundParameters['readGroup'] -permission 'ReadAndExecute, ChangePermissions' Grant-NTFSPermissions -path $FullShareName -object $PSBoundParameters['changeGroup'] -permission 'Modify, ChangePermissions' Grant-NTFSPermissions -path $FullShareName -object $PSBoundParameters['SG_SiteAdminsGroup'] -permission 'FullControl, ChangePermissions' #& "$env:windir\system32\net.exe" share $ShareName=$FullShareName '/GRANT:Everyone,FULL' New-SmbShare -Name $PSBoundParameters['ShareName'] -Path $FullShareName -FullAccess Everyone if ($error.count -eq 0) { Write-Verbose -Message ('The folder {0} was shared correctly.' -f $ShareName) } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating the share." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-AreaShareNTFS #EndRegion - New-AreaShareNTFS.ps1 #Region - New-CaObjects.ps1 Function New-CaObjects { <# .Synopsis Create Certificate Authority Objects and Delegations .DESCRIPTION Create the Certificate Authority Objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-CaObjects .INPUTS .NOTES Version: 1.3 DateModified: 01/Feb/2018 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module -name EguibarIT.Delegation -Verbose:$false #Get the OS Instalation Type $OsInstalationType = Get-ItemProperty -Path 'HKLM:Software\Microsoft\Windows NT\CurrentVersion' | Select-Object -ExpandProperty InstallationType ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 # Organizational Units Distinguished Names # IT Admin OU $ItAdminOu = $confXML.n.Admin.OUs.ItAdminOU.name # IT Admin OU Distinguished Name $ItAdminOuDn = 'OU={0},{1}' -f $ItAdminOu, $AdDn # It Admin Groups OU # $ItGroupsOu = $confXML.n.Admin.OUs.ItAdminGroupsOU.name # It Admin Groups OU Distinguished Name # $ItGroupsOuDn = 'OU={0},{1}' -f $ItGroupsOu, $ItAdminOuDn # It Privileged Groups OU $ItPGOu = $confXML.n.Admin.OUs.ItPrivGroupsOU.name # It Privileged Groups OU Distinguished Name $ItPGOuDn = 'OU={0},{1}' -f $ItPGOu, $ItAdminOuDn # It Admin Rights OU $ItRightsOu = $confXML.n.Admin.OUs.ItRightsOU.name # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn $parameters = $null #endregion Declarations ################################################################################ } Process { # Check if AD module is installed If(-not((Get-WindowsFeature -Name RSAT-AD-PowerShell).Installed)) { Install-WindowsFeature -Name RSAT-AD-PowerShell -IncludeAllSubFeature } Import-Module -name ActiveDirectory -Verbose:$false # AD CS Step by Step Guide: Two Tier PKI Hierarchy Deployment # https://social.technet.microsoft.com/wiki/contents/articles/15037.ad-cs-step-by-step-guide-two-tier-pki-hierarchy-deployment.aspx # Deploy a PKI on Windows Server 2016 # https://timothygruber.com/pki/deploy-a-pki-on-windows-server-2016-part-2/ try { # Check if feature is installed, if not then proceed to install it. If(-not((Get-WindowsFeature -Name ADCS-Cert-Authority).Installed)) { Install-WindowsFeature -Name ADCS-Cert-Authority -IncludeAllSubFeature Install-WindowsFeature -Name ADCS-web-enrollment Install-WindowsFeature -Name ADCS-Online-Cert If($OsInstalationType -ne 'Server Core') { Install-WindowsFeature -Name RSAT-ADCS -IncludeAllSubFeature } # https://www.pkisolutions.com/tools/pspki/ # Install PSPKI module for managing Certification Authority Install-PackageProvider -Name NuGet -Force Install-Module -Name PSPKI -Force Import-Module PSPKI #Define PKI Cname $PkiServer = ('pki.{0}' -f $env:USERDNSDOMAIN) # Create CAPolicy.inf for Enterprise Root CA $CaPolicy = @" [Version] Signature="$Windows NT$" [PolicyStatementExtension] Policies=AllIssuancePolicy Critical=False [AllIssuancePolicy] OID=2.5.29.32.0 URL=http://$PkiServer/certdata/cps.txt [Certsrv_Server] RenewalKeyLength=$($confXML.n.CA.CAKeyLength) RenewalValidityPeriod=Years RenewalValidityPeriodUnits=$($confXML.n.CA.CACertValidity) CRLPeriod=$($confXML.n.CA.CACRLPeriod) CRLPeriodUnits=$($confXML.n.CA.CACRLPeriodUnits) CRLDeltaPeriod=$($confXML.n.CA.CACRLDeltaPeriod) CRLDeltaPeriodUnits=$($confXML.n.CA.CACRLDeltaPeriodUnits) LoadDefaultTemplates=0 "@ # Set the content into the file Set-Content -Path C:\Windows\CaPolicy.ini -Value $CaPolicy -Force # Create Folder where to store CA Database $CaConfig = ('{0}\CaConfig\' -f $env:SystemDrive) if(-not(Test-Path $CaConfig)) { New-Item -ItemType Directory -Force -Path $CaConfig } $Splat = @{ CAType = $confXML.n.CA.CAType CryptoProviderName = $confXML.n.CA.CACryptoProvider KeyLength = $confXML.n.CA.CAKeyLength HashAlgorithmName = $confXML.n.CA.CAHashAlgorithm ValidityPeriod = 'Years' ValidityPeriodUnits = $confXML.n.CA.CACertValidity CACommonName = '{0}-CA' -f ($AdDn.Split(",")[0]).split("=")[1] CADistinguishedNameSuffix = $AdDn DatabaseDirectory = $CaConfig LogDirectory = '{0}LOGs' -f $CaConfig Force = $true Confirm = $false } # Configure the new CA Install-AdcsCertificationAuthority @Splat # configure the web enrollment role service Install-ADCSwebenrollment -Confirm } # End If } # End Try catch { throw } # End Try-Catch finally { # Remove all distribution points foreach ($crl in Get-CACrlDistributionPoint) { Remove-CACrlDistributionPoint $crl.uri -Force } # Add CDP local path Add-CACRLDistributionPoint -Uri C:\Windows\System32\CertSrv\CertEnroll\%3%8%9.crl -PublishToServer -PublishDeltaToServer -Force # Add CDP url Add-CACRLDistributionPoint -Uri http://$PkiServer/CertEnroll/%3%8%9.crl -AddToCertificateCDP -AddToFreshestCrl -Force Get-CAAuthorityInformationAccess | Where-Object {$_.Uri -like '*ldap*' -or $_.Uri -like '*http*' -or $_.Uri -like '*file*'} | Remove-CAAuthorityInformationAccess -Force # Add AIA url Add-CAAuthorityInformationAccess -AddToCertificateAia http://$PkiServer/CertEnroll/%1_%3%4.crt -Force # Configure CRL and DeltaCRL [String]$cmd = "Certutil -setreg CA\CRLPeriodUnits $($confXML.n.CA.CACRLPeriodUnits)" Invoke-Expression -Command $cmd [String]$cmd = "Certutil -setreg CA\CRLPeriod $($confXML.n.CA.CACRLPeriod)" Invoke-Expression -Command $cmd [String]$cmd = "Certutil -setreg CA\CRLDeltaPeriodUnits $($confXML.n.CA.CACRLDeltaPeriodUnits)" Invoke-Expression -Command $cmd [String]$cmd = "Certutil -setreg CA\CRLDeltaPeriod $($confXML.n.CA.CACRLDeltaPeriod)" Invoke-Expression -Command $cmd <##TODO Failing next 2 #> [String]$cmd = "Certutil -setreg CA\CRLOverlapPeriodUnits $($confXML.n.CA.CACRLOverlapPeriodUnits)" Invoke-Expression -Command $cmd [String]$cmd = "Certutil -setreg CA\CRLOverlapPeriod $($confXML.n.CA.CACRLOverlapPeriod)" Invoke-Expression -Command $cmd # Create A record for PKI Add-DnsServerResourceRecordCName -Name "pki" -HostNameAlias ('{0}.{1}' -f $env:COMPUTERNAME, $env:USERDNSDOMAIN) -ZoneName $env:USERDNSDOMAIN # Configure CA auditing [String]$cmd = "Certutil -setreg CA\AuditFilter 127" Invoke-Expression -Command $cmd # Configure the AIA [String]$Locations = '"1:C:\Windows\system32\CertSrv\CertEnroll\%1_%3%4.crt\n2:ldap:///CN=%7,CN=AIA,CN=Public Key Services,CN=Services,%6%11\n2:http://{0}/CertEnroll/%1_%3%4.crt"' -f $PkiServer [String]$cmd = "certutil -setreg CA\CACertPublicationURLs $($Locations)" Invoke-Expression -Command $cmd # Configure the CDP [String]$Locations = '"65:C:\Windows\system32\CertSrv\CertEnroll\%3%8%9.crl\n79:ldap:///CN=%7%8,CN=%2,CN=CDP,CN=Public Key Services,CN=Services,%6%10\n6:http://{0}/CertEnroll/%3%8%9.crl\n65:\\{1}\CertEnroll\%3%8%9.crl"' -f $PkiServer, ('{0}.{1}' -f $env:COMPUTERNAME, $env:USERDNSDOMAIN) [String]$cmd = "certutil -setreg CA\CRLPublicationURLs $($Locations)" Invoke-Expression -Command $cmd # Configure Online Responder #Configure and Publish the OCSP Response Signing Certificate Get-CertificateTemplate -Name 'OCSPResponseSigning' | Get-CertificateTemplateAcl | Add-CertificateTemplateAcl -Identity ('{0}$' -f $env:computername) -AccessType Allow -AccessMask Read, Enroll | Set-CertificateTemplateAcl Get-CertificationAuthority | Get-CATemplate | Add-CATemplate -DisplayName 'OCSP Response Signing' Restart-Service certsvc } # End Try-Catch-Finally <# ############################################################################### #Install Edge $ProgressPreference='SilentlyContinue' #for faster download Invoke-WebRequest -Uri "http://dl.delivery.mp.microsoft.com/filestreamingservice/files/07367ab9-ceee-4409-a22f-c50d77a8ae06/MicrosoftEdgeEnterpriseX64.msi" -UseBasicParsing -OutFile "$env:USERPROFILE\Downloads\MicrosoftEdgeEnterpriseX64.msi" #start install Start-Process -Wait -Filepath msiexec.exe -Argumentlist "/i $env:UserProfile\Downloads\MicrosoftEdgeEnterpriseX64.msi /q" #start Edge start-sleep 5 & "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" #> ############################################################################### # Create OU Admin groups $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.AdminXtra.GG.PkiAdmins.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.AdminXtra.GG.PkiAdmins.DisplayName Path = $ItPGOuDn Description = $confXML.n.AdminXtra.GG.PkiAdmins.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SG_PkiAdmins = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.AdminXtra.GG.PkiTemplateAdmins.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.AdminXtra.GG.PkiTemplateAdmins.DisplayName Path = $ItPGOuDn Description = $confXML.n.AdminXtra.GG.PkiTemplateAdmins.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SG_PkiTemplAdmins = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.PkiRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.PkiRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.PkiRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_PkiRight = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.PkiTemplateRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.PkiTemplateRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.PkiTemplateRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_PkiTemplRight = New-AdDelegatedGroup @parameters # Apply the PSO to the corresponding Groups Add-ADFineGrainedPasswordPolicySubject -Identity $confXML.n.Admin.PSOs.ItAdminsPSO.Name -Subjects $SG_PkiAdmins, $SG_PkiTemplAdmins, $SL_PkiRight, $SL_PkiTemplRight ############################################################################### # Nest Groups - Security for RODC # Avoid having privileged or semi-privileged groups copy to RODC Add-AdGroupMember -Identity 'Denied RODC Password Replication Group' -Members $SG_PkiAdmins, $SG_PkiTemplAdmins, $SL_PkiRight, $SL_PkiTemplRight ############################################################################### # Nest Groups - Extend Rights through delegation model groups Add-AdGroupNesting -Identity $SG_PkiAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.InfraAdmins.Name) Add-AdGroupNesting -Identity $SG_PkiTemplAdmins -Members $SG_PkiAdmins Add-AdGroupNesting -Identity $SL_PkiRight -Members $SG_PkiAdmins Add-AdGroupNesting -Identity $SL_PkiTemplRight -Members $SG_PkiTemplAdmins Add-AdGroupNesting -Identity 'Cryptographic Operators' -Members $SG_PkiAdmins ############################################################################### # START Delegation to SL_InfraRights group on ADMIN area # Set-AdAclPkiAdmin -Group $SL_PkiRight.SamAccountName -ItRightsOuDN $ItRightsOuDn # Set-AdAclPkiTemplateAdmin -Group $SL_PkiTemplRight.SamAccountName ############################################################################### # START Create new Templates #https://github.com/GoateePFE/ADCSTemplate # Export-ADCSTemplate -Server DC1 -DisplayName WAC > .\WAC.json # #Windows Admin Center and Enterprise CA #https://github.com/microsoft/WSLab/tree/master/Scenarios/Windows%20Admin%20Center%20and%20Enterprise%20CA $DisplayName="RemoteDesktopAuthentication" $TemplateOtherAttributes = @{ 'Name' = [System.String]$DisplayName 'ObjectClass' = [System.String]'pKICertificateTemplate' 'flags' = [System.Int32]'131680' 'revision' = [System.Int32]'100' 'msPKI-Cert-Template-OID' = '1.3.6.1.4.1.311.21.8.2144245.16492515.9915066.5498192.1427428.109.8434507.13944343' 'msPKI-Certificate-Application-Policy' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.5.5.7.3.1','1.3.6.1.4.1.311.54.1.2') 'msPKI-Certificate-Name-Flag' = [System.Int32]'1249902592' 'msPKI-Enrollment-Flag' = [System.Int32]'40' 'msPKI-Minimal-Key-Size' = [System.Int32]'2048' 'msPKI-Private-Key-Flag' = [System.Int32]'101056768' 'msPKI-RA-Signature' = [System.Int32]'0' 'msPKI-Template-Minor-Revision' = [System.Int32]'3' 'msPKI-Template-Schema-Version' = [System.Int32]'4' 'pKICriticalExtensions' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('2.5.29.15') 'pKIDefaultCSPs' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1,Microsoft RSA SChannel Cryptographic Provider') 'pKIDefaultKeySpec' = [System.Int32]'1' 'pKIExpirationPeriod' = [System.Byte[]]@('0','128','114','14','93','194','253','255') 'pKIExtendedKeyUsage' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.5.5.7.3.1','1.3.6.1.4.1.311.54.1.2') 'pKIKeyUsage' = [System.Byte[]]@('160','0') 'pKIMaxIssuingDepth' = [System.Int32]'0' 'pKIOverlapPeriod' = [System.Byte[]]@('0','128','166','10','255','222','255','255') } New-Template -DisplayName $DisplayName -TemplateOtherAttributes $TemplateOtherAttributes #Publish Template PublishCert -CertDisplayName $DisplayName $DisplayName="WindowsAdminCenter" $TemplateOtherAttributes = @{ 'Name' = [System.String]$DisplayName 'ObjectClass' = [System.String]'pKICertificateTemplate' 'flags' = [System.Int32]'131649' 'revision' = [System.Int32]'101' "msPKI-Cert-Template-OID" = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.4.1.311.21.8.2144245.16492515.9915066.5498192.1427428.109.11631727.2421588') 'msPKI-Certificate-Application-Policy' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.5.5.7.3.2','1.3.6.1.5.5.7.3.1') 'msPKI-Certificate-Name-Flag' = [System.Int32]'1249902592' 'msPKI-Enrollment-Flag' = [System.Int32]'40' 'msPKI-Minimal-Key-Size' = [System.Int32]'2048' 'msPKI-Private-Key-Flag' = [System.Int32]'101056768' 'msPKI-RA-Application-Policies' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('msPKI-Asymmetric-Algorithm`PZPWSTR`RSA`msPKI-Hash-Algorithm`PZPWSTR`SHA512`msPKI-Key-Usage`DWORD`16777215`msPKI-Symmetric-Algorithm`PZPWSTR`3DES`msPKI-Symmetric-Key-Length`DWORD`168') 'msPKI-RA-Signature' = [System.Int32]'0' 'msPKI-Template-Minor-Revision' = [System.Int32]'1' 'msPKI-Template-Schema-Version' = [System.Int32]'4' 'pKICriticalExtensions' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('2.5.29.15') 'pKIDefaultCSPs' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1,Microsoft RSA SChannel Cryptographic Provider','2,Microsoft DH SChannel Cryptographic Provider') 'pKIDefaultKeySpec' = [System.Int32]'1' 'pKIExpirationPeriod' = [System.Byte[]]@('0','128','114','14','93','194','253','255') 'pKIExtendedKeyUsage' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.5.5.7.3.1','1.3.6.1.5.5.7.3.2') 'pKIKeyUsage' = [System.Byte[]]@('160','0') 'pKIMaxIssuingDepth' = [System.Int32]'0' 'pKIOverlapPeriod' = [System.Byte[]]@('0','128','166','10','255','222','255','255') } New-Template -DisplayName $DisplayName -TemplateOtherAttributes $TemplateOtherAttributes #Publish Template PublishCert -CertDisplayName $DisplayName $DisplayName="WinRM" $TemplateOtherAttributes = @{ 'Name' = [System.String]$DisplayName 'ObjectClass' = [System.String]'pKICertificateTemplate' 'flags' = [System.Int32]'131649' 'revision' = [System.Int32]'100' "msPKI-Cert-Template-OID" = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.4.1.311.21.8.2144245.16492515.9915066.5498192.1427428.109.16552861.1454492') 'msPKI-Certificate-Application-Policy' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.5.5.7.3.2','1.3.6.1.5.5.7.3.1') 'msPKI-Certificate-Name-Flag' = [System.Int32]'1249902592' 'msPKI-Enrollment-Flag' = [System.Int32]'32' 'msPKI-Minimal-Key-Size' = [System.Int32]'2048' 'msPKI-Private-Key-Flag' = [System.Int32]'101056512' 'msPKI-RA-Application-Policies' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@("msPKI-Asymmetric-Algorithm`PZPWSTR`RSA`msPKI-Hash-Algorithm`PZPWSTR`SHA256`msPKI-Key-Usage`DWORD`16777215`msPKI-Symmetric-Algorithm`PZPWSTR`3DES`msPKI-Symmetric-Key-Length`DWORD`168") 'msPKI-RA-Signature' = [System.Int32]'0' 'msPKI-Template-Minor-Revision' = [System.Int32]'2' 'msPKI-Template-Schema-Version' = [System.Int32]'4' 'pKICriticalExtensions' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('2.5.29.15') 'pKIDefaultCSPs' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1,Microsoft RSA SChannel Cryptographic Provider','2,Microsoft DH SChannel Cryptographic Provider') 'pKIDefaultKeySpec' = [System.Int32]'1' 'pKIExpirationPeriod' = [System.Byte[]]@('0','128','114','14','93','194','253','255') 'pKIExtendedKeyUsage' = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]@('1.3.6.1.5.5.7.3.1','1.3.6.1.5.5.7.3.2') 'pKIKeyUsage' = [System.Byte[]]@('160','0') 'pKIMaxIssuingDepth' = [System.Int32]'0' 'pKIOverlapPeriod' = [System.Byte[]]@('0','128','166','10','255','222','255','255') } New-Template -DisplayName $DisplayName -TemplateOtherAttributes $TemplateOtherAttributes #Publish Template PublishCert -CertDisplayName $DisplayName <# $GatewayServerName="Wac1" $TemplateName = "WindowsAdminCenter" # Install PSPKI module for managing Certification Authority Install-PackageProvider -Name NuGet -Force Install-Module -Name PSPKI -Force Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force Import-Module PSPKI #Set Cert Template permission Get-CertificateTemplate -Name $TemplateName | Get-CertificateTemplateAcl | Add-CertificateTemplateAcl -User "$GatewayServerName$" -AccessType Allow -AccessMask Read, Enroll,AutoEnroll | Set-CertificateTemplateAcl #Configure AutoEnrollment policy and enroll cert on WACGW Invoke-Command -ComputerName $GatewayServerName -ScriptBlock { Set-CertificateAutoEnrollmentPolicy -StoreName MY -PolicyState Enabled -ExpirationPercentage 10 -EnableTemplateCheck -EnableMyStoreManagement -context Machine certutil -pulse } #> } End { Write-Verbose -Message ('Function {0} created Certificate Authority objects and Delegations successfully.' -f $MyInvocation.InvocationName) Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-CaObjects #EndRegion - New-CaObjects.ps1 #Region - New-CentralItOU.ps1 function New-CentralItOu { <# .Synopsis Create Central OU and aditional Tier 0 infrastructure OUs .DESCRIPTION Create Central OU including sub-OUs, secure them accordingly, move built-in objects and secure them, create needed groups and secure them, make nesting and delegations and finaly create PSO and delegate accordingly. .EXAMPLE New-CentralItOu .PARAMETER Param1 ConfigXFileFile:..[STRING] Full path to the configuration.xml file Param2 CreateExchange:...[SWITCH] If present It will create all needed Exchange objects, containers and delegations Param3 CreateDfs:........[SWITCH] If present It will create all needed DFS objects, containers and delegations Param4 CreateCa:.........[SWITCH] If present It will create all needed Certificate Authority (PKI) objects, containers and delegations Param5 CreateAGPM:.......[SWITCH] If present It will create all needed AGPM objects, containers and delegations Param6 CreateLAPS:.......[SWITCH] If present It will create all needed LAPS objects, containers and delegations Param7 CreateDHCP:.......[SWITCH] If present It will create all needed DHCP objects, containers and delegations Param8 DMscripts:........[String] Full path to the Delegation Model Scripts Directory This function relies on Config.xml file. .NOTES Version: 1.2 DateModified: 28/Oct/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([String])] Param ( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 If present It will create all needed Exchange objects, containers and delegations [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed Exchange objects, containers and delegations.', Position = 1)] [switch] $CreateExchange, # Param3 Create DFS Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed DFS objects, containers and delegations.', Position = 2)] [switch] $CreateDfs, # Param4 Create CA (PKI) Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed Certificate Authority (PKI) objects, containers and delegations.', Position = 3)] [switch] $CreateCa, # Param5 Create AGPM Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed AGPM objects, containers and delegations.', Position = 4)] [switch] $CreateAGPM, # Param6 Create LAPS Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed LAPS objects, containers and delegations.', Position = 5)] [switch] $CreateLAPS, # Param7 Create DHCP Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed DHCP objects, containers and delegations.', Position = 6)] [switch] $CreateDHCP, # Param8 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 7)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name GroupPolicy -Verbose:$false Import-Module -name EguibarIT.Delegation -Verbose:$false ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Read the value from parsed SWITCH parameters. try { # Check if CreateExchange parameter is parsed. If($PSBoundParameters['CreateExchange']) { # If parameter is parsed, then make variable TRUE $CreateExchange = $True } else { # Otherwise variable is FALSE $CreateExchange = $False } # Check if CreateDfs parameter is parsed. If($PSBoundParameters['CreateDfs']) { # If parameter is parsed, then make variable TRUE $CreateDfs = $True } else { # Otherwise variable is FALSE $CreateDfs = $False } # Check if CreateCa parameter is parsed. If($PSBoundParameters['CreateCa']) { # If parameter is parsed, then make variable TRUE $CreateCa = $True } else { # Otherwise variable is FALSE $CreateCa = $False } # Check if CreateAGPM parameter is parsed. If($PSBoundParameters['CreateAGPM']) { # If parameter is parsed, then make variable TRUE $CreateAGPM = $True } else { # Otherwise variable is FALSE $CreateAGPM = $False } # Check if CreateLAPS parameter is parsed. If($PSBoundParameters['CreateLAPS']) { # If parameter is parsed, then make variable TRUE $CreateLAPS = $True } else { # Otherwise variable is FALSE $CreateLAPS = $False } } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 # Global Groups Foreach($node in $confXML.n.Admin.GG) { Foreach($Child in $node.ChildNodes) { # Create variable for each defined ADMIN GlobalGroup name, Appending SG prefix New-Variable -Name "$('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $Child.Name)" -Value ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $Child.Name) -Description ($Child.Description) -Option ReadOnly -Force } } New-Variable -Name "SG_Operations" -Value ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.Operations.Name) -Force New-Variable -Name "SG_ServerAdmins" -Value ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.ServerAdmins.Name) -Force # Domain Local Groups Foreach($node in $confXML.n.Admin.LG) { Foreach($Child in $node.ChildNodes) { # Create variable for each defined ADMIN LocalGroup name using the XML name, Appending SL prefix New-Variable -Name "$('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $Child.LocalName)" -Value ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $Child.Name) -Description ($Child.Description) -Option ReadOnly -Force } } New-Variable -Name "SL_SvrAdmRight" -Value ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrAdmRight.Name) -Force New-Variable -Name "SL_SvrOpsRight" -Value ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrOpsRight.Name) -Force # Users $AdminName = $confXML.n.Admin.users.Admin.Name $newAdminName = $confXML.n.Admin.users.NEWAdmin.Name # Organizational Units Names # Iterate all OUs within Admin Foreach($node in $confXML.n.Admin.OUs) { Foreach($Child in $node.ChildNodes) { # Create variable for current OUs name, Using the XML LocalName of the node for the variable New-Variable -Name "$($Child.LocalName)" -Value ($Child.Name) -Description ($Child.Description) -Option ReadOnly -Force } } # Organizational Units Distinguished Names # Admin Area # IT Admin OU Distinguished Name New-Variable -Name 'ItAdminOuDn' -Value ('OU={0},{1}' -f $ItAdminOu, $AdDn) -Option ReadOnly -Force # It Admin Users OU Distinguished Name $ItAdminAccountsOuDn = 'OU={0},{1}' -f $ItAdminAccountsOu, $ItAdminOuDn # It Admin Groups OU Distinguished Name $ItAdminGroupsOuDn = 'OU={0},{1}' -f $ItAdminGroupsOu, $ItAdminOuDn # It Privileged Groups OU Distinguished Name $ItPrivGroupsOUDn = 'OU={0},{1}' -f $ItPrivGroupsOU, $ItAdminOuDn # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn # It Admin ServiceAccount OU Distinguished Name $ItServiceAccountsOuDn = 'OU={0},{1}' -f $ItServiceAccountsOu, $ItAdminOuDn # It Admin T0SA OU Distinguished Name #$ItSAT0OuDn = 'OU={0},{1}' -f $ItSAT0Ou, $ItServiceAccountsOuDn # It Admin T0SA OU Distinguished Name #$ItSAT1OuDn = 'OU={0},{1}' -f $ItSAT1Ou, $ItServiceAccountsOuDn # It Admin T0SA OU Distinguished Name #$ItSAT2OuDn = 'OU={0},{1}' -f $ItSAT2Ou, $ItServiceAccountsOuDn # It PAW OU Distinguished Name $ItPawOuDn = 'OU={0},{1}' -f $ItPawOu, $ItAdminOuDn # It PAW T0 OU Distinguished Name $ItPawT0OuDn = 'OU={0},{1}' -f $ItPawT0Ou, $ItPawOuDn # It PAW T1 OU Distinguished Name $ItPawT1OuDn = 'OU={0},{1}' -f $ItPawT1Ou, $ItPawOuDn # It PAW T2 OU Distinguished Name $ItPawT2OuDn = 'OU={0},{1}' -f $ItPawT2Ou, $ItPawOuDn # It PAW Staging OU Distinguished Name $ItPawStagingOuDn = 'OU={0},{1}' -f $ItPawStagingOu, $ItPawOuDn # It Infrastructure Servers OU Distinguished Name $ItInfraOuDn = 'OU={0},{1}' -f $ItInfraOu, $ItAdminOuDn # It Infrastructure Servers T0 OU Distinguished Name $ItInfraT0OuDn = 'OU={0},{1}' -f $ItInfraT0Ou, $ItInfraOuDn # It Infrastructure Servers T1 OU Distinguished Name $ItInfraT1OuDn = 'OU={0},{1}' -f $ItInfraT1Ou, $ItInfraOuDn # It Infrastructure Servers T2 OU Distinguished Name $ItInfraT2OuDn = 'OU={0},{1}' -f $ItInfraT2Ou, $ItInfraOuDn # It Infrastructure Servers Staging OU Distinguished Name $ItInfraStagingOuDn = 'OU={0},{1}' -f $ItInfraStagingOu, $ItInfraOuDn # It HOUSEKEEPING OU Distinguished Name $ItHousekeepingOuDn = 'OU={0},{1}' -f $ItHousekeepingOu, $ItAdminOuDn # Servers Area # Servers OU New-Variable -Name 'ServersOu' -Value $confXML.n.Servers.OUs.ServersOU.Name -Option ReadOnly -Force # Servers OU Distinguished Name $ServersOuDn = 'OU={0},{1}' -f $ServersOu, $AdDn # Sites Area # Sites OU New-Variable -Name 'SitesOu' -Value $confXML.n.Sites.OUs.SitesOU.name -Option ReadOnly -Force # Sites OU Distinguished Name $SitesOuDn = 'OU={0},{1}' -f $SitesOu, $AdDn # Sites GLOBAL OU $SitesGlobalOu = $confXML.n.Sites.OUs.OuSiteGlobal.name # Sites GLOBAL OU Distinguished Name $SitesGlobalOuDn = 'OU={0},{1}' -f $SitesGlobalOu, $SitesOuDn # Sites GLOBAL GROUPS OU $SitesGlobalGroupOu = $confXML.n.Sites.OUs.OuSiteGlobalGroups.name # Sites GLOBAL GROUPS OU Distinguished Name $SitesGlobalGroupOuDn = 'OU={0},{1}' -f $SitesGlobalGroupOu, $SitesGlobalOuDn # Sites GLOBAL APPACCUSERS OU $SitesGlobalAppAccUserOu = $confXML.n.Sites.OUs.OuSiteGlobalAppAccessUsers.name # Sites GLOBAL APPACCUSERS OU Distinguished Name $SitesGlobalAppAccUserOuDn = 'OU={0},{1}' -f $SitesGlobalAppAccUserOu, $SitesGlobalOuDn # Quarantine OU New-Variable -Name 'ItQuarantineOu' -Value $confXML.n.Admin.OUs.ItNewComputersOU.name -Option ReadOnly -Force # Quarantine OU Distinguished Name $ItQuarantineOuDn = 'OU={0},{1}' -f $ItQuarantineOu, $AdDn # parameters variable for splatting CMDlets $parameters = $null #endregion Declarations ################################################################################ } Process { ############################################################################### # Create IT Admin and Sub OUs Write-Verbose -Message 'Create Admin Area and related structure...' New-DelegateAdOU -ouName $ItAdminOu -ouPath $AdDn -ouDescription $confXML.n.Admin.OUs.ItAdminOU.description # Remove Inheritance and copy the ACE Set-AdInheritance -LDAPPath $ItAdminOuDn -RemoveInheritance $true -RemovePermissions $true <# # Remove AUTHENTICATED USERS group from OU # # CHECK... This one should not "LIST" but must be on ACL Remove-AuthUser -LDAPPath $ItAdminOuDn # Clean Ou Start-AdCleanOU -LDAPPath $ItAdminOuDn -RemoveUnknownSIDs # Remove Pre-Windows 2000 Access group from OU Remove-PreWin2000FromOU -LDAPPath $ItAdminOuDn # Remove ACCOUNT OPERATORS 2000 Access group from OU Remove-AccountOperator -LDAPPath $ItAdminOuDn # Remove PRINT OPERATORS 2000 Access group from OU Remove-PrintOperator -LDAPPath $ItAdminOuDn #> # Computer objects within this ares MUST have read access, otherwise GPO will not apply - TO BE DONE ############################################################################### #region Create Sub-OUs for admin $Splat = @{ ouPath = $ItAdminOuDn CleanACL =$True } New-DelegateAdOU -ouName $ItAdminAccountsOu -ouDescription $confXML.n.Admin.OUs.ItAdminAccountsOU.description @Splat New-DelegateAdOU -ouName $ItAdminGroupsOU -ouDescription $confXML.n.Admin.OUs.ItAdminGroupsOU.description @Splat New-DelegateAdOU -ouName $ItPrivGroupsOU -ouDescription $confXML.n.Admin.OUs.ItPrivGroupsOU.description @Splat New-DelegateAdOU -ouName $ItPawOu -ouDescription $confXML.n.Admin.OUs.ItPawOU.description @Splat New-DelegateAdOU -ouName $ItRightsOu -ouDescription $confXML.n.Admin.OUs.ItRightsOU.description @Splat New-DelegateAdOU -ouName $ItServiceAccountsOu -ouDescription $confXML.n.Admin.OUs.ItServiceAccountsOU.description @Splat New-DelegateAdOU -ouName $ItHousekeepingOu -ouDescription $confXML.n.Admin.OUs.ItHousekeepingOU.description @Splat New-DelegateAdOU -ouName $ItInfraOu -ouDescription $confXML.n.Admin.OUs.ItInfraOU.description @Splat # Ensure inheritance is enabled for child Admin OUs $Splat = @{ RemoveInheritance = $false RemovePermissions = $True } Set-AdInheritance -LDAPPath $ItAdminAccountsOuDn @Splat Set-AdInheritance -LDAPPath $ItAdminGroupsOUDn @Splat Set-AdInheritance -LDAPPath $ItPrivGroupsOUDn @Splat Set-AdInheritance -LDAPPath $ItPawOuDn @Splat Set-AdInheritance -LDAPPath $ItRightsOuDn @Splat Set-AdInheritance -LDAPPath $ItServiceAccountsOuDn @Splat Set-AdInheritance -LDAPPath $ItHousekeepingOuDn @Splat Set-AdInheritance -LDAPPath $ItInfraOuDn @Splat # PAW Sub-OUs $Splat = @{ ouPath = $ItPawOuDn CleanACL =$True } New-DelegateAdOU -ouName $ItPawT0Ou -ouDescription $confXML.n.Admin.OUs.ItPawT0OU.description @Splat New-DelegateAdOU -ouName $ItPawT1Ou -ouDescription $confXML.n.Admin.OUs.ItPawT1OU.description @Splat New-DelegateAdOU -ouName $ItPawT2Ou -ouDescription $confXML.n.Admin.OUs.ItPawT2OU.description @Splat New-DelegateAdOU -ouName $ItPawStagingOu -ouDescription $confXML.n.Admin.OUs.ItPawStagingOU.description @Splat # Ensure inheritance is enabled for child Admin OUs $Splat = @{ RemoveInheritance = $false RemovePermissions = $True } Set-AdInheritance -LDAPPath $ItPawT0OuDn @Splat Set-AdInheritance -LDAPPath $ItPawT1OuDn @Splat Set-AdInheritance -LDAPPath $ItPawT2OuDn @Splat Set-AdInheritance -LDAPPath $ItPawStagingOuDn @Splat # Service Accounts Sub-OUs $Splat = @{ ouPath = $ItServiceAccountsOuDn CleanACL =$True } New-DelegateAdOU -ouName $ItSAT0OU -ouDescription $confXML.n.Admin.OUs.ItSAT0OU.description @Splat New-DelegateAdOU -ouName $ItSAT1OU -ouDescription $confXML.n.Admin.OUs.ItSAT1OU.description @Splat New-DelegateAdOU -ouName $ItSAT2OU -ouDescription $confXML.n.Admin.OUs.ItSAT2OU.description @Splat # Ensure inheritance is enabled for child Admin OUs $Splat = @{ RemoveInheritance = $false RemovePermissions = $True } Set-AdInheritance -LDAPPath $ItT0SAOuDn @Splat Set-AdInheritance -LDAPPath $ItT1SAOuDn @Splat Set-AdInheritance -LDAPPath $ItT2SAOuDn @Splat # Infrastructure Servers Sub-OUs $Splat = @{ ouPath = $ItInfraOuDn CleanACL =$True } New-DelegateAdOU -ouName $ItInfraT0Ou -ouDescription $confXML.n.Admin.OUs.ItInfraT0.description @Splat New-DelegateAdOU -ouName $ItInfraT1Ou -ouDescription $confXML.n.Admin.OUs.ItInfraT1.description @Splat New-DelegateAdOU -ouName $ItInfraT2Ou -ouDescription $confXML.n.Admin.OUs.ItInfraT2.description @Splat New-DelegateAdOU -ouName $ItInfraStagingOu -ouDescription $confXML.n.Admin.OUs.ItInfraStagingOU.description @Splat # Ensure inheritance is enabled for child Admin OUs $Splat = @{ RemoveInheritance = $false RemovePermissions = $True } Set-AdInheritance -LDAPPath $ItInfraT0OuDn @Splat Set-AdInheritance -LDAPPath $ItInfraT1OuDn @Splat Set-AdInheritance -LDAPPath $ItInfraT2OuDn @Splat Set-AdInheritance -LDAPPath $ItInfraStagingOuDn @Splat #endregion ############################################################################### #region Move Built-In Admin user & Groups (Builtin OU groups can't be moved) Write-Verbose -Message 'Moving objects...' Get-ADUser -Identity $AdminName | Move-ADObject -TargetPath $ItAdminAccountsOuDn Get-ADUser -Identity $confXML.n.Admin.users.Guest.Name | Move-ADObject -TargetPath $ItAdminAccountsOuDn Get-ADUser -Identity krbtgt | Move-ADObject -TargetPath $ItAdminAccountsOuDn Get-ADGroup -Identity 'Domain Admins' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'Enterprise Admins' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'Schema Admins' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'Domain Controllers' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'Group Policy Creator Owners' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'Read-only Domain Controllers' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'Enterprise Read-only Domain Controllers' | Move-ADObject -TargetPath $ItPrivGroupsOUDn Get-ADGroup -Identity 'DnsUpdateProxy' | Move-ADObject -TargetPath $ItAdminGroupsOuDn Get-ADGroup -Identity 'Domain Users' | Move-ADObject -TargetPath $ItAdminGroupsOuDn Get-ADGroup -Identity 'Domain Computers' | Move-ADObject -TargetPath $ItAdminGroupsOuDn Get-ADGroup -Identity 'Domain Guests' | Move-ADObject -TargetPath $ItAdminGroupsOuDn Get-ADGroup -Identity 'Allowed RODC Password Replication Group' | Move-ADObject -TargetPath $ItRightsOuDn Get-ADGroup -Identity 'RAS and IAS Servers' | Move-ADObject -TargetPath $ItRightsOuDn Get-ADGroup -Identity 'DNSAdmins' | Move-ADObject -TargetPath $ItRightsOuDn Get-ADGroup -Identity 'Cert Publishers' | Move-ADObject -TargetPath $ItRightsOuDn Get-ADGroup -Identity 'Denied RODC Password Replication Group' | Move-ADObject -TargetPath $ItRightsOuDn # Following groups only exist on Win 2012 If ($Global:OsBuild -ge 9200) { Get-ADGroup -Identity 'Protected Users' | Move-ADObject -TargetPath $ItPGOuDn Get-ADGroup -Identity 'Cloneable Domain Controllers' | Move-ADObject -TargetPath $ItPGOuDn Get-ADGroup -Identity 'Access-Denied Assistance Users' | Move-ADObject -TargetPath $ItGroupsOuDn Get-ADGroup -Filter { SamAccountName -like "WinRMRemoteWMIUsers*" } | Move-ADObject -TargetPath $ItGroupsOuDn } # Following groups only exist on Win 2019 If ($Global:OsBuild -ge 17763) { Get-ADGroup -Identity 'Enterprise Key Admins' | Move-ADObject -TargetPath $ItPGOuDn Get-ADGroup -Identity 'Key Admins' | Move-ADObject -TargetPath $ItPGOuDn #Get-ADGroup -Identity 'Windows Admin Center CredSSP Admins' | Move-ADObject -TargetPath $ItGroupsOuDn } # Get-ADGroup "Administrators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Account Operators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Backup Operators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Certificate Service DCOM Access" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Cryptographic Operators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Server Operators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Remote Desktop Users" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Distributed COM Users" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Event Log Readers" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Guests" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "IIS_IUSRS" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Incoming Forest Trust Builders" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Network Configuration Operators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Performance Log Users" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Performance Monitor Users" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Pre-Windows 2000 Compatible Access" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Print Operators" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Replicator" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Terminal Server License Servers" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Users" | Move-ADObject -TargetPath $ItRightsOuDn # Get-ADGroup "Windows Authorization Access Group" | Move-ADObject -TargetPath $ItRightsOuDn #endregion ############################################################################### ############################################################################### #region Creating Secured Admin accounts Write-Verbose -Message 'Creating and securing Admin accounts...' try { # Try to get the new Admin $NewAdminExists = Get-AdUser -Filter { SamAccountName -eq $newAdminName } # Check if the new Admin account already exist. If not, then create it. If($NewAdminExists) { #The user was found. Proceed to modify it accordingly. $parameters = @{ Enabled = $true UserPrincipalName = ('{0}@{1}' -f $newAdminName, $env:USERDNSDOMAIN) SamAccountName = $newAdminName DisplayName = $newAdminName Description = $confXML.n.Admin.users.NEWAdmin.description employeeId = '0123456' TrustedForDelegation = $false AccountNotDelegated = $true Company = $confXML.n.RegisteredOrg Country = 'MX' Department = $confXML.n.Admin.users.NEWAdmin.department State = 'Puebla' EmailAddress = ('{0}@{1}' -f $newAdminName, $env:USERDNSDOMAIN) Replace = @{ 'employeeType' = $confXML.n.NC.AdminAccSufix0 'msNpAllowDialin' = $false 'msDS-SupportedEncryptionTypes' = '24' } } If(Test-Path -Path ('{0}\Pic\{1}.jpg' -f $DMscripts, $newAdminName)) { # Read the path and file name of JPG picture $PhotoFile = '{0}\Pic\{1}.jpg' -f $DMscripts, $newAdminName # Get the content of the JPG file $photo = [byte[]](Get-Content -Path $PhotoFile -Encoding byte) # Only if photo exists, add it to splatting $parameters.Replace.Add('thumbnailPhoto',$photo) } Set-AdUser -Identity $NewAdminExists } #end if -user exists Else { # User was not Found! create new. $parameters = @{ Path = $ItAdminAccountsOuDn Name = $newAdminName AccountPassword = (ConvertTo-SecureString -String $confXML.n.DefaultPassword -AsPlainText -Force) ChangePasswordAtLogon = $false Enabled = $true UserPrincipalName = ('{0}@{1}' -f $newAdminName, $env:USERDNSDOMAIN) SamAccountName = $newAdminName DisplayName = $newAdminName Description = $confXML.n.Admin.users.NEWAdmin.description employeeId = '0123456' TrustedForDelegation = $false AccountNotDelegated = $true Company = $confXML.n.RegisteredOrg Country = 'MX' Department = $confXML.n.Admin.users.NEWAdmin.department State = 'Puebla' EmailAddress = ('{0}@{1}' -f $newAdminName, $env:USERDNSDOMAIN) OtherAttributes = @{ 'employeeType' = $confXML.n.NC.AdminAccSufix0 'msNpAllowDialin' = $false 'msDS-SupportedEncryptionTypes' = '24' } } If(Test-Path -Path ('{0}\Pic\{1}.jpg' -f $DMscripts, $newAdminName)) { # Read the path and file name of JPG picture $PhotoFile = '{0}\Pic\{1}.jpg' -f $DMscripts, $newAdminName # Get the content of the JPG file $photo = [byte[]](Get-Content -Path $PhotoFile -Encoding byte) # Only if photo exists, add it to splatting $parameters.OtherAttributes.Add('thumbnailPhoto',$photo) } # Create the new Admin with special values New-AdUser @parameters $NewAdminExists = Get-AdUser -Identity $newAdminName #http://blogs.msdn.com/b/openspecification/archive/2011/05/31/windows-configurations-for-kerberos-supported-encryption-type.aspx # 'msDS-SupportedEncryptionTypes'= Kerberos DES Encryption = 2, Kerberos AES 128 = 8, Kerberos AES 256 = 16 } #end esle-if new user created # Set the Protect against accidental deletions attribute Get-AdUser -Identity $AdminName | Set-ADObject -ProtectedFromAccidentalDeletion $true $NewAdminExists | Set-ADObject -ProtectedFromAccidentalDeletion $true # Make it member of administrative groups Add-AdGroupNesting -Identity 'Domain Admins' -Members $NewAdminExists Add-AdGroupNesting -Identity 'Enterprise Admins' -Members $NewAdminExists Add-AdGroupNesting -Identity 'Group Policy Creator Owners' -Members $NewAdminExists Add-AdGroupNesting -Identity 'Denied RODC Password Replication Group' -Members $NewAdminExists # http://blogs.msdn.com/b/muaddib/archive/2013/12/30/how-to-modify-security-inheritance-on-active-directory-objects.aspx #### # Remove Everyone group from Admin-User & Administrator Remove-Everyone -LDAPPath $NewAdminExists.DistinguishedName Remove-Everyone -LDAPPath ('CN={0},{1}' -f $AdminName, $ItAdminAccountsOuDn) #### # Remove AUTHENTICATED USERS group from Admin-User & Administrator #Remove-AuthUser -LDAPPath $NewAdminExists.DistinguishedName #Remove-AuthUser -LDAPPath ('CN={0},{1}' -f $AdminName, $ItAdminAccountsOuDn) #### # Remove Pre-Windows 2000 Compatible Access group from Admin-User & Administrator Remove-PreWin2000 -LDAPPath $NewAdminExists.DistinguishedName Remove-PreWin2000 -LDAPPath ('CN={0},{1}' -f $AdminName, $ItAdminAccountsOuDn) ### # Configure TheGood account # Read the path and file name of JPG picture $PhotoFile = '{0}\Pic\{1}.jpg' -f $DMscripts, $AdminName # Get the content of the JPG file $photo = [byte[]](Get-Content -Path $PhotoFile -Encoding byte) Get-ADUser -Identity $AdminName | Set-AdUser -TrustedForDelegation $false -AccountNotDelegated $true -Add @{ 'employeeType' = $confXML.n.NC.AdminAccSufix0 'msNpAllowDialin' = $false 'msDS-SupportedEncryptionTypes' = '24' 'thumbnailPhoto' = $photo } } # end try catch { throw } finally { Write-Verbose -Message 'Admin accounts created and secured.' } #endregion Creating Secured Admin accounts ############################################################################### ############################################################################### #region Create Admin groups # Iterate through all Admin-LocalGroups child nodes Foreach($node in $confXML.n.Admin.LG.ChildNodes) { Write-Verbose -Message ('Create group {0}' -f ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $node.Name)) $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $node.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $node.DisplayName Path = $ItRightsOuDn Description = $node.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $node.Name)" -Value (New-AdDelegatedGroup @parameters) -Force } # Iterate through all Admin-GlobalGroups child nodes Foreach($node in $confXML.n.Admin.GG.ChildNodes) { Write-Verbose -Message ('Create group {0}' -f ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $node.Name)) $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $node.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $node.DisplayName Path = $ItGroupsOuDn Description = $node.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $node.Name)" -Value (New-AdDelegatedGroup @parameters) -Force } # Create Servers Area / Tier1 Domain Local & Global Groups $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.Operations.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.Servers.GG.Operations.DisplayName Path = $ItGroupsOuDn Description = $confXML.n.Servers.GG.Operations.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.Operations.Name)" -Value (New-AdDelegatedGroup @parameters) -Force $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.ServerAdmins.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.Servers.GG.ServerAdmins.DisplayName Path = $ItGroupsOuDn Description = $confXML.n.Servers.GG.ServerAdmins.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.ServerAdmins.Name)" -Value (New-AdDelegatedGroup @parameters) -Force $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrOpsRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.Servers.LG.SvrOpsRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.Servers.LG.SvrOpsRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrOpsRight.Name)" -Value (New-AdDelegatedGroup @parameters) -Force $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrAdmRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.Servers.LG.SvrAdmRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.Servers.LG.SvrAdmRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrAdmRight.Name)" -Value (New-AdDelegatedGroup @parameters) -Force # Get all Privileged groups into an array $AllGroups = @( $SG_InfraAdmins, $SG_AdAdmins, $SG_T0SA, $SG_T1SA, $SG_T2SA, $SG_GpoAdmins, $SG_Tier0Admins, $SG_Tier1Admins, $SG_Tier2Admins, $SG_AllSiteAdmins, $SG_AllGALAdmins ) # Move the groups to PG OU foreach($item in $AllGroups) { # Remove the ProtectedFromAccidentalDeletion, otherwise throws error when moving $item | Set-ADObject -ProtectedFromAccidentalDeletion $false # Move objects to PG OU $item | Move-ADObject -TargetPath $ItPGOuDn # Set back again the ProtectedFromAccidentalDeletion flag. #The group has to be fetch again because of the previus move Get-ADGroup -Identity $item.SamAccountName | Set-ADObject -ProtectedFromAccidentalDeletion $true } #endregion ############################################################################### ############################################################################### #region Create Group Managed Service Account # Get the current OS build Get-OsBuild If ($Global:OsBuild -ge 9200) { # Create the KDS Root Key (only once per domain). This is used by the KDS service on DCs (along with other information) to generate passwords # http://blogs.technet.com/b/askpfeplat/archive/2012/12/17/windows-server-2012-group-managed-service-accounts.aspx # If working in a test environment with a minimal number of DCs and the ability to guarantee immediate replication, please use: # Add-KdsRootKey –EffectiveTime ((get-date).addhours(-10)) Add-KdsRootKey -EffectiveTime ((get-date).addhours(-10)) } If ($Global:OsBuild -ge 9200) { $Splat = @{ Name = $confXML.n.Admin.gMSA.AdTaskScheduler.Name SamAccountName = $confXML.n.Admin.gMSA.AdTaskScheduler.Name DNSHostName = ('{0}.{1}' -f $confXML.n.Admin.gMSA.AdTaskScheduler.Name, $env:USERDNSDOMAIN) AccountNotDelegated = $true Description = $confXML.n.Admin.gMSA.AdTaskScheduler.Description DisplayName = $confXML.n.Admin.gMSA.AdTaskScheduler.DisplayName KerberosEncryptionType = 'AES128,AES256' Path = 'OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT0OU.name, $ItServiceAccountsOuDn enabled = $True TrustedForDelegation = $false ServicePrincipalName = ('HOST/{0}.{1}' -f $confXML.n.Admin.gMSA.AdTaskScheduler.Name, $env:USERDNSDOMAIN) } $ReplaceParams = @{ Replace = @{ 'c'="MX" 'co'="Mexico" 'company'=$confXML.n.RegisteredOrg 'department'="IT" 'employeeID'='T0' 'employeeType'="ServiceAccount" 'info'=$confXML.n.Admin.gMSA.AdTaskScheduler.Description 'l'="Puebla" 'title'=$confXML.n.Admin.gMSA.AdTaskScheduler.DisplayName 'userPrincipalName'='{0}@{1}' -f $confXML.n.Admin.gMSA.AdTaskScheduler.Name, $env:USERDNSDOMAIN } } try { New-ADServiceAccount @Splat | Set-ADServiceAccount @ReplaceParams } catch { throw } } else { $Splat = @{ name = $confXML.n.Admin.gMSA.AdTaskScheduler.Name Description = $confXML.n.Admin.gMSA.AdTaskScheduler.Description Path = 'OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT0OU.name, $ItServiceAccountsOuDn enabled = $True } New-ADServiceAccount @Splat } #endregion ############################################################################### ############################################################################### #region Create a New Fine Grained Password Policy for Admins Accounts $PSOexists = $null $PsoName = $confXML.n.Admin.PSOs.ItAdminsPSO.Name $PSOexists = Get-ADFineGrainedPasswordPolicy -Filter { cn -eq $PsoName } if(-not($PSOexists)) { $parameters = @{ Name = $confXML.n.Admin.PSOs.ItAdminsPSO.Name Precedence = $confXML.n.Admin.PSOs.ItAdminsPSO.Precedence ComplexityEnabled = [System.Boolean]$confXML.n.Admin.PSOs.ItAdminsPSO.ComplexityEnabled Description = $confXML.n.Admin.PSOs.ItAdminsPSO.Description DisplayName = $confXML.n.Admin.PSOs.ItAdminsPSO.DisplayName LockoutDuration = $confXML.n.Admin.PSOs.ItAdminsPSO.LockoutDuration LockoutObservationWindow = $confXML.n.Admin.PSOs.ItAdminsPSO.LockoutObservationWindow LockoutThreshold = $confXML.n.Admin.PSOs.ItAdminsPSO.LockoutThreshold MaxPasswordAge = $confXML.n.Admin.PSOs.ItAdminsPSO.MaxPasswordAge MinPasswordAge = $confXML.n.Admin.PSOs.ItAdminsPSO.MinPasswordAge MinPasswordLength = $confXML.n.Admin.PSOs.ItAdminsPSO.MinPasswordLength PasswordHistoryCount = $confXML.n.Admin.PSOs.ItAdminsPSO.PasswordHistoryCount ReversibleEncryptionEnabled = [System.Boolean]$confXML.n.Admin.PSOs.ItAdminsPSO.ReversibleEncryptionEnabled } New-ADFineGrainedPasswordPolicy @parameters [String]$PsoName = $confXML.n.Admin.PSOs.ItAdminsPSO.Name $PSOexists = Get-ADFineGrainedPasswordPolicy -Filter { cn -eq $PsoName } } # Apply the PSO to the corresponding accounts and groups $parameters = @( $AdminName, $newAdminName, 'Domain Admins', 'Enterprise Admins', $SG_InfraAdmins.SamAccountName, $SG_AdAdmins.SamAccountName, $SG_GpoAdmins.SamAccountName, $SG_Tier0Admins.SamAccountName, $SG_Tier1Admins.SamAccountName, $SG_Tier2Admins.SamAccountName, $SG_Operations.SamAccountName, $SG_ServerAdmins.SamAccountName, $SG_AllSiteAdmins.SamAccountName, $SG_AllGALAdmins.SamAccountName, $SG_GlobalUserAdmins.SamAccountName, $SG_GlobalPcAdmins.SamAccountName, $SG_GlobalGroupAdmins.SamAccountName, $SG_ServiceDesk.SamAccountName, $SL_InfraRight.SamAccountName, $SL_AdRight.SamAccountName, $SL_UM.SamAccountName, $SL_GM.SamAccountName, $SL_PUM.SamAccountName, $SL_PGM.SamAccountName, $SL_GpoAdminRight.SamAccountName, $SL_DirReplRight.SamAccountName, $SL_PISM.SamAccountName, $SL_PAWM.SamAccountName, $SL_PSAM.SamAccountName, $SL_SvrAdmRight.SamAccountName, $SL_SvrOpsRight.SamAccountName, $SL_GlobalGroupRight.SamAccountName, $SL_GlobalAppAccUserRight.SamAccountName ) Add-ADFineGrainedPasswordPolicySubject -Identity $PSOexists -Subjects $parameters #endregion ############################################################################### ############################################################################### #region Create a New Fine Grained Password Policy for Service Accounts $PSOexists = $null $PsoName = $confXML.n.Admin.PSOs.ServiceAccountsPSO.Name $PSOexists = Get-ADFineGrainedPasswordPolicy -Filter { cn -eq $PsoName } if(-not($PSOexists)) { $parameters = @{ Name = $confXML.n.Admin.PSOs.ServiceAccountsPSO.Name Precedence = $confXML.n.Admin.PSOs.ServiceAccountsPSO.Precedence ComplexityEnabled = [System.Boolean]$confXML.n.Admin.PSOs.ServiceAccountsPSO.ComplexityEnabled Description = $confXML.n.Admin.PSOs.ServiceAccountsPSO.Description DisplayName = $confXML.n.Admin.PSOs.ServiceAccountsPSO.DisplayName LockoutDuration = $confXML.n.Admin.PSOs.ServiceAccountsPSO.LockoutDuration LockoutObservationWindow = $confXML.n.Admin.PSOs.ServiceAccountsPSO.LockoutObservationWindow LockoutThreshold = $confXML.n.Admin.PSOs.ServiceAccountsPSO.LockoutThreshold MaxPasswordAge = $confXML.n.Admin.PSOs.ServiceAccountsPSO.MaxPasswordAge MinPasswordAge = $confXML.n.Admin.PSOs.ServiceAccountsPSO.MinPasswordAge MinPasswordLength = $confXML.n.Admin.PSOs.ServiceAccountsPSO.MinPasswordLength PasswordHistoryCount = $confXML.n.Admin.PSOs.ServiceAccountsPSO.PasswordHistoryCount ReversibleEncryptionEnabled = [System.Boolean]$confXML.n.Admin.PSOs.ServiceAccountsPSO.ReversibleEncryptionEnabled } New-ADFineGrainedPasswordPolicy @parameters $PSOexists = Get-ADFineGrainedPasswordPolicy -Filter { cn -eq $PsoName } } # Apply the PSO to all Tier Service Accounts $parameters = @( $SG_T0SA.SamAccountName, $SG_T1SA.SamAccountName, $SG_T2SA.SamAccountName ) Add-ADFineGrainedPasswordPolicySubject -Identity $PSOexists -Subjects $parameters #endregion ############################################################################### ############################################################################### #region Nest Groups - Security for RODC # Avoid having privileged or semi-privileged groups copy to RODC Write-Verbose -Message 'Nesting groups...' $parameters = @( $AdminName, $newAdminName, 'Domain Admins', 'Enterprise Admins', $SG_InfraAdmins, $SG_AdAdmins, $SG_GpoAdmins, $SG_Tier0Admins, $SG_Tier1Admins, $SG_Tier2Admins, $SG_T0SA, $SG_T1SA, $SG_T2SA, $SG_Operations, $SG_ServerAdmins, $SG_AllSiteAdmins, $SG_AllGALAdmins, $SG_GlobalUserAdmins, $SG_GlobalPcAdmins, $SG_GlobalGroupAdmins, $SG_ServiceDesk, $SL_InfraRight, $SL_AdRight, $SL_UM, $SL_GM, $SL_PUM, $SL_PGM, $SL_GpoAdminRight, $SL_DirReplRight, $SL_PISM, $SL_PAWM, $SL_PSAM, $SL_SvrAdmRight, $SL_SvrOpsRight, $SL_GlobalGroupRight, $SL_GlobalAppAccUserRight ) Add-AdGroupNesting -Identity 'Denied RODC Password Replication Group' -Members $parameters #endregion ############################################################################### ############################################################################### #region Enabling Management Accounts to Modify the Membership of Protected Groups # Enable PUM to manage Privileged Accounts (Reset PWD, enable/disable Administrator built-in account) Set-AdAclMngPrivilegedAccounts -Group $SL_PUM.SamAccountName # Enable PGM to manage Privileged Groups (Administrators, Domain Admins...) Set-AdAclMngPrivilegedGroups -Group $SL_PGM.SamAccountName #endregion ############################################################################### ############################################################################### #region Nest Groups - Delegate Rights through Builtin groups # http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-and-windows-part-1-understanding-privileged-groups-in-ad.aspx # http://blogs.msmvps.com/acefekay/2012/01/06/using-group-nesting-strategy-ad-best-practices-for-group-strategy/ Add-AdGroupNesting -Identity 'Cryptographic Operators' -Members $SG_AdAdmins Add-AdGroupNesting -Identity 'Network Configuration Operators' -Members $SG_AdAdmins Add-AdGroupNesting -Identity DnsAdmins -Members $SG_AdAdmins Add-AdGroupNesting -Identity 'Event Log Readers' -Members $SG_AdAdmins, $SG_Operations Add-AdGroupNesting -Identity 'Performance Log Users' -Members $SG_AdAdmins, $SG_Operations Add-AdGroupNesting -Identity 'Performance Monitor Users' -Members $SG_AdAdmins, $SG_Operations Add-AdGroupNesting -Identity 'Remote Desktop Users' -Members $SG_AdAdmins # https://technet.microsoft.com/en-us/library/dn466518(v=ws.11).aspx $parameters = @($AdminName, $NewAdminName, $SG_InfraAdmins, $SG_AdAdmins, $SG_GpoAdmins, $SG_Tier0Admins, $SG_Tier1Admins, $SG_Tier2Admins, $SG_Operations, $SG_ServerAdmins, $SG_AllSiteAdmins, $SG_AllGALAdmins, $SG_GlobalUserAdmins, $SG_GlobalPcAdmins, $SG_GlobalGroupAdmins, $SG_ServiceDesk ) Add-AdGroupNesting -Identity 'Protected Users' -Members $parameters #endregion ############################################################################### ############################################################################### #region Nest Groups - Extend Rights through delegation model groups # http://blogs.msmvps.com/acefekay/2012/01/06/using-group-nesting-strategy-ad-best-practices-for-group-strategy/ # InfraAdmins as member of InfraRight $parameters = @{ Identity = $SL_InfraRight Members = $SG_InfraAdmins } Add-AdGroupNesting @parameters # InfraAdmins as member of PUM $parameters = @{ Identity = $SL_PUM Members = $SG_InfraAdmins } Add-AdGroupNesting @parameters # InfraAdmins as member of PGM $parameters = @{ Identity = $SL_PGM Members = $SG_InfraAdmins } Add-AdGroupNesting @parameters # InfraAdmins as member of PISM $parameters = @{ Identity = $SL_PISM Members = $SG_InfraAdmins } Add-AdGroupNesting @parameters # InfraAdmins as member of PAWM $parameters = @{ Identity = $SL_PAWM Members = $SG_InfraAdmins } Add-AdGroupNesting @parameters # InfraAdmins as member of PSAM $parameters = @{ Identity = $SL_PSAM Members = $SG_InfraAdmins.SamAccountName } Add-AdGroupNesting @parameters # InfraAdmins as member of Tier0Admins $parameters = @{ Identity = $SG_Tier0Admins.SamAccountName Members = $SG_InfraAdmins.SamAccountName } Add-AdGroupNesting @parameters # InfraAdmins as member of DirReplRight $parameters = @{ Identity = $SL_DirReplRight.SamAccountName Members = $SG_InfraAdmins.SamAccountName } Add-AdGroupNesting @parameters # InfraAdmins as member of AdAdmins $parameters = @{ Identity = $SG_AdAdmins Members = $SG_InfraAdmins } Add-AdGroupNesting @parameters # AdAdmins as member of AdRight $parameters = @{ Identity = $SL_AdRight Members = $SG_AdAdmins } Add-AdGroupNesting @parameters # AdAdmins as member of UM $parameters = @{ Identity = $SL_UM Members = $SG_AdAdmins } Add-AdGroupNesting @parameters # AdAdmins as member of GM $parameters = @{ Identity = $SL_GM Members = $SG_AdAdmins } Add-AdGroupNesting @parameters # AdAdmins as member of GpoAdmins $parameters = @{ Identity = $SG_GpoAdmins Members = $SG_AdAdmins } Add-AdGroupNesting @parameters # AdAdmins as member of AllSiteAdmins $parameters = @{ Identity = $SG_AllSiteAdmins Members = $SG_AdAdmins } Add-AdGroupNesting @parameters # AdAdmins as member of ServerAdmins $parameters = @{ Identity = $SG_ServerAdmins Members = $SG_AdAdmins } Add-AdGroupNesting @parameters # GpoAdmins as member of GpoAdminRight $parameters = @{ Identity = $SL_GpoAdminRight Members = $SG_GpoAdmins } Add-AdGroupNesting @parameters # AllSiteAdmins as member of AllGalAdmins $parameters = @{ Identity = $SG_AllGALAdmins Members = $SG_AllSiteAdmins } Add-AdGroupNesting @parameters # AllGalAdmins as member of ServiceDesk $parameters = @{ Identity = $SG_ServiceDesk Members = $SG_AllGALAdmins } Add-AdGroupNesting @parameters # ServerAdmins as member of SvrAdmRight $parameters = @{ Identity = $SL_SvrAdmRight Members = $SG_ServerAdmins } Add-AdGroupNesting @parameters # Operations as member of SvrOpsRight $parameters = @{ Identity = $SL_SvrOpsRight Members = $SG_Operations } Add-AdGroupNesting @parameters # ServerAdmins as member of Operations $parameters = @{ Identity = $SG_Operations Members = $SG_ServerAdmins } Add-AdGroupNesting @parameters #endregion ############################################################################### ############################################################################### #region redirect Users & Computers containers New-DelegateAdOU -ouName $ItQuarantineOu -ouPath $AdDn -ouDescription $confXML.n.Admin.OUs.ItNewComputersOU.description -RemoveAuthenticatedUsers New-DelegateAdOU -ouName $confXML.n.Admin.OUs.ItNewUsersOU.Name -ouPath $AdDn -ouDescription $confXML.n.Admin.OUs.ItNewUsersOU.description -RemoveAuthenticatedUsers # START Remove Delegation to BuiltIn groups BEFORE REDIRECTION $parameters = @{ Group = 'Account Operators' LDAPPath = 'CN=Computers,{0}' -f $AdDn RemoveRule = $True } ### COMPUTERS # Remove the Account Operators group from ACL to Create/Delete Users Set-AdAclCreateDeleteUser @parameters # Remove the Account Operators group from ACL to Create/Delete Computers Set-AdAclCreateDeleteComputer @parameters # Remove the Account Operators group from ACL to Create/Delete Groups Set-AdAclCreateDeleteGroup @parameters # Remove the Account Operators group from ACL to Create/Delete Contacts Set-AdAclCreateDeleteContact @parameters # Remove the Account Operators group from ACL to Create/Delete inetOrgPerson Set-CreateDeleteInetOrgPerson @parameters # Remove the Account Operators group from ACL to Create/Delete inetOrgPerson Set-AdAclCreateDeletePrintQueue @parameters $parameters = @{ Group = 'Account Operators' LDAPPath = 'CN=Users,{0}' -f $AdDn RemoveRule = $True } ### USERS # Remove the Account Operators group from ACL to Create/Delete Users Set-AdAclCreateDeleteUser @parameters # Remove the Account Operators group from ACL to Create/Delete Computers Set-AdAclCreateDeleteComputer @parameters # Remove the Account Operators group from ACL to Create/Delete Groups Set-AdAclCreateDeleteGroup @parameters # Remove the Account Operators group from ACL to Create/Delete Contacts Set-AdAclCreateDeleteContact @parameters # Remove the Account Operators group from ACL to Create/Delete inetOrgPerson Set-CreateDeleteInetOrgPerson @parameters # Remove the Print Operators group from ACL to Create/Delete PrintQueues Set-AdAclCreateDeletePrintQueue @parameters ############################################################################### # Redirect Default USER & COMPUTERS Containers redircmp.exe ('OU={0},{1}' -f $ItQuarantineOu, $AdDn) redirusr.exe ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItNewUsersOU.Name, $AdDn) #endregion ############################################################################### ############################################################################### #region Delegation to ADMIN area (Tier 0) Write-Verbose -Message 'Delegate Admin Area...' # Computer objects within this ares MUST have read access, otherwise GPO will not apply # UM - Semi-Privileged User Management Set-AdAclDelegateUserAdmin -Group $SL_UM.SamAccountName -LDAPpath $ItAdminAccountsOuDn Set-AdAclDelegateGalAdmin -Group $SL_UM.SamAccountName -LDAPpath $ItAdminAccountsOuDn # GM - Semi-Privileged Group Management Set-AdAclCreateDeleteGroup -Group $SL_GM.SamAccountName -LDAPPath $ItGroupsOuDn Set-AdAclChangeGroup -Group $SL_GM.SamAccountName -LDAPPath $ItGroupsOuDn # PUM - Privileged User Management Set-AdAclDelegateUserAdmin -Group $SL_PUM.SamAccountName -LDAPpath $ItAdminAccountsOuDn Set-AdAclDelegateGalAdmin -Group $SL_PUM.SamAccountName -LDAPpath $ItAdminAccountsOuDn # PGM - Privileged Group Management # Create/Delete Groups Set-AdAclCreateDeleteGroup -Group $SL_PGM.SamAccountName -LDAPPath $ItPGOuDn Set-AdAclCreateDeleteGroup -Group $SL_PGM.SamAccountName -LDAPPath $ItRightsOuDn # Change Group Properties Set-AdAclChangeGroup -Group $SL_PGM.SamAccountName -LDAPPath $ItPGOuDn Set-AdAclChangeGroup -Group $SL_PGM.SamAccountName -LDAPPath $ItRightsOuDn # PISM - Privileged Infrastructure Services Management # Create/Delete Computers Set-AdAclDelegateComputerAdmin -Group $SL_PISM.SamAccountName -LDAPPath $ItInfraT0OuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_PISM.SamAccountName -LDAPPath $ItInfraT1OuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_PISM.SamAccountName -LDAPPath $ItInfraT2OuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_PISM.SamAccountName -LDAPPath $ItInfraStagingOuDn -QuarantineDN $ItQuarantineOuDn # PAWM - Privileged Access Workstation Management Set-AdAclDelegateComputerAdmin -Group $SL_PAWM.SamAccountName -LDAPPath $ItPawT0OuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_PAWM.SamAccountName -LDAPPath $ItPawT1OuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_PAWM.SamAccountName -LDAPPath $ItPawT2OuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_PAWM.SamAccountName -LDAPPath $ItPawStagingOuDn -QuarantineDN $ItQuarantineOuDn # PSAM - Privileged Service Account Management - Create/Delete Managed Service Accounts & Standard user service accounts # Managed Service Accounts "Default Container" $parameters = @{ Group = $SL_PSAM.SamAccountName LDAPPath = ('CN=Managed Service Accounts,{0}' -f $AdDn) } Set-AdAclCreateDeleteGMSA @parameters Set-AdAclCreateDeleteMSA @parameters # TIER 0 $parameters = @{ Group = $SL_PSAM.SamAccountName LDAPPath = $ItT0SAOuDn } Set-AdAclCreateDeleteGMSA @parameters Set-AdAclCreateDeleteMSA @parameters Set-AdAclCreateDeleteUser @parameters Set-AdAclResetUserPassword @parameters Set-AdAclChangeUserPassword @parameters Set-AdAclUserGroupMembership @parameters Set-AdAclUserAccountRestriction @parameters Set-AdAclUserLogonInfo @parameters # TIER 1 $parameters = @{ Group = $SL_PSAM.SamAccountName LDAPPath = $ItT1SAOuDn } Set-AdAclCreateDeleteGMSA @parameters Set-AdAclCreateDeleteMSA @parameters Set-AdAclCreateDeleteUser @parameters Set-AdAclResetUserPassword @parameters Set-AdAclChangeUserPassword @parameters Set-AdAclUserGroupMembership @parameters Set-AdAclUserAccountRestriction @parameters Set-AdAclUserLogonInfo @parameters # TIER 2 $parameters = @{ Group = $SL_PSAM.SamAccountName LDAPPath = $ItT0SAOuDn } Set-AdAclCreateDeleteGMSA @parameters Set-AdAclCreateDeleteMSA @parameters Set-AdAclCreateDeleteUser @parameters Set-AdAclResetUserPassword @parameters Set-AdAclChangeUserPassword @parameters Set-AdAclUserGroupMembership @parameters Set-AdAclUserAccountRestriction @parameters Set-AdAclUserLogonInfo @parameters # GPO Admins # Create/Delete GPOs Set-AdAclCreateDeleteGPO -Group $SL_GpoAdminRight.SamAccountName # Link existing GPOs to OUs Set-AdAclLinkGPO -Group $SL_GpoAdminRight.SamAccountName # Change GPO options Set-AdAclGPoption -Group $SL_GpoAdminRight.SamAccountName # Delegate Directory Replication Rights Set-AdDirectoryReplication -Group $SL_DirReplRight.SamAccountName # Infrastructure Admins # Organizational Units at domain level Set-AdAclCreateDeleteOU -Group $SL_InfraRight.SamAccountName -LDAPPath $AdDn # Organizational Units at Admin area Set-AdAclCreateDeleteOU -Group $SL_InfraRight.SamAccountName -LDAPPath $ItAdminOuDn # Subnet Configuration Container # Create/Delete Subnet Set-AdAclCreateDeleteSubnet -Group $SL_InfraRight.SamAccountName # Site Configuration Container # Create/Delete Sites Set-AdAclCreateDeleteSite -Group $SL_InfraRight.SamAccountName # Site-Link Configuration Container # Create/Delete Site-Link Set-AdAclCreateDeleteSiteLink -Group $SL_InfraRight.SamAccountName # AD Admins # Delete computers from default container Set-DeleteOnlyComputer -Group $SL_AdRight.SamAccountName -LDAPPath $ItQuarantineOuDn # Subnet Configuration Container| # Change Subnet Set-AdAclChangeSubnet -Group $SL_AdRight.SamAccountName # Site Configuration Container # Change Site Set-AdAclChangeSite -Group $SL_AdRight.SamAccountName # Site-Link Configuration Container # Change SiteLink Set-AdAclChangeSiteLink -Group $SL_AdRight.SamAccountName #endregion ############################################################################### ############################################################################### #region Create Baseline GPO Write-Verbose -Message 'Creating Baseline GPOs and configure them accordingly...' # Domain New-DelegateAdGpo -gpoDescription Baseline -gpoScope C -gpoLinkPath $AdDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription Baseline -gpoScope U -gpoLinkPath $AdDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Domain Controllers New-DelegateAdGpo -gpoDescription DomainControllers-Baseline -gpoScope C -gpoLinkPath ('OU=Domain Controllers,{0}' -f $AdDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Admin Area New-DelegateAdGpo -gpoDescription ItAdmin-Baseline -gpoScope C -gpoLinkPath $ItAdminOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ItAdmin-Baseline -gpoScope U -gpoLinkPath $ItAdminOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItAdminOU.Name) -gpoScope U -gpoLinkPath $ItAdminAccountsOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Service Accounts New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItServiceAccountsOU.Name) -gpoScope U -gpoLinkPath $ItServiceAccountsOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItSAT0OU.Name) -gpoScope U -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT0OU.Name, $ItServiceAccountsOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItSAT1OU.Name) -gpoScope U -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT1OU.Name, $ItServiceAccountsOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItSAT2OU.Name) -gpoScope U -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItSAT2OU.Name, $ItServiceAccountsOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # PAWs New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawOU.Name) -gpoScope C -gpoLinkPath $ItPawOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT0OU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItPawT0OU.Name, $ItPawOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT1OU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItPawT1OU.Name, $ItPawOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT2OU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItPawT2OU.Name, $ItPawOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawStagingOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItPawStagingOU.Name, $ItPawOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Infrastructure Servers New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraOU.Name) -gpoScope C -gpoLinkPath $ItInfraOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT0.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItInfraT0.Name, $ItInfraOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT1.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItInfraT1.Name, $ItInfraOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT2.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItInfraT2.Name, $ItInfraOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraStagingOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItInfraStagingOU.Name, $ItInfraOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # redirected containers (X-Computers & X-Users) New-DelegateAdGpo -gpoDescription ('{0}-LOCKDOWN' -f $confXML.n.Admin.OUs.ItNewComputersOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItNewComputersOU.Name, $AdDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-LOCKDOWN' -f $confXML.n.Admin.OUs.ItNewUsersOU.Name) -gpoScope U -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Admin.OUs.ItNewUsersOU.Name, $AdDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Housekeeping New-DelegateAdGpo -gpoDescription ('{0}-LOCKDOWN' -f $confXML.n.Admin.OUs.ItHousekeepingOU.Name) -gpoScope U -gpoLinkPath $ItHousekeepingOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-LOCKDOWN' -f $confXML.n.Admin.OUs.ItHousekeepingOU.Name) -gpoScope C -gpoLinkPath $ItHousekeepingOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) ############################################################################### # Import GPO from Archive #Import the Default Domain Policy Import-GPO -BackupId $confXML.n.Admin.GPOs.DefaultDomain.backupID -TargetName $confXML.n.Admin.GPOs.DefaultDomain.Name -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure Default Domain Controllers GPO Import-GPO -BackupId $confXML.n.Admin.GPOs.DefaultDomainControllers.backupID -TargetName $confXML.n.Admin.GPOs.DefaultDomainControllers.Name -path (Join-Path $DMscripts SecTmpl) # C-DomainControllers-Baseline Import-GPO -BackupId $confXML.n.Admin.GPOs.DCBaseline.backupID -TargetName ('{0}-{1}-Baseline' -f $confXML.n.Admin.GPOs.DCBaseline.Scope, $confXML.n.Admin.GPOs.DCBaseline.Name) -path (Join-Path $DMscripts SecTmpl) # C-Baseline Import-GPO -BackupId $confXML.n.Admin.GPOs.PCbaseline.backupID -TargetName 'C-Baseline' -path (Join-Path $DMscripts SecTmpl) # U-Baseline Import-GPO -BackupId $confXML.n.Admin.GPOs.Userbaseline.backupID -TargetName 'U-Baseline' -path (Join-Path $DMscripts SecTmpl) ############################################################################### # Configure GPO Restrictions based on Tier Model # Domain $Splat = @( 'ALL SERVICES', 'ANONYMOUS LOGON', 'NT AUTHORITY\Local Account', 'NT AUTHORITY\Local Account and member of administrators group' ) Set-GpoPrivilegeRights -GpoToModify 'C-Baseline' -DenyNetworkLogon $Splat $parameters = @( $SG_T0SA.SamAccountName, $SG_T1SA.SamAccountName, $SG_T2SA.SamAccountName ) Set-GpoPrivilegeRights -GpoToModify 'C-Baseline' -DenyInteractiveLogon $parameters $parameters = @( $SG_T0SA.SamAccountName, $SG_T1SA.SamAccountName, $SG_T2SA.SamAccountName, $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify 'C-Baseline' -DenyRemoteInteractiveLogon $parameters $parameters = @( $SG_Tier0Admins.SamAccountName, $SG_Tier1Admins.SamAccountName, $SG_Tier2Admins.SamAccountName, 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify 'C-Baseline' -DenyBatchLogon $parameters -DenyServiceLogon $parameters $parameters = @( 'Network Service', 'NT SERVICE\All Services' ) Set-GpoPrivilegeRights -GpoToModify 'C-Baseline' -ServiceLogon $parameters # Domain Controllers $parameters = @( $SG_T1SA.SamAccountName, $SG_T2SA.SamAccountName, $SG_Tier0Admins.SamAccountName, $SG_Tier1Admins.SamAccountName, $SG_Tier2Admins.SamAccountName, 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify 'C-DomainControllers-Baseline' -DenyBatchLogon $parameters -DenyServiceLogon $parameters Set-GpoPrivilegeRights -GpoToModify 'C-DomainControllers-Baseline' -BatchLogon $SG_T0SA.SamAccountName -ServiceLogon $SG_T0SA.SamAccountName, 'Network Service' $parameters = @( $SG_Tier0Admins.SamAccountName, 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify 'C-DomainControllers-Baseline' -InteractiveLogon $parameters -RemoteInteractiveLogon $parameters $parameters = @( $SG_T1SA.SamAccountName, $SG_T2SA.SamAccountName, $SG_Tier1Admins.SamAccountName, $SG_Tier2Admins.SamAccountName, 'Account Operators', 'Backup Operators', 'Print Operators' ) Set-GpoPrivilegeRights -GpoToModify 'C-DomainControllers-Baseline' -DenyInteractiveLogon $parameters # Admin Area $parameters = @( $SG_T1SA.SamAccountName, $SG_T2SA.SamAccountName, $SG_Tier0Admins.SamAccountName, $SG_Tier1Admins.SamAccountName, $SG_Tier2Admins.SamAccountName, 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify 'C-ItAdmin-Baseline' -DenyBatchLogon $parameters -DenyServiceLogon $parameters $parameters = @( $SG_T0SA.SamAccountName 'Network Service', 'NT SERVICE\All Services' ) Set-GpoPrivilegeRights -GpoToModify 'C-ItAdmin-Baseline' -BatchLogon $SG_T0SA.SamAccountName -ServiceLogon $parameters # Admin Area = HOUSEKEEPING $parameters = @( $SG_Tier0Admins.SamAccountName, 'Domain Admins', 'Administrators' ) Set-GpoPrivilegeRights -GpoToModify 'C-Housekeeping-LOCKDOWN' -NetworkLogon $parameters -InteractiveLogon $parameters # Admin Area = Infrastructure Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT0.Name) -InteractiveLogon $SL_PISM.SamAccountName, 'Domain Admins', Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT0.Name) -RemoteInteractiveLogon $SL_PISM.SamAccountName $parameters = @( $SG_T0SA.SamAccountName 'Network Service', 'NT SERVICE\All Services' ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT0.Name) -BatchLogon $SG_T0SA.SamAccountName -ServiceLogon $parameters Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT1.Name) -InteractiveLogon $SG_Tier1Admins.SamAccountName, Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT1.Name) -RemoteInteractiveLogon $SG_Tier1Admins.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT1.Name) -BatchLogon $SG_T1SA.SamAccountName -ServiceLogon $SG_T1SA.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT2.Name) -InteractiveLogon $SG_Tier2Admins.SamAccountName, Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT1.Name) -RemoteInteractiveLogon $SG_Tier2Admins.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraT2.Name) -BatchLogon $SG_T2SA.SamAccountName -ServiceLogon $SG_T2SA.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraStagingOU.Name) -InteractiveLogon $SL_PISM.SamAccountName, 'Domain Admins', Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItInfraStagingOU.Name) -RemoteInteractiveLogon $SL_PISM.SamAccountName # Admin Area = PAWs Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawStagingOU.Name) -InteractiveLogon $SL_PAWM.SamAccountName, Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawStagingOU.Name) -RemoteInteractiveLogon $SL_PAWM.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT0OU.Name) -InteractiveLogon $SL_PAWM.SamAccountName, Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT0OU.Name) -RemoteInteractiveLogon $SL_PAWM.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT0OU.Name) -BatchLogon $SG_T0SA.SamAccountName -ServiceLogon $SG_T0SA.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT1OU.Name) -InteractiveLogon $SG_Tier1Admins.SamAccountName, Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT1OU.Name) -RemoteInteractiveLogon $SG_Tier1Admins.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT1OU.Name) -BatchLogon $SG_T1SA.SamAccountName -ServiceLogon $SG_T1SA.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT2OU.Name) -InteractiveLogon $SG_Tier2Admins.SamAccountName, Administrators Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT2OU.Name) -RemoteInteractiveLogon $SG_Tier2Admins.SamAccountName Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $confXML.n.Admin.OUs.ItPawT2OU.Name) -BatchLogon $SG_T2SA.SamAccountName -ServiceLogon $SG_T2SA.SamAccountName #endregion ############################################################################### ############################################################################### #region SERVERS OU (area) Write-Verbose -Message 'Creating Servers Area...' ############################################################################### # Create Servers and Sub OUs New-DelegateAdOU -ouName $ServersOu -ouPath $AdDn -ouDescription $confXML.n.Servers.OUs.ServersOU.Description # Create Sub-OUs for Servers New-DelegateAdOU -ouName $confXML.n.Servers.OUs.SqlOU.Name -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.SqlOU.Description New-DelegateAdOU -ouName $confXML.n.Servers.OUs.WebOU.Name -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.WebOU.Description New-DelegateAdOU -ouName $confXML.n.Servers.OUs.FileOU.Name -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.FileOU.Description New-DelegateAdOU -ouName $confXML.n.Servers.OUs.ApplicationOU.Name -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.ApplicationOU.Description New-DelegateAdOU -ouName $confXML.n.Servers.OUs.HypervOU.Name -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.HypervOU.Description New-DelegateAdOU -ouName $confXML.n.Servers.OUs.RemoteDesktopOU.Name -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.RemoteDesktopOU.Description # Create basic GPO for Servers New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $ServersOu) -gpoScope C -gpoLinkPath $ServersOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Create basic GPOs for different types under Servers New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Servers.OUs.ApplicationOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Servers.OUs.ApplicationOU.Name, $ServersOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Servers.OUs.FileOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Servers.OUs.FileOU.Name, $ServersOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Servers.OUs.HypervOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Servers.OUs.HypervOU.Name, $ServersOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Servers.OUs.RemoteDesktopOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Servers.OUs.RemoteDesktopOU.Name, $ServersOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Servers.OUs.SqlOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Servers.OUs.SqlOU.Name, $ServersOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $confXML.n.Servers.OUs.WebOU.Name) -gpoScope C -gpoLinkPath ('OU={0},{1}' -f $confXML.n.Servers.OUs.WebOU.Name, $ServersOuDn) -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Import the security templates to the corresponding GPOs under Servers # Configure Default Servers Baseline Import-GPO -BackupId $confXML.n.Servers.GPOs.Servers.backupID -TargetName ('C-{0}-Baseline' -f $ServersOu) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure File Server GPO Import-GPO -BackupId $confXML.n.Servers.GPOs.FileSrv.backupID -TargetName ('C-{0}-Baseline' -f $confXML.n.Servers.OUs.FileOU.Name) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure Hyper-V GPO Import-GPO -BackupId $confXML.n.Servers.GPOs.HyperV.backupID -TargetName ('C-{0}-Baseline' -f $confXML.n.Servers.OUs.HypervOU.Name) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure RemoteDesktop GPO Import-GPO -BackupId $confXML.n.Servers.GPOs.RemoteDesktop.backupID -TargetName ('C-{0}-Baseline' -f $confXML.n.Servers.OUs.RemoteDesktopOU.Name) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure Web GPO Import-GPO -BackupId $confXML.n.Servers.GPOs.WebSrv.backupID -TargetName ('C-{0}-Baseline' -f $confXML.n.Servers.OUs.WebOU.Name) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Tier Restrictions $parameters = @( $SG_Tier0Admins.SamAccountName, $SG_Tier2Admins.SamAccountName, 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', 'Guests', $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $ServersOu) -DenyInteractiveLogon $parameters -DenyRemoteInteractiveLogon $parameters Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $ServersOu) -BatchLogon $SG_T1SA.SamAccountName -ServiceLogon $SG_T1SA.SamAccountName -InteractiveLogon $SG_Tier1Admins.SamAccountName -RemoteInteractiveLogon $SG_Tier0Admins.SamAccountName ############################################################################### #region Delegation to SL_SvrAdmRight and SL_SvrOpsRight groups to SERVERS area # Get the DN of 1st level OU underneath SERVERS area $AllSubOu = Get-AdOrganizationalUnit -Filter * -SearchBase $ServersOuDn -SearchScope OneLevel | Select-Object -ExpandProperty DistinguishedName # Iterate through each sub OU and invoke delegation Foreach ($Item in $AllSubOu) { ############################################################################### # Delegation to SL_SvrAdmRight group to SERVERS area Set-AdAclDelegateComputerAdmin -Group $SL_SvrAdmRight.SamAccountName -LDAPPath $Item -QuarantineDN $ItQuarantineOuDn ############################################################################### # Delegation to SL_SvrOpsRight group on SERVERS area # Change Public Info Set-AdAclComputerPublicInfo -Group $SL_SvrOpsRight.SamAccountName -LDAPPath $Item # Change Personal Info Set-AdAclComputerPersonalInfo -Group $SL_SvrOpsRight.SamAccountName -LDAPPath $Item }#end foreach # Create/Delete OUs within Servers Set-AdAclCreateDeleteOU -Group $SL_InfraRight.SamAccountName -LDAPPath $ServersOuDn # Change OUs within Servers Set-AdAclChangeOU -Group $SL_AdRight.SamAccountName -LDAPPath $ServersOuDn #endregion ############################################################################### #endregion ############################################################################### ############################################################################### #region Create Sites OUs (Area) Write-Verbose -Message 'Creating Sites Area...' New-DelegateAdOU -ouName $SitesOu -ouPath $AdDn -ouDescription $confXML.n.Sites.OUs.SitesOU.Description # Create basic GPO for Users and Computers New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $SitesOu) -gpoScope C -gpoLinkPath $SitesOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $SitesOu) -gpoScope U -gpoLinkPath $SitesOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) # Tier Restrictions $parameters = @( $SG_Tier0Admins.SamAccountName, $SG_Tier1Admins.SamAccountName, 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', 'Guests', $AdminName, $newAdminName ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $SitesOu) -DenyInteractiveLogon $parameters -DenyRemoteInteractiveLogon $parameters Set-GpoPrivilegeRights -GpoToModify ('C-{0}-Baseline' -f $SitesOu) -BatchLogon $SG_T2SA.SamAccountName -ServiceLogon $SG_T2SA.SamAccountName -InteractiveLogon $SG_Tier2Admins.SamAccountName -RemoteInteractiveLogon $SG_Tier2Admins.SamAccountName # Create Global OU within SITES area New-DelegateAdOU -ouName $SitesGlobalOu -ouPath $SitesOuDn -ouDescription $confXML.n.Sites.OUs.OuSiteGlobal.Description New-DelegateAdOU -ouName $SitesGlobalGroupOu -ouPath $SitesGlobalOuDn -ouDescription $confXML.n.Sites.OUs.OuSiteGlobalGroups.Description New-DelegateAdOU -ouName $SitesGlobalAppAccUserOu -ouPath $SitesGlobalOuDn -ouDescription $confXML.n.Sites.OUs.OuSiteGlobalAppAccessUsers.Description # Sites OU # Create/Delete OUs within Sites Set-AdAclCreateDeleteOU -Group $SL_InfraRight.SamAccountName -LDAPPath $SitesOuDn # Sites OU # Change OUs Set-AdAclChangeOU -Group $SL_AdRight.SamAccountName -LDAPPath $SitesOuDn Write-Verbose -Message 'START APPLICATION ACCESS USER Global Delegation' ############################################################################### #region USER Site Administrator Delegation $parameters = @{ Group = $SL_GlobalAppAccUserRight.SamAccountName LDAPPath = $SitesGlobalAppAccUserOuDn } Set-AdAclDelegateUserAdmin @parameters #### GAL Set-AdAclDelegateGalAdmin @parameters Add-AdGroupNesting -Identity $SL_GlobalAppAccUserRight.SamAccountName -Members $SG_GlobalUserAdmins.SamAccountName #endregion USER Site Delegation ############################################################################### Write-Verbose -Message 'START GROUP Global Delegation' ############################################################################### #region GROUP Site Admin Delegation # Create/Delete Groups Set-AdAclCreateDeleteGroup -Group $SL_GlobalGroupRight.SamAccountName -LDAPPath $SitesGlobalGroupOuDn # Nest groups Add-AdGroupNesting -Identity $SL_GlobalGroupRight.SamAccountName -Members $SG_GlobalGroupAdmins.SamAccountName #### GAL # Change Group Properties Set-AdAclChangeGroup -Group $SL_GlobalGroupRight.SamAccountName -LDAPPath $SitesGlobalGroupOuDn #endregion GROUP Site Delegation ############################################################################### Write-Verbose 'Sites area was delegated correctly to the corresponding groups.' #endregion ############################################################################### ############################################################################### # Check if Exchange objects have to be created. Proccess if TRUE if($CreateExchange) { # Get the Config.xml file $param = @{ ConfigXMLFile = Join-Path -Path $DMscripts -ChildPath Config.xml -Resolve verbose = $true } New-ExchangeObjects @param } ############################################################################### # Check if DFS objects have to be created. Proccess if TRUE if($CreateDfs) { # Get the Config.xml file $param = @{ ConfigXMLFile = Join-Path -Path $DMscripts -ChildPath Config.xml -Resolve verbose = $true } New-DfsObjects @param } ############################################################################### # Check if Certificate Authority (PKI) objects have to be created. Proccess if TRUE if($CreateCa) { New-CaObjects -ConfigXMLFile $ConfXML } ############################################################################### # Check if Advanced Group Policy Management (AGPM) objects have to be created. Proccess if TRUE if($CreateAGPM) { New-AGPMObjects -ConfigXMLFile $ConfXML } ############################################################################### # Check if MS Local Administrator Password Service (LAPS) is to be used. Proccess if TRUE if($CreateLAPS) { #To-Do #New-LAPSobjects -PawOuDn $ItPawOuDn -ServersOuDn $ServersOuDn -SitesOuDn $SitesOuDn New-LAPSobjects -ConfigXMLFile $ConfXML } ############################################################################### # Check if DHCP is to be used. Proccess if TRUE if($CreateDHCP) { # New-DHCPobjects -ConfigXMLFile $ConfXML } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating central OU." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-CentralItOU #EndRegion - New-CentralItOU.ps1 #Region - New-DelegateAdGpo.ps1 function New-DelegateAdGpo { <# .Synopsis Creates and Links new GPO .DESCRIPTION Create new custom delegated GPO, Delegate rights to an existing group and links it to the given OU .EXAMPLE New-DelegateAdGpo MyNewGPO C "OU=Servers,OU=eguibarit,OU=local" "SL_GpoRight" .EXAMPLE New-DelegateAdGpo -gpoDescription MyNewGPO -gpoScope C -gpoLinkPath "OU=Servers,OU=eguibarit,OU=local" -GpoAdmin "SL_GpoRight" .PARAMETER gpoDescription [STRING] Description of the GPO. Used to build the name. Only Characters a-z A-Z .PARAMETER gpoScope [STRING] Scope of the GPO. U for Users and C for Computers DEFAULT is U. The non-used part of the GPO will get disabled .PARAMETER gpoLinkPath [STRING] Where to link the newly created GPO .PARAMETER GpoAdmin [STRING] Domain Local Group with GPO Rights to be assigned No Config.xml needed for this function. .INPUTS None .OUTPUTS Microsoft.GroupPolicy.Gpo .LINKS http://www.eguibarit.com .NOTES Version: 1.2 DateModified: 22/Jan/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([Microsoft.GroupPolicy.Gpo])] Param ( # Param1 GPO description, used to generate name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Description of the GPO. Used to build the name.', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $gpoDescription, # Param2 GPO scope. U = Users, C = Computers [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Scope of the GPO. U for Users and C for Computers DEFAULT is U. The non-used part of the GPO will get disabled', Position = 1)] [ValidateSet('U', 'C', ignorecase = $false)] [string] $gpoScope, # Param3 GPO Link to OU [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Where to link the newly created GPO', Position = 2)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $gpoLinkPath, # Param4 Domain Local Group with GPO Rights to be assigned [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Domain Local Group with GPO Rights to be assigned', Position = 3)] [string] $GpoAdmin ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name GroupPolicy -Verbose:$false try { # Active Directory Domain Distinguished Name If(-not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } } catch { throw } $gpoAlreadyExist = $null $gpoName = '{0}-{1}' -f $PSBoundParameters['gpoScope'], $PSBoundParameters['gpoDescription'] #$adGroupName = Get-ADGroup -Identity $GpoAdmin $dcServer = (Get-ADDomaincontroller).HostName } Process { # Check if the GPO already exist $gpoAlreadyExist = Get-GPO -Name $gpoName -ErrorAction SilentlyContinue # Clean the error if object does not exist. No need to log. $error.clear() if (-not $gpoAlreadyExist) { Write-Verbose -Message ('Policy: Create policy {0}' -f $gpoName) $parameters = @{ Name = $gpoName Comment = $gpoName Server = $dcServer ErrorAction = 'SilentlyContinue' Verbose = $true } $CurrentNewGPO = New-GPO @parameters Write-Verbose -Message '1 second pause to give AD a chance to catch up' Start-Sleep -Seconds 1 #Write-Host "Remove Authenticated Users from GPO Security Filtering" #Set-GPPermissions -Name $gpoName -PermissionLevel None -TargetName "Authenticated Users" -TargetType Group -Server $dcServer # Give Rights to SL_AdRights Write-Verbose -Message ('Add Administrators to {0}' -f $gpoName) $parameters = @{ GUID = $CurrentNewGPO.Id PermissionLevel = 'GpoEditDeleteModifySecurity' TargetName = $GpoAdmin TargetType = 'group' Server = $dcServer ErrorAction = 'SilentlyContinue' Verbose = $true } Set-GPPermissions @parameters #Write-Host "Add Editors to GPO" #Set-GPPermissions -Name $gpoName -PermissionLevel GpoEdit -TargetName $gpoEditors -TargetType group -Server $dcServer #Write-Host "Add AD-Group to Security Filtering on GPO" #Set-GPPermissions -Name $gpoName -PermissionLevel GpoApply -TargetName "$($adGroupName)" -TargetType Group -Server $dcServer If ($gpoScope -eq 'C') { Write-Verbose -Message 'Disable Policy User Settings' $CurrentNewGPO.GpoStatus = 'UserSettingsDisabled' } else { Write-Verbose -Message 'Disable Policy Computer Settings' $CurrentNewGPO.GpoStatus = 'ComputerSettingsDisabled' } Write-Verbose -Message 'Add GPO-link to corresponding OU' $parameters = @{ GUID = $CurrentNewGPO.Id Target = $PSBoundParameters['gpoLinkPath'] LinkEnabled = 'Yes' Server = $dcServer } New-GPLink @parameters # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Adding settings #Write-Host "Setting Screen saver timeout to 15 minutes" #Set-GPRegistryValue -Name $gpoName -key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" -ValueName ScreenSaveTimeOut -Type String -value 900 #Write-Host "Enable Screen Saver" #Set-GPRegistryValue -Name $gpoName -key "HKCU\Software\Policies\Microsoft\Windows\Control Panel\Desktop" -ValueName ScreenSaveActive -Type String -value 1 #Write-Host "Disable Desktop Cleanup Wizzard" #Set-GPRegistryValue -Name $gpoName -key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -ValueName NoDesktopCleanupWizard -Type Dword -value 1 #Write-Host "Remove MyMusic from Start Menu" #Set-GPRegistryValue -Name $gpoName -key "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" -ValueName NoStartMenuMymusic -Type Dword -value 1 } else { Write-Verbose -Message ('{0} Policy already exist. Skipping.' -f $gpoName) } } End { Write-Verbose -Message ('Function New-DelegateAdGpo Finished creating {0} GPO' -f $gpoName) Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' return $CurrentNewGPO } } Export-ModuleMember -Function New-DelegateAdGpo #EndRegion - New-DelegateAdGpo.ps1 #Region - New-DelegatedAdOU.ps1 function New-DelegateAdOU { <# .Synopsis Create New custom delegated AD OU .DESCRIPTION Create New custom delegated AD OU, and remove some groups as Account Operators and Print Operators .EXAMPLE New-DelegateAdOU OuName OuPath OuDescription ... .INPUTS Param1 OuName:............ [STRING] Name of the OU Param2 OuPath:............ [STRING] LDAP path where this ou will be created Param3 OuDescrition:...... [STRING] Full description of the OU Param4 OuCity:............ [STRING] Param5 OuCountry:......... [STRING] Param6 OuStreetAddress:... [STRING] Param7 OuState:........... [STRING] Param8 OuZipCode:......... [STRING] Param9 strOuDisplayName:.. [STRING] Param10 RemoveAuthenticatedUsers:.. [Switch] Remove Authenticated Users Param11 CleanACL:.......... [Switch] Remove Authenticated Users No Config.xml needed for this function. .NOTES Version: 1.2 DateModified: 01/Feb/2017 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] # https://docs.microsoft.com/en-us/dotnet/api/microsoft.activedirectory.management?view=activedirectory-management-10.0 [OutputType([Microsoft.ActiveDirectory.Management.ADOrganizationalUnit])] Param ( # Param1 Site Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the OU', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [ValidateLength(2,50)] [string] $ouName, # Param2 OU DistinguishedName (Path) [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'LDAP path where this ou will be created', Position = 1)] [ValidateNotNullOrEmpty()] [string] $ouPath, # Param3 OU Description [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 2)] [string] $ouDescription, # Param4 OU City [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 3)] [string] $ouCity, # Param5 OU Country [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 4)] [string] $ouCountry, # Param6 OU Street Address [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 5)] [string] $ouStreetAddress, # Param7 OU State [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 6)] [string] $ouState, # Param8 OU Postal Code [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 7)] [string] $ouZIPCode, # Param9 OU Display Name [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 8)] [string] $strOuDisplayName, #PARAM10 Remove Authenticated Users [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Remove Authenticated Users. CAUTION! This might affect applying GPO to objects.', Position = 9)] [switch] $RemoveAuthenticatedUsers, #PARAM11 Remove Specific Non-Inherited ACE and enable inheritance [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = ' Remove Specific Non-Inherited ACE and enable inheritance.', Position = 10)] [switch] $CleanACL ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name EguibarIT.Delegation -Verbose:$false #------------------------------------------------------------------------------ # Define the variables try { # Active Directory Domain Distinguished Name If(-not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Sites OU Distinguished Name $ouNameDN = 'OU={0},{1}' -f $PSBoundParameters['ouName'], $PSBoundParameters['ouPath'] } Catch { throw } #$Return = $null # END variables #------------------------------------------------------------------------------ } Process { # if (-not $strOuDisplayName) { $strOuDisplayName = $PSBoundParameters['ouName'] } try { # Try to get Ou $OUexists = Get-AdOrganizationalUnit -Filter { distinguishedName -eq $ouNameDN } -SearchBase $AdDn # Check if OU exists If($OUexists) { # OU it does exists Write-Warning -Message ('Organizational Unit {0} already exists.' -f $ouNameDN) } else { Write-Verbose -Message ('Creating the {0} Organizational Unit' -f $PSBoundParameters['ouName']) # Create OU $parameters = @{ Name = $PSBoundParameters['ouName'] Path = $PSBoundParameters['ouPath'] City = $PSBoundParameters['ouCity'] Country = $PSBoundParameters['ouCountry'] Description = $PSBoundParameters['ouDescription'] DisplayName = $PSBoundParameters['strOuDisplayName'] PostalCode = $PSBoundParameters['ouZIPCode'] ProtectedFromAccidentalDeletion = $true StreetAddress = $PSBoundParameters['ouStreetAddress'] State = $PSBoundParameters['ouState'] } $OUexists = New-ADOrganizationalUnit @parameters } } catch { throw } # Remove "Account Operators" and "Print Operators" built-in groups from OU. Any unknown/UnResolvable SID will be removed. Start-AdCleanOU -LDAPPath $ouNameDN -RemoveUnknownSIDs if($PSBoundParameters['CleanACL']) { Remove-SpecificACLandEnableInheritance -LDAPpath $ouNameDN } } End { Write-Verbose -Message ('Function New-DelegateAdOU finished {0}' -f $ouNameDN) Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' return $OUexists } } Export-ModuleMember -Function New-DelegatedAdOU #EndRegion - New-DelegatedAdOU.ps1 #Region - New-DelegateSiteOU.ps1 function New-DelegateSiteOU { <# .Synopsis Create New delegated Site OU .DESCRIPTION Create the new OU representing the SITE root on the pre-defined container (Sites, Country, etc.), then adding additional OU structure below to host different object types, create the corresponding managing groups and GPOs and finally delegating right to those objects. .EXAMPLE New-DelegateSiteOU -ouName "Mexico" -ouDescription "Mexico Site root" -ConfigXMLFile "C:\PsScripts\Config.xml" .INPUTS Param1 ouName:...............[String] Name of the OU corresponding to the SITE root Param2 ouDescription:........[String] Description of the OU Param3 ouCity:...............[String] Param4 ouCountry:............[String] Param5 ouStreetAddress:......[String] Param6 ouState:..............[String] Param7 ouZIPCode:............[String] Param8 CreateExchange:.......[switch] If present It will create all needed Exchange objects and containers. Param9 CreateLAPS............[switch] If present It will create all needed LAPS objects, containers and delegations. Param10 ConfigXMLFile:.......[String] Full path to the configuration.xml file This function relies on Config.xml file. .NOTES Version: 1.2 DateModified: 11/Feb/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([String])] Param ( # Param1 Site Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the OU corresponding to the SITE root', Position = 0)] [ValidateNotNullOrEmpty()] [string] $ouName, # Param2 OU Description [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Description of the OU', Position = 1)] [string] $ouDescription, # Param3 OU City [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 2)] [string] $ouCity, # Param4 OU Country [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 3)] [ValidatePattern('[a-zA-Z]*')] [ValidateLength(2,2)] [string] $ouCountry, # Param5 OU Street Address [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 4)] [string] $ouStreetAddress, # Param6 OU State [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 5)] [string] $ouState, # Param7 OU Postal Code [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 6)] [string] $ouZIPCode, # Param8 Create Exchange Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed Exchange objects and containers.', Position = 7)] [switch] $CreateExchange, # Param9 Create LAPS Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed LAPS objects, containers and delegations.', Position = 8)] [switch] $CreateLAPS, # PARAM10 full path to the configuration.xml file [Parameter(Mandatory = $true, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True, ValueFromRemainingArguments = $false, HelpMessage='Full path to the configuration.xml file', Position=9)] [string] $ConfigXMLFile ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name GroupPolicy -Verbose:$false Import-Module -name EguibarIT.Delegation -Verbose:$false #------------------------------------------------------------------------------ # Define the variables try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } Catch { throw } #################### # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 #################### # Users #################### # Groups $SG_AllSiteAdmins = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.AllSiteAdmins.Name) $SG_AllGALAdmins = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.AllGALAdmins.Name) #################### # OU DistinguishedNames # Admin Area # IT Admin OU $ItAdminOu = $confXML.n.Admin.OUs.ItAdminOU.name # IT Admin OU Distinguished Name $ItAdminOuDn = 'OU={0},{1}' -f $ItAdminOu, $AdDn # It Admin Groups OU $ItGroupsOu = $confXML.n.Admin.OUs.ItAdminGroupsOU.name # It Admin Groups OU Distinguished Name $ItGroupsOuDn = 'OU={0},{1}' -f $ItGroupsOu, $ItAdminOuDn # It Privileged Groups OU #$ItPGOu = $confXML.n.Admin.OUs.ItPrivGroupsOU.name # It Privileged Groups OU Distinguished Name #$ItPGOuDn = 'OU={0},{1}' -f $ItPGOu, $ItAdminOuDn # It Admin Rights OU $ItRightsOu = $confXML.n.Admin.OUs.ItRightsOU.name # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn # Sites Area # Sites OU $SitesOu = $confXML.n.Sites.OUs.SitesOU.name # Sites OU Distinguished Name $SitesOuDn = 'OU={0},{1}' -f $SitesOu, $AdDn # Sites GLOBAL OU #$SitesGlobalOu = $confXML.n.Sites.OUs.OuSiteGlobal.name # Sites GLOBAL OU Distinguished Name #$SitesGlobalOuDn = 'OU={0},{1}' -f $SitesGlobalOu, $SitesOuDn # Sites GLOBAL GROUPS OU #$SitesGlobalGroupOu = $confXML.n.Sites.OUs.OuSiteGlobalGroups.name # Sites GLOBAL GROUPS OU Distinguished Name #$SitesGlobalGroupOuDn = 'OU={0},{1}' -f $SitesGlobalGroupOu, $SitesGlobalOuDn # Sites GLOBAL APPACCUSERS OU #$SitesGlobalAppAccUserOu = $confXML.n.Sites.OUs.OuSiteGlobalAppAccessUsers.name # Sites GLOBAL APPACCUSERS OU Distinguished Name #$SitesGlobalAppAccUserOuDn = 'OU={0},{1}' -f $SitesGlobalAppAccUserOu, $SitesGlobalOuDn # Quarantine OU $ItQuarantineOu = $confXML.n.Admin.OUs.ItNewComputersOU.name # Quarantine OU Distinguished Name $ItQuarantineOuDn = 'OU={0},{1}' -f $ItQuarantineOu, $AdDn # Current OU DistinguishedName $ouNameDN = 'OU={0},{1}' -f $ouName, $SitesOuDn # parameters variable for splatting the CMDlets $splat = $null # END variables #------------------------------------------------------------------------------ } Process { # Checking if the OU exist is done prior calling this function. Write-Verbose -Message ('Create Site root OU {0}' -f $PSBoundParameters['ouName']) # Check if the Site OU exists If(-not(Get-AdOrganizationalUnit -Filter { distinguishedName -eq $ouNameDN } -SearchBase $AdDn)) { $splat = @{ ouName = $PSBoundParameters['ouName'] ouPath = $SitesOuDn ouDescription = $PSBoundParameters['ouDescription'] ouCity = $PSBoundParameters['ouCity'] ouCountry = $PSBoundParameters['ouCountry'] ouStreetAddress = $PSBoundParameters['ouStreetAddress'] ouState = $PSBoundParameters['ouState'] ouZIPCode = $PSBoundParameters['ouZIPCode'] strOuDisplayName = $PSBoundParameters['ouName'] } # If does not exist, create it. New-DelegateAdOU @splat } else { Write-Warning -Message ('Site {0} already exist. Continue to cleanup.' -f $PSBoundParameters['ouName']) # If OU already exist, clean it. Start-AdCleanOU -LDAPPath $ouNameDN -RemoveUnknownSIDs } Write-Verbose -Message 'Create SITE Sub-OU' ############################################################################### #region Create SITE Sub-OU # --- USER CLASS --- $splat = @{ ouName = $confXML.n.Sites.OUs.OuSiteUser.Name ouPath = $ouNameDN ouDescription = '{0} {1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteUser.description } New-DelegateAdOU @splat # --- COMPUTER CLASS --- $splat = @{ ouName = $confXML.n.Sites.OUs.OuSiteComputer.Name ouPath = $ouNameDN ouDescription = '{0} {1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteComputer.description } New-DelegateAdOU @splat $splat = @{ ouName = $confXML.n.Sites.OUs.OuSiteLaptop.Name ouPath = $ouNameDN ouDescription = '{0} {1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLaptop.description } New-DelegateAdOU @splat # --- GROUP CLASS --- $splat = @{ ouName = $confXML.n.Sites.OUs.OuSiteGroup.Name ouPath = $ouNameDN ouDescription = '{0} {1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteGroup.description } New-DelegateAdOU @splat # --- VOLUME CLASS --- $splat = @{ ouName = $confXML.n.Sites.OUs.OuSiteShares.Name ouPath = $ouNameDN ouDescription = '{0} {1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteShares.description } New-DelegateAdOU @splat # --- PRINTQUEUE CLASS --- $splat = @{ ouName = $confXML.n.Sites.OUs.OuSitePrintQueue.Name ouPath = $ouNameDN ouDescription = '{0} {1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSitePrintQueue.description } New-DelegateAdOU @splat #endregion END ############################################################################### Write-Verbose -Message ('Create requiered groups for the site {0}' -f $PSBoundParameters['ouName']) ############################################################################### #region Create the required Right's Local Domain groups # Iterate through all Site-LocalGroups child nodes Foreach($node in $confXML.n.Sites.LG.ChildNodes) { Write-Verbose -Message ('Create group {0}' -f ('{0}{1}{2}{1}{3}' -f $NC['sl'], $NC['Delim'], $node.Name, $PSBoundParameters['ouName'])) $parameters = @{ Name = '{0}{1}{2}{1}{3}' -f $NC['sl'], $NC['Delim'], $node.Name, $PSBoundParameters['ouName'] GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = '{0} {1}' -f $PSBoundParameters['ouName'], $node.DisplayName Path = $ItRightsOuDn Description = '{0} {1}' -f $PSBoundParameters['ouName'], $node.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $node.Name)" -Value (New-AdDelegatedGroup @parameters) -Force } #endregion ############################################################################### ############################################################################### #region Create the required Admin Global groups # Iterate through all Site-GlobalGroups child nodes Foreach($node in $confXML.n.Sites.GG.ChildNodes) { Write-Verbose -Message ('Create group {0}' -f ('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $node.Name, $PSBoundParameters['ouName'])) $parameters = @{ Name = '{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $node.Name, $PSBoundParameters['ouName'] GroupCategory = 'Security' GroupScope = 'Global' DisplayName = '{0} {1}' -f $PSBoundParameters['ouName'], $node.DisplayName Path = $ItGroupsOuDn Description = '{0} {1}' -f $PSBoundParameters['ouName'], $node.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } New-Variable -Name "$('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $node.Name)" -Value (New-AdDelegatedGroup @parameters) -Force } #endregion ############################################################################### Write-Verbose -Message 'Add group membership & nesting' ############################################################################### #region Add group membership & nesting #region NESTING Global groups into Domain Local Groups -> order Less privileged to more privileged Add-AdGroupNesting -Identity $SL_PwdRight -Members $SG_PwdAdmins, $SG_GALAdmins, $SG_SiteAdmins if($PSBoundParameters['CreateSrvContainer']) { Add-AdGroupNesting -Identity $SL_LocalServerRight -Members $SG_LocalServerAdmins } Add-AdGroupNesting -Identity $SL_PcRight -Members $SG_ComputerAdmins, $SG_SiteAdmins Add-AdGroupNesting -Identity $SL_GroupRight -Members $SG_GroupAdmins, $SG_SiteAdmins Add-AdGroupNesting -Identity $SL_CreateUserRight -Members $SG_UserAdmins, $SG_SiteAdmins Add-AdGroupNesting -Identity $SL_GALRight -Members $SG_GALAdmins, $SG_SiteAdmins <# VIOLATES Tiering model Add-AdGroupNesting -Identity $SL_LocalServerRight -Members $SG_SiteAdmins #> Add-AdGroupNesting -Identity $SL_SiteRight -Members $SG_SiteAdmins #endregion #region NESTING Global groups into Global Groups -> order Less privileged to more privileged Add-AdGroupNesting -Identity $SG_PwdAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.ServiceDesk.Name) if($PSBoundParameters['CreateSrvContainer']) { Add-AdGroupNesting -Identity $SG_LocalServerAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Servers.GG.ServerAdmins.Name) } Add-AdGroupNesting -Identity $SG_ComputerAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.GlobalPcAdmins.Name) Add-AdGroupNesting -Identity $SG_GroupAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.GlobalGroupAdmins.Name) Add-AdGroupNesting -Identity $SG_UserAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.GlobalUserAdmins.Name) Add-AdGroupNesting -Identity $SG_GALAdmins -Members $SG_AllGALAdmins Add-AdGroupNesting -Identity $SG_SiteAdmins -Members $SG_AllSiteAdmins #endregion #endregion ############################################################################### <#Write-Verbose -Message 'Nesting to Built-In groups' ############################################################################### #region Nest Groups - Delegate Rights through Builtin groups # http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-and-windows-part-1-understanding-privileged-groups-in-ad.aspx Add-AdGroupNesting -Identity 'Remote Desktop Users' -Members $SG_SiteAdmins #endregion ############################################################################### #> Write-Verbose -Message 'Create basic GPO' ############################################################################### #region Create basic GPO # Create Desktop Baseline $splat = @{ gpoDescription = '{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteComputer.Name gpoScope = 'C' gpoLinkPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteComputer.Name, $ouNameDN GpoAdmin = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) } New-DelegateAdGpo @splat # Create Laptop-Baseline Baseline $splat = @{ gpoDescription = '{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLaptop.Name gpoScope = 'C' gpoLinkPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLaptop.Name, $ouNameDN GpoAdmin = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) } New-DelegateAdGpo @splat # Create Users Baseline $splat = @{ gpoDescription = '{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteUser.Name gpoScope = 'U' gpoLinkPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteUser.Name, $ouNameDN GpoAdmin = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) } New-DelegateAdGpo @splat #endregion Create basic GPO ############################################################################### Write-Verbose -Message 'Configure GPO' ############################################################################### #region Configure GPO # Configure Users $splat = @{ BackupId = $confXML.n.Sites.OUs.OuSiteUser.backupID TargetName = 'U-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteUser.Name path = Join-Path -Path $DMscripts -ChildPath SecTmpl } Import-GPO @splat if($PSBoundParameters['CreateSrvContainer']) { # Configure File-Print Server Baseline GPO $splat = @{ BackupId = $confXML.n.Sites.OUs.OuSiteFilePrint.backupID TargetName = 'C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteFilePrint.Name path = Join-Path -Path $DMscripts -ChildPath SecTmpl } Import-GPO @splat # File-Print Baseline Tiering Restrictions $splat = @( 'Schema Admins', 'Enterprise Admins', 'Domain Admins', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name, 'Guests' ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteFilePrint.Name) -DenyNetworkLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name), 'Guests' ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteFilePrint.Name) -DenyInteractiveLogon $splat -DenyRemoteInteractiveLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name), 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteFilePrint.Name) -DenyBatchLogon $splat -DenyServiceLogon $splat $splat = ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteFilePrint.Name) -BatchLogon $splat -ServiceLogon $splat # Configure Local Servers Baseline $splat = @{ BackupId = $confXML.n.Sites.OUs.OuSiteLocalServer.backupID TargetName = 'C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLocalServer.Name path = Join-Path -Path $DMscripts -ChildPath SecTmpl } Import-GPO @splat # Local Servers Baseline Tiering Restrictions $splat = @( 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLocalServer.Name) -DenyNetworkLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name), 'Guests' ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLocalServer.Name) -DenyInteractiveLogon $splat -DenyRemoteInteractiveLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name), 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLocalServer.Name) -DenyBatchLogon $splat -DenyServiceLogon $splat $splat = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLocalServer.Name) -BatchLogon $splat -ServiceLogon $splat } # Configure Desktop Baseline $splat = @{ BackupId = $confXML.n.Sites.OUs.OuSiteComputer.backupID TargetName = 'C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteComputer.Name path = Join-Path -Path $DMscripts -ChildPath SecTmpl } Import-GPO @splat # Desktop Baseline Tiering Restrictions $splat = @( 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteComputer.Name) -DenyNetworkLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name), 'Guests' ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteComputer.Name) -DenyInteractiveLogon $splat -DenyRemoteInteractiveLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name), 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteComputer.Name) -DenyBatchLogon $splat -DenyServiceLogon $splat $splat = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteComputer.Name) -BatchLogon $splat -ServiceLogon $splat # Configure Laptop Baseline $splat = @{ BackupId = $confXML.n.Sites.OUs.OuSiteLaptop.backupID TargetName = 'C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLaptop.Name path = Join-Path -Path $DMscripts -ChildPath SecTmpl } Import-GPO @splat # Laptop Baseline Tiering Restrictions $splat = @( 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLaptop.Name) -DenyNetworkLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name), 'Guests' ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLaptop.Name) -DenyInteractiveLogon $splat -DenyRemoteInteractiveLogon $splat $splat = @( ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1ServiceAccount.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier0Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier1Admins.Name), ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2Admins.Name), 'Schema Admins', 'Enterprise Admins', 'Domain Admins', 'Administrators', 'Account Operators', 'Backup Operators', 'Print Operators', 'Server Operators', 'Guests', $confXML.n.Admin.users.Admin.name, $confXML.n.Admin.users.newAdmin.name ) Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLaptop.Name) -DenyBatchLogon $splat -DenyServiceLogon $splat $splat = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.Tier2ServiceAccount.Name Set-GpoPrivilegeRights -GpoToModify ('C-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteLaptop.Name) -BatchLogon $splat -ServiceLogon $splat #endregion Configure GPO ############################################################################### Write-Verbose -Message 'Delegate GPO' ############################################################################### #region Delegate GPO if($PSBoundParameters['CreateSrvContainer']) { Write-Verbose -Message ('Add Local Admin to new {0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteFilePrint.Name) $splat = @{ Name = ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteFilePrint.Name) PermissionLevel = 'GpoEdit' TargetName = $SG_SiteAdmins.SamAccountName TargetType = 'group' ErrorAction = 'SilentlyContinue' Verbose = $true } Set-GPPermissions @splat Write-Verbose -Message ('Add Local Admin to new {0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLocalServer.Name) $splat = @{ Name = ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLocalServer.Name) PermissionLevel = 'GpoEdit' TargetName = $SG_SiteAdmins.SamAccountName TargetType = 'group' ErrorAction = 'SilentlyContinue' Verbose = $true } Set-GPPermissions @splat } # Give Rights to SG_SiteAdmin_XXXX to $ouName + -Desktop Write-Verbose -Message ('Add Local Admin to new {0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteComputer.Name) $splat = @{ Name = ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteComputer.Name) PermissionLevel = 'GpoEdit' TargetName = $SG_SiteAdmins.SamAccountName TargetType = 'group' ErrorAction = 'SilentlyContinue' Verbose = $true } Set-GPPermissions @splat Write-Verbose -Message ('Add Local Admin to new {0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLaptop.Name) $splat = @{ Name = ('C-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteLaptop.Name) PermissionLevel = 'GpoEdit' TargetName = $SG_SiteAdmins.SamAccountName TargetType = 'group' ErrorAction = 'SilentlyContinue' Verbose = $true } Set-GPPermissions @splat Write-Verbose -Message ('Add Local Admin to new {0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteUser.Name) $splat = @{ Name = ('U-{0}-{1}' -f $PSBoundParameters['ouName'], $confXML.n.Sites.OUs.OuSiteUser.Name) PermissionLevel = 'GpoEdit' TargetName = $SG_SiteAdmins.SamAccountName TargetType = 'group' ErrorAction = 'SilentlyContinue' Verbose = $true } Set-GPPermissions @splat #endregion Delegate GPO ############################################################################### Write-Verbose -Message 'Rights delegation' # --- Exchange Related ############################################################################### If($PSBoundParameters['CreateExchange']) { Start-AdDelegateSite -ConfigXMLFile $ConfigXMLFile -ouName $ouName -QuarantineDN $ItQuarantineOuDn -CreateExchange #create Sub-OUs # --- USER CLASS --- New-DelegateAdOU -ouName $confXML.n.Sites.OUs.OuSiteMailbox.Name -ouPath $ouNameDN -ouDescription ('{0} {1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteMailbox.Description) # --- GROUP CLASS --- New-DelegateAdOU -ouName $confXML.n.Sites.OUs.OuSiteDistGroup.Name -ouPath $ouNameDN -ouDescription ('{0} {1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteDistGroup.Description) # --- CONTACT CLASS --- New-DelegateAdOU -ouName $confXML.n.Sites.OUs.OuSiteContact.Name -ouPath $ouNameDN -ouDescription ('{0} {1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteContact.Description) #create Basic Gpo # Create Mailboxes Baseline $splat = @{ gpoDescription = '{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteMailbox.Name gpoScope = 'U' gpoLinkPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteMailbox.Name, $ouNameDN GpoAdmin = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) } New-DelegateAdGpo @splat # Delegate GPO Write-Verbose -Message ('Add Local Admin to new {0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteMailbox.Name) $splat = @{ Name = ('U-{0}-{1}' -f $ouName, $confXML.n.Sites.OUs.OuSiteMailbox.Name) PermissionLevel = 'GpoEdit' TargetName = $SG_SiteAdmins.SamAccountName TargetType = 'group' ErrorAction = 'SilentlyContinue' } Set-GPPermissions @splat }# end if CreateExchange else { Start-AdDelegateSite -ConfigXMLFile $ConfigXMLFile -ouName $ouName -QuarantineDN $ItQuarantineOuDn } # --- LAPS Related ############################################################################### If($PSBoundParameters['CreateLAPS']) { # Desktop LAPS delegation Set-AdAclLaps -ResetGroup $SL_PwdRight.SamAccountName -ReadGroup $SL_PwdRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteComputer.Name, $ouNameDN) # Laptop LAPS delegation Set-AdAclLaps -ResetGroup $SL_PwdRight.SamAccountName -ReadGroup $SL_PwdRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLaptop.Name, $ouNameDN) If($PsBoundParameters['CreateSrvContainer']) { # File-Print LAPS delegation Set-AdAclLaps -ResetGroup $SL_LocalServerRight.SamAccountName -ReadGroup $SL_LocalServerRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteFilePrint.Name, $ouNameDN) # Local Server LAPS delegation Set-AdAclLaps -ResetGroup $SL_LocalServerRight.SamAccountName -ReadGroup $SL_LocalServerRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLocalServer.Name, $ouNameDN) } } } End { Write-Verbose -Message ("Function $($MyInvocation.InvocationName) finished creating creating Site {0}" -f $PSBoundParameters['ouName']) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-DelegateSiteOU #EndRegion - New-DelegateSiteOU.ps1 #Region - New-DfsObjects.ps1 Function New-DfsObjects { <# .Synopsis Create DFS Objects and Delegations .DESCRIPTION Create the DFS Objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-DfsObjects .INPUTS .NOTES Version: 1.3 DateModified: 01/Feb/2018 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name EguibarIT.Delegation -Verbose:$false ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 # Organizational Units Distinguished Names # IT Admin OU $ItAdminOu = $confXML.n.Admin.OUs.ItAdminOU.name # IT Admin OU Distinguished Name $ItAdminOuDn = 'OU={0},{1}' -f $ItAdminOu, $AdDn # It Privileged Groups OU $ItPGOu = $confXML.n.Admin.OUs.ItPrivGroupsOU.name # It Privileged Groups OU Distinguished Name $ItPGOuDn = 'OU={0},{1}' -f $ItPGOu, $ItAdminOuDn # It Admin Rights OU $ItRightsOu = $confXML.n.Admin.OUs.ItRightsOU.name # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn $parameters = $null #endregion Declarations ################################################################################ } Process { # Check if feature is installed, if not then proceed to install it. If(-not((Get-WindowsFeature -Name FS-DFS-Namespace).Installed)) { Install-WindowsFeature -Name FS-DFS-Namespace -IncludeAllSubFeature } If(-not((Get-WindowsFeature -Name FS-DFS-Replication).Installed)) { Install-WindowsFeature -Name FS-DFS-Replication -IncludeAllSubFeature } ############################################################################### # Create OU Admin groups $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.AdminXtra.GG.DfsAdmins.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.AdminXtra.GG.DfsAdmins.DisplayName Path = $ItPGOuDn Description = $confXML.n.AdminXtra.GG.DfsAdmins.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SG_DfsAdmins = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.DfsRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.DfsRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.DfsRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_DfsRight = New-AdDelegatedGroup @parameters # Apply the PSO to the SL_DfsRights and SG_DfsAdmin Group Add-ADFineGrainedPasswordPolicySubject -Identity $confXML.n.Admin.PSOs.ItAdminsPSO.Name -Subjects $SG_DfsAdmins, $SL_DfsRight ############################################################################### # Nest Groups - Security for RODC # Avoid having privileged or semi-privileged groups copy to RODC Add-AdGroupMember -Identity 'Denied RODC Password Replication Group' -Members $SG_DfsAdmins, $SL_DfsRight ############################################################################### # Nest Groups - Extend Rights through delegation model groups Add-AdGroupNesting -Identity $SL_DfsRight -Members $SG_DfsAdmins Add-AdGroupNesting -Identity $SG_DfsAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.AdAdmins.Name) ############################################################################### # START Delegation to SL_InfraRights group on ADMIN area # Distributed File System # Full control over DFS-Configuration & DFSR-GlobalSettings Set-AdAclFullControlDFS -Group $SL_DfsRight.SamAccountName } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) created DFS objects and Delegations successfully." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-DfsObjects #EndRegion - New-DfsObjects.ps1 #Region - New-DhcpObjects.ps1 Function New-DHCPobjects { <# .Synopsis Create DHCP Objects and Delegations .DESCRIPTION Create the DHCP Objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-DHCPobjects .INPUTS Param1 ConfigXMLFile:..[STRING] Full path to the configuration.xml file Param2 DMscripts:......[String] Full path to the Delegation Model Scripts Directory .NOTES Version: 1.0 DateModified: 29/Oct/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module ActiveDirectory -Verbose:$false Import-Module EguibarIT.Delegation -Verbose:$false ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 $parameters = $null # Organizational Units Distinguished Names # IT Admin OU $ItAdminOu = $confXML.n.Admin.OUs.ItAdminOU.name # IT Admin OU Distinguished Name $ItAdminOuDn = 'OU={0},{1}' -f $ItAdminOu, $AdDn # It Privileged Groups OU $ItPGOu = $confXML.n.Admin.OUs.ItPrivGroupsOU.name # It Privileged Groups OU Distinguished Name $ItPGOuDn = 'OU={0},{1}' -f $ItPGOu, $ItAdminOuDn # It Admin Rights OU $ItRightsOu = $confXML.n.Admin.OUs.ItRightsOU.name # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn #endregion Declarations ################################################################################ } Process { ############################################################################### # Create OU Admin groups $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.AdminXtra.GG.DHCPAdmins.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.AdminXtra.GG.DHCPAdmins.DisplayName Path = $ItPGOuDn Description = $confXML.n.AdminXtra.GG.DHCPAdmins.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SG_DHCPAdmins = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.DHCPRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.DHCPRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.DHCPRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_DHCPRight = New-AdDelegatedGroup @parameters # Apply the PSO to the SL_DfsRights and SG_DfsAdmin Group Add-ADFineGrainedPasswordPolicySubject -Identity $confXML.n.Admin.PSOs.ItAdminsPSO.Name -Subjects $SG_DHCPAdmins, $SL_DHCPRight ############################################################################### # Nest Groups - Security for RODC # Avoid having privileged or semi-privileged groups copy to RODC Add-AdGroupMember -Identity 'Denied RODC Password Replication Group' -Members $SG_DHCPAdmins, $SL_DHCPRight ############################################################################### # Nest Groups - Extend Rights through delegation model groups Add-AdGroupNesting -Identity $SL_DHCPRight -Members $SG_DHCPAdmins Add-AdGroupNesting -Identity $SG_DHCPAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.AdAdmins.Name) ############################################################################### # START Delegation to SL_DHCPRight # Dynamic Host Configuration Protocol (DHCP) Set-AdAclFullControlDHCP -Group $SL_DHCPRight.SamAccountName } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) created DHCP objects and Delegations successfully." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-DhcpObjects #EndRegion - New-DhcpObjects.ps1 #Region - New-EitAdSite.ps1 function New-EitAdSite { <# .Synopsis Create new AD Site .DESCRIPTION Create new AD Site .EXAMPLE New-EitAdSite -NewSiteName $SiteName .INPUTS Param1 NewSiteName - Name for the new site. .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([string])] Param ( # Param1 New Site name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Add help message for user', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $NewSiteName ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false #Get a reference to the RootDSE of the current domain Write-Verbose -Message 'Get the Root DSE of the forest' $ADConfigurationNamingContext = ([ADSI]'LDAP://RootDSE').configurationNamingContext.ToString() # Get the Sites container $ADSiteDN = "CN=Sites,$ADConfigurationNamingContext" Write-Verbose -Message "Set necessary site variables `r " $NewADSiteDN = 'CN={0},{1}' -f $PSBoundParameters['NewSiteName'], $ADSiteDN } Process { If (Test-Path -Path AD:$NewADSiteDN) { Write-Warning -Message ('The site {0} already exist. Please review the name and try again' -f $PSBoundParameters['NewSiteName']) } else { Write-Verbose -Message 'Create New Site Object `r ' TRY { New-ADObject -Name $PSBoundParameters['NewSiteName'] -Path $ADSiteDN -Type Site } CATCH { Write-Warning -Message ('An error occured while attempting to create the new site {0} in the AD Site Path: {1} `r ' -f $PSBoundParameters['NewSiteName'], $ADSiteDN) } $SiteCreationCheck = Test-Path -Path AD:$NewADSiteDN IF ($SiteCreationCheck -eq $false) { Write-Warning -Message ('Failed to create the new site {0} `r ' -f $PSBoundParameters['NewSiteName']) } ELSE { ## OPEN ELSE Site Object created successfully Write-Verbose -Message 'Create New Site Object Child Objects (NTDS Site Settings & Servers Container) `r ' TRY { ## OPEN TRY Create New Site Object Child Objects (NTDS Site Settings & Servers Container) New-ADObject -Name 'NTDS Site Settings' -Path $NewADSiteDN -Type NTDSSiteSettings New-ADObject -Name 'Servers' -Path $NewADSiteDN -Type serversContainer Write-Verbose -Message 'Get New AD Site as variable `r ' $NewADSiteInfo = Get-ADObject $NewADSiteDN } ## CLOSE TRY Create New Site Object Child Objects (NTDS Site Settings & Servers Container) CATCH { Write-Warning -Message ('An error occured while attempting to create site {0} child objects in the AD Site Path: {1} `r ' -f $PSBoundParameters['NewSiteName'], $NewADSiteDN) } }#end elseIf }#end elseIf } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating new AD Site." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-EitAdSite #EndRegion - New-EitAdSite.ps1 #Region - New-ExchangeObjects.ps1 Function New-ExchangeObjects { <# .Synopsis Create Exchange Objects and Containers .DESCRIPTION Create the Exchange OU structure and objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-ExchangeObjects .INPUTS .NOTES Version: 1.0 DateModified: 19/Apr/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module -name ServerManager -Verbose:$false Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name GroupPolicy -Verbose:$false Import-Module -name EguibarIT.Delegation -Verbose:$false ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 # Organizational Units Distinguished Names # IT Admin OU New-Variable -Name 'ItAdminOu' -Value $confXML.n.Admin.OUs.ItAdminOU.name -Option ReadOnly -Force # IT Admin OU Distinguished Name New-Variable -Name 'ItAdminOuDn' -Value ('OU={0},{1}' -f $ItAdminOu, $AdDn) -Option ReadOnly -Force # It Admin Groups OU #$ItGroupsOu = $confXML.n.Admin.OUs.ItAdminGroupsOU.name # It Admin Groups OU Distinguished Name #$ItGroupsOuDn = 'OU={0},{1}' -f $ItGroupsOu, $ItAdminOuDn # It Privileged Groups OU $ItPGOu = $confXML.n.Admin.OUs.ItPrivGroupsOU.name # It Privileged Groups OU Distinguished Name $ItPGOuDn = 'OU={0},{1}' -f $ItPGOu, $ItAdminOuDn # It Admin Rights OU $ItRightsOu = $confXML.n.Admin.OUs.ItRightsOU.name # It Admin Rights OU Distinguished Name $ItRightsOuDn = 'OU={0},{1}' -f $ItRightsOu, $ItAdminOuDn # It Admin Exchange OU $ItExchangeOu = $confXML.n.AdminXtra.OUs.ItExchangeOU.name # It Admin Exchange OU Distinguished Name $ItExchangeOuDn = 'OU={0},{1}' -f $ItExchangeOu, $ItAdminOuDn # It Admin Exchange Distribution Groups OU $ItExDistGroupsOu = $confXML.n.AdminXtra.OUs.ItExDistGroups.name # It Admin Exchange Distribution Groups OU Distinguished Name $ItExDistGroupsOuDn = 'OU={0},{1}' -f $ItExDistGroupsOu, $ItExchangeOuDn # It Admin Exchange External Contacts OU #$ItExExternalContactOu = $confXML.n.AdminXtra.OUs.ItExExternalContact.name # It Admin Exchange External Contacts OU Distinguished Name #$ItExExternalContactOuDn = 'OU={0},{1}' -f $ItExExternalContactOu, $ItExchangeOuDn # It Admin Exchange Resource OU #$ItExResourceOu = $confXML.n.AdminXtra.OUs.ItExResource.name # It Admin Exchange Resource OU Distinguished Name #$ItExResourceOuDn = 'OU={0},{1}' -f $ItExResourceOu, $ItExchangeOuDn # It Admin Exchange Shared OU #$ItExSharedOu = $confXML.n.AdminXtra.OUs.ItExShared.name # It Admin Exchange Shared OU Distinguished Name #$ItExSharedOuDn = 'OU={0},{1}' -f $ItExSharedOu, $ItExchangeOuDn # It Admin Exchange Equipment OU #$ItExEquipOu = $confXML.n.AdminXtra.OUs.ItExEquip.name # It Admin Exchange Equipment OU Distinguished Name #$ItExEquipOuDn = 'OU={0},{1}' -f $ItExEquipOu, $ItExchangeOuDn # Servers OU $ServersOu = $confXML.n.Servers.OUs.ServersOU.name # Servers OU Distinguished Name $ServersOuDn = 'OU={0},{1}' -f $ServersOu, $AdDn # Exchange Servers $ExServersOu = $confXML.n.Servers.OUs.ExchangeOU.Name # Exchange Servers Distinguished Name $ExServersOuDn = 'OU={0},{1}' -f $ExServersOu, $ServersOuDn # Exchange CAS Servers $ExCasOu = $confXML.n.Servers.OUs.ExCasOU.Name # Exchange CAS Servers Distinguished Name $ExCasOuDn = 'OU={0},{1}' -f $ExCasOu, $ExServersOuDn # Exchange HUB Servers $ExHubOu = $confXML.n.Servers.OUs.ExHubOU.Name # Exchange HUB Servers Distinguished Name $ExHubOuDn = 'OU={0},{1}' -f $ExHubOu, $ExServersOuDn # Exchange EDGE Servers $ExEdgeOu = $confXML.n.Servers.OUs.ExEdgeOU.Name # Exchange EDGE Servers Distinguished Name $ExEdgeOuDn = 'OU={0},{1}' -f $ExEdgeOu, $ExServersOuDn # Exchange MAILBOX Servers $ExMailboxOu = $confXML.n.Servers.OUs.ExMailboxOU.Name # Exchange MAILBOX Servers Distinguished Name $ExMailboxOuDn = 'OU={0},{1}' -f $ExMailboxOu, $ExServersOuDn # Exchange MIXED ROLE Servers $ExMixedOu = $confXML.n.Servers.OUs.ExMixedRolOU.Name # Exchange MIXED ROLE Servers Distinguished Name $ExMixedOuDn = 'OU={0},{1}' -f $ExMixedOu, $ExServersOuDn # Quarantine OU $ItQuarantineOu = $confXML.n.Admin.OUs.ItNewComputersOU.name # Quarantine OU Distinguished Name $ItQuarantineOuDn = 'OU={0},{1}' -f $ItQuarantineOu, $AdDn #endregion Declarations ################################################################################ } Process { ############################################################################### # Create Sub-OUs for admin New-DelegateAdOU -ouName $ItExchangeOu -ouPath $ItAdminOuDn -ouDescription $confXML.n.AdminXtra.OUs.ItExchangeOU.Description ############################################################################### # Create Sub-Sub-OUs New-DelegateAdOU -ouName $ItExDistGroupsOu -ouPath $ItExchangeOuDn -ouDescription $confXML.n.AdminXtra.OUs.ItExDistGroups.Description New-DelegateAdOU -ouName $ItExExternalContactOu -ouPath $ItExchangeOuDn -ouDescription $confXML.n.AdminXtra.OUs.ItExExternalContact.Description New-DelegateAdOU -ouName $ItExResourceOu -ouPath $ItExchangeOuDn -ouDescription $confXML.n.AdminXtra.OUs.ItExResource.Description New-DelegateAdOU -ouName $ItExSharedOu -ouPath $ItExchangeOuDn -ouDescription $confXML.n.AdminXtra.OUs.ItExShared.Description New-DelegateAdOU -ouName $ItExEquipOu -ouPath $ItExchangeOuDn -ouDescription $confXML.n.AdminXtra.OUs.ItExEquip.Description ############################################################################### # Create OU Admin groups $parameters = @{ Name = '{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.AdminXtra.GG.ExAdmins.Name GroupCategory = 'Security' GroupScope = 'Global' DisplayName = $confXML.n.AdminXtra.GG.ExAdmins.DisplayName Path = $ItPGOuDn Description = $confXML.n.AdminXtra.GG.ExAdmins.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SG_ExAdmins = New-AdDelegatedGroup @parameters $parameters = @{ Name = '{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.AdminXtra.LG.ExRight.Name GroupCategory = 'Security' GroupScope = 'DomainLocal' DisplayName = $confXML.n.AdminXtra.LG.ExRight.DisplayName Path = $ItRightsOuDn Description = $confXML.n.AdminXtra.LG.ExRight.Description ProtectFromAccidentalDeletion = $True RemoveAccountOperators = $True RemoveEveryone = $True RemovePreWin2000 = $True } $SL_ExRight = New-AdDelegatedGroup @parameters ############################################################################### # Create a New Fine Grained Password Policy for Admins Accounts # and apply the PSO to the account () Add-ADFineGrainedPasswordPolicySubject -Identity $confXML.n.Admin.PSOs.ItAdminsPSO.Name -Subjects $SG_ExAdmins.SamAccountName, $SL_ExRight.SamAccountName ############################################################################### # Nest Groups - Security for RODC # Avoid having privileged or semi-privileged groups copy to RODC Add-AdGroupMember -Identity 'Denied RODC Password Replication Group' -Members $SG_ExAdmins, $SL_ExRight ############################################################################### # Nest Groups - Extend Rights Add-AdGroupNesting -Identity $SG_ExAdmins -Members ('{0}{1}{2}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.GG.InfraAdmins.Name) Add-AdGroupNesting -Identity $SL_ExRight -Members $SG_ExAdmins ############################################################################### # START Delegation to SL_InfraRights group on ADMIN area $SL_InfraRight = (Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.InfraRight.Name)).SamAccountName $SL_AdRight = (Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.AdRight.Name)).SamAccountName $SL_PGM = (Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.PGM.Name)).SamAccountName # Administration OU Set-AdAclCreateDeleteGroup -Group $SL_InfraRight -LDAPPath $ItExDistGroupsOuDn Set-AdAclCreateDeleteGroup -Group $SL_PGM -LDAPPath $ItExDistGroupsOuDn Set-AdAclCreateDeleteGroup -Group $SL_ExRight.SamAccountName -LDAPPath $ItExDistGroupsOuDn ############################################################################### # START Delegation to SL_AdRights group on ADMIN area $SL_AdRights = (Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.AdRight.Name)).SamAccountName # Administration OU Set-AdAclChangeGroup -Group $SL_AdRights.SamAccountName -LDAPPath $ItExDistGroupsOuDn Set-AdAclChangeGroup -Group $SL_PGM -LDAPPath $ItExDistGroupsOuDn Set-AdAclChangeGroup -Group $SL_ExRight.SamAccountName -LDAPPath $ItExDistGroupsOuDn ############################################################################### # Create Servers and Sub OUs # Create Sub-Sub-OUs for Exchange New-DelegateAdOU -ouName $ExServersOu -ouPath $ServersOuDn -ouDescription $confXML.n.Servers.OUs.ExchangeOU.Description New-DelegateAdOU -ouName $ExCasOu -ouPath $ExServersOuDn -ouDescription $confXML.n.Servers.OUs.ExCasOU.Description New-DelegateAdOU -ouName $ExHubOu -ouPath $ExServersOuDn -ouDescription $confXML.n.Servers.OUs.ExHubOU.Description New-DelegateAdOU -ouName $ExEdgeOu -ouPath $ExServersOuDn -ouDescription $confXML.n.Servers.OUs.ExEdgeOU.Description New-DelegateAdOU -ouName $ExMailboxOu -ouPath $ExServersOuDn -ouDescription $confXML.n.Servers.OUs.ExMailboxOU.Description New-DelegateAdOU -ouName $ExMixedOu -ouPath $ExServersOuDn -ouDescription $confXML.n.Servers.OUs.ExMixedRolOU.Description ############################################################################### # START Delegation to SL_InfraRights group on SERVERS area # Servers OU # Create/Delete Computers Set-AdAclDelegateComputerAdmin -Group $SL_InfraRight.SamAccountName -LDAPPath $ExServersOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_InfraRight.SamAccountName -LDAPPath $ExCasOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_InfraRight.SamAccountName -LDAPPath $ExHubOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_InfraRight.SamAccountName -LDAPPath $ExEdgeOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_InfraRight.SamAccountName -LDAPPath $ExMailboxOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_InfraRight.SamAccountName -LDAPPath $ExMixedOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_ExRight.SamAccountName -LDAPPath $ExServersOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_ExRight.SamAccountName -LDAPPath $ExCasOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_ExRight.SamAccountName -LDAPPath $ExHubOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_ExRight.SamAccountName -LDAPPath $ExEdgeOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_ExRight.SamAccountName -LDAPPath $ExMailboxOuDn -QuarantineDN $ItQuarantineOuDn Set-AdAclDelegateComputerAdmin -Group $SL_ExRight.SamAccountName -LDAPPath $ExMixedOuDn -QuarantineDN $ItQuarantineOuDn ############################################################################### # START Delegation to SL_AdRights group # Servers OU # Change Public Info Set-AdAclComputerPublicInfo -Group $SL_AdRight -LDAPPath $ExServersOuDn Set-AdAclComputerPublicInfo -Group $SL_AdRight -LDAPPath $ExCasOuDn Set-AdAclComputerPublicInfo -Group $SL_AdRight -LDAPPath $ExHubOuDn Set-AdAclComputerPublicInfo -Group $SL_AdRight -LDAPPath $ExEdgeOuDn Set-AdAclComputerPublicInfo -Group $SL_AdRight -LDAPPath $ExMailboxOuDn Set-AdAclComputerPublicInfo -Group $SL_AdRight -LDAPPath $ExMixedOuDn Set-AdAclComputerPublicInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExServersOuDn Set-AdAclComputerPublicInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExCasOuDn Set-AdAclComputerPublicInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExHubOuDn Set-AdAclComputerPublicInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExEdgeOuDn Set-AdAclComputerPublicInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExMailboxOuDn Set-AdAclComputerPublicInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExMixedOuDn # Change Personal Info Set-AdAclComputerPersonalInfo -Group $SL_AdRight -LDAPPath $ExServersOuDn Set-AdAclComputerPersonalInfo -Group $SL_AdRight -LDAPPath $ExCasOuDn Set-AdAclComputerPersonalInfo -Group $SL_AdRight -LDAPPath $ExHubOuDn Set-AdAclComputerPersonalInfo -Group $SL_AdRight -LDAPPath $ExEdgeOuDn Set-AdAclComputerPersonalInfo -Group $SL_AdRight -LDAPPath $ExMailboxOuDn Set-AdAclComputerPersonalInfo -Group $SL_AdRight -LDAPPath $ExMixedOuDn Set-AdAclComputerPersonalInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExServersOuDn Set-AdAclComputerPersonalInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExCasOuDn Set-AdAclComputerPersonalInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExHubOuDn Set-AdAclComputerPersonalInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExEdgeOuDn Set-AdAclComputerPersonalInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExMailboxOuDn Set-AdAclComputerPersonalInfo -Group $SL_ExRight.SamAccountName -LDAPPath $ExMixedOuDn ############################################################################### # Create basic GPOs for different types under Servers New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $ExCasOu) -gpoScope C -gpoLinkPath $ExCasOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $ExHubOu) -gpoScope C -gpoLinkPath $ExHubOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $ExMailboxOu) -gpoScope C -gpoLinkPath $ExMailboxOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) New-DelegateAdGpo -gpoDescription ('{0}-Baseline' -f $ExEdgeOuDn) -gpoScope C -gpoLinkPath $ExEdgeOuDn -GpoAdmin ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.GpoAdminRight.Name) ############################################################################### # Import the security templates to the corresponding GPOs under Servers # Configure Exchange ClientAccess GPO #Import-GPO -BackupId $confXML.n.AdminXtra.GPOs.ExCas.backupID -TargetName ('C-{0}-Baseline' -f $ExCasOu) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure Exchange Hub GPO #Import-GPO -BackupId $confXML.n.AdminXtra.GPOs.ExHub.backupID -TargetName ('C-{0}-Baseline' -f $ExHubOu) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure Mailbox GPO #Import-GPO -BackupId $confXML.n.AdminXtra.GPOs.ExMailbox.backupID -TargetName ('C-{0}-Baseline' -f $ExMailboxOu) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) # Configure EDGE GPO #Import-GPO -BackupId $confXML.n.AdminXtra.GPOs.ExEdge.backupID -TargetName ('C-{0}-Baseline' -f $ExEdgeOuDn) -path (Join-Path -Path $DMscripts -ChildPath SecTmpl) } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating Exchange containers and objects." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-ExchangeObjects #EndRegion - New-ExchangeObjects.ps1 #Region - New-LapsObjects.ps1 Function New-LAPSobjects { <# .Synopsis Create Local Administration Password Services (LAPS) Objects and Delegations .DESCRIPTION Create the LAPS Objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-LAPSobjects -PawOuDn "OU=PAW,OU=Admin,DC=EguibarIT,DC=local" -ServersOuDn "OU=Servers,DC=EguibarIT,DC=local" -SitesOuDn "OU=Sites,DC=EguibarIT,DC=local" .INPUTS Param1 PawOuDn:......[String] Distinguished Name of the IT PrivilegedAccess Workstations OU Param2 ServersOuDn:..[String] Distinguished Name of the Servers OU Param3 SitesOuDn:....[String] Distinguished Name of the Sites OU .NOTES Version: 1.1 DateModified: 11/Feb/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, # Param2 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [string] $DMscripts = "C:\PsScripts\" ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module ActiveDirectory -Verbose:$false Import-Module EguibarIT.Delegation -Verbose:$false Import-Module AdmPwd.PS -Verbose:$false ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 $SL_InfraRight = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.InfraRight.Name) $SL_PISM = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.PISM.Name) $SL_PAWM = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.PAWM.Name) # $SL_AdRight = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.AdRight.Name) $SL_SvrAdmRight = Get-ADGroup -Identity ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Servers.LG.SvrAdmRight.Name) $guidmap = $null $guidmap = @{} $guidmap = Get-AttributeSchemaHashTable #$parameters = $null # Organizational Units Distinguished Names # IT Admin OU $ItAdminOu = $confXML.n.Admin.OUs.ItAdminOU.name # IT Admin OU Distinguished Name $ItAdminOuDn = 'OU={0},{1}' -f $ItAdminOu, $AdDn # Servers OU $ServersOu = $confXML.n.Servers.OUs.ServersOU.name # Servers OU Distinguished Name $ServersOuDn = 'OU={0},{1}' -f $ServersOu, $AdDn # It InfraServers OU $ItInfraServersOu = $confXML.n.Admin.OUs.ItInfraOU.name # It PAW OU Distinguished Name $ItInfraServersOuDn = 'OU={0},{1}' -f $ItInfraServersOu, $ItAdminOuDn # It InfraServers Tier0 OU $ItInfraT0OU = $confXML.n.Admin.OUs.ItInfraT0.name # It InfraServers Tier0 OU Distinguished Name $ItInfraT0OUDN = 'OU={0},{1}' -f $ItInfraT0OU, $ItInfraServersOuDn # It InfraServers Tier1 OU $ItInfraT1OU = $confXML.n.Admin.OUs.ItInfraT1.name # It InfraServers Tier1 OU Distinguished Name $ItInfraT1OUDN = 'OU={0},{1}' -f $ItInfraT1OU, $ItInfraServersOuDn # It InfraServers Tier2 OU $ItInfraT2OU = $confXML.n.Admin.OUs.ItInfraT2.name # It InfraServers Tier2 OU Distinguished Name $ItInfraT2OUDN = 'OU={0},{1}' -f $ItInfraT2OU, $ItInfraServersOuDn # It InfraServers Staging Tier0 OU $ItInfraStagingOU = $confXML.n.Admin.OUs.ItInfraStagingOU.name # It InfraServers Staging Tier0 OU Distinguished Name $ItInfraStagingOUDN = 'OU={0},{1}' -f $ItInfraStagingOU, $ItInfraServersOuDn # It PAW OU $ItPawOu = $confXML.n.Admin.OUs.ItPawOU.name # It PAW OU Distinguished Name $ItPawOuDn = 'OU={0},{1}' -f $ItPawOu, $ItAdminOuDn # It PAW Tier0 OU $ItPawT0OU = $confXML.n.Admin.OUs.ItPawT0OU.name # It PAW Tier0 OU Distinguished Name $ItPawT0OUDN = 'OU={0},{1}' -f $ItPawT0OU, $ItPawOuDn # It PAW Tier1 OU $ItPawT1OU = $confXML.n.Admin.OUs.ItPawT1OU.name # It PAW Tier1 OU Distinguished Name $ItPawT1OUDN = 'OU={0},{1}' -f $ItPawT1OU, $ItPawOuDn # It PAW Tier2 OU $ItPawT2OU = $confXML.n.Admin.OUs.ItPawT2OU.name # It PAW Tier2 OU Distinguished Name $ItPawT2OUDN = 'OU={0},{1}' -f $ItPawT2OU, $ItPawOuDn # It PAW Staging Tier0 OU $ItPawStagingOU = $confXML.n.Admin.OUs.ItPawStagingOU.name # It PAW Tier2 OU Distinguished Name $ItPawStagingOUDN = 'OU={0},{1}' -f $ItPawStagingOU, $ItPawOuDn # Sites OU $SitesOu = $confXML.n.Sites.OUs.SitesOU.name # Sites OU Distinguished Name $SitesOuDn = 'OU={0},{1}' -f $SitesOu, $AdDn #endregion Declarations ################################################################################ # Check if schema is extended for LAPS. Extend it if not. Try { if($null -eq $guidmap["ms-Mcs-AdmPwd"]) { Write-Verbose -Message 'LAPS is NOT supported on this environment. Proceeding to configure it by extending the Schema.' # Check if user can change schema if (-not ((Get-ADUser $env:UserName -Properties memberof).memberof -like "CN=Schema Admins*")) { Write-Verbose -Message 'Member is not a Schema Admin... adding it.' Add-ADGroupMember -Identity 'Schema Admins' -Members $env:username # Modify Schema try { Write-Verbose -Message 'Modify the schema...!' Update-AdmPwdADSchema -Verbose } catch { throw } finally { # If Schema extension OK, remove user from Schema Admin Remove-ADGroupMember -Identity 'Schema Admins' -Members $env:username -Confirm:$false } }#end if }#end if }#end try catch { throw } Finally { Write-Verbose -Message 'Schema was extended succesfully for LAPS.' }#end finally } Process { # Make Infrastructure Servers modifications Set-AdAclLaps -ResetGroup $SL_PISM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItInfraT0OUDN Set-AdAclLaps -ResetGroup $SL_PISM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItInfraT1OUDN Set-AdAclLaps -ResetGroup $SL_PISM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItInfraT2OUDN Set-AdAclLaps -ResetGroup $SL_PISM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItInfraStagingOUDN # Make PAW modifications Set-AdAclLaps -ResetGroup $SL_PAWM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItPawT0OUDN Set-AdAclLaps -ResetGroup $SL_PAWM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItPawT1OUDN Set-AdAclLaps -ResetGroup $SL_PAWM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItPawT2OUDN Set-AdAclLaps -ResetGroup $SL_PAWM.SamAccountName -ReadGroup $SL_InfraRight.SamAccountName -LDAPPath $ItPawStagingOUDN # Make Servers Modifications Set-AdAclLaps -ResetGroup $SL_SvrAdmRight.SamAccountName -ReadGroup $SL_SvrAdmRight.SamAccountName -LDAPPath $ServersOuDn # Make Sites Modifications # Get the DN of 1st level OU underneath SERVERS area $AllSubOu = Get-AdOrganizationalUnit -Filter * -SearchBase $SitesOuDn -SearchScope OneLevel | Select-Object -ExpandProperty DistinguishedName # Iterate through each sub OU and invoke delegation Foreach ($Item in $AllSubOu) { # Exclude _Global OU from delegation If(-not($item.Split(',')[0].Substring(3) -eq $confXML.n.Sites.OUs.OuSiteGlobal.name)) { # Get group who manages Desktops and Laptops $CurrentGroup = (Get-ADGroup -Identity ('{0}{1}{2}{1}{3}' -f $NC['sl'], $NC['Delim'], $confXML.n.Sites.LG.PcRight.Name, ($item.Split(',')[0].Substring(3)))).SamAccountName # Desktops $CurrentLDAPPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteComputer.Name, $Item Set-AdAclLaps -ResetGroup $CurrentGroup.SamAccountName -ReadGroup $CurrentGroup.SamAccountName -LDAPPath $CurrentLDAPPath # Laptop $CurrentLDAPPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLaptop.Name, $Item Set-AdAclLaps -ResetGroup $CurrentGroup.SamAccountName -ReadGroup $CurrentGroup.SamAccountName -LDAPPath $CurrentLDAPPath # Get group who manages Local Servers & File-Print $CurrentGroup = (Get-ADGroup -Identity ('{0}{1}{2}{1}{3}' -f $NC['sl'], $NC['Delim'], $confXML.n.Sites.LG.LocalServerRight.Name, ($item.Split(',')[0].Substring(3)))).SamAccountName # File-Print $CurrentLDAPPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteFilePrint.Name, $Item Set-AdAclLaps -ResetGroup $CurrentGroup.SamAccountName -ReadGroup $CurrentGroup.SamAccountName -LDAPPath $CurrentLDAPPath # Local Server $CurrentLDAPPath = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLocalServer.Name, $Item Set-AdAclLaps -ResetGroup $CurrentGroup.SamAccountName -ReadGroup $CurrentGroup.SamAccountName -LDAPPath $CurrentLDAPPath } }#end foreach } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) created LAPS and Delegations successfully." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-LapsObjects #EndRegion - New-LapsObjects.ps1 #Region - New-LocalLogonTask.ps1 function New-LocalLogonTask { <# .SYNOPSIS Generates a New Local Logon task .DESCRIPTION Generates a New Local Logon task .EXAMPLE New-LocalLogonTask -Name -Description -Author -Command -CommandArguments -Hiden .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( # Param1 help description [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 0)] [ValidateNotNullOrEmpty()] [string] $name, # Param2 help description [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 1)] [ValidateNotNullOrEmpty()] [string] $Description, # Param3 help description [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 2)] [ValidateNotNullOrEmpty()] [string] $Author, # Param4 help description [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 3)] [ValidateNotNullOrEmpty()] [string] $Command, # Param5 help description [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 4)] [string] $CommandArguments, # Param6 help description [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 5)] [switch] $Hidden ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383607(v=vs.85).aspx try { # Create the TaskService object $service = New-Object -ComObject('Schedule.Service') # Connect to the server's Task Service Scheduler $service.Connect($Env:computername) $rootFolder = $service.GetFolder('\') $taskDefinition = $service.NewTask(0) # Define information about the task. # Set the registration info for the task by creating the RegistrationInfo object. $regInfo = $taskDefinition.RegistrationInfo $regInfo.Description = $Description $regInfo.Author = $Author # Set the task setting info for the Task Scheduler by creating a TaskSettings object. $settings = $taskDefinition.Settings $settings.Enabled = $true $settings.StartWhenAvailable = $true $settings.Hidden = $Hidden # Create a logon trigger $triggers = $taskDefinition.Triggers # TriggerTypeLogon is 9 $trigger = $triggers.Create(9) # Trigger variables that define when the trigger is active $trigger.StartBoundary = '2014-10-0T22:00:00' #$trigger.DaysInterval = 1 $trigger.Id = 'LogonTriggerId' $trigger.Enabled = $true # Create the action for the task to execute. Add an action to the task $Action = $taskDefinition.Actions.Create(0) $Action.Path = $Command $Action.Arguments = $CommandArguments # Register (create -> 6 ) the task $rootFolder.RegisterTaskDefinition( $name, $taskDefinition, 6, $null , $null , 0) } catch { throw $error } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating new task." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-LocalLogonTask #EndRegion - New-LocalLogonTask.ps1 #Region - New-TimePolicyGPO.ps1 Function New-TimePolicyGPO { <# .Synopsis .DESCRIPTION .EXAMPLE New-TimePolicyGPO .INPUTS .NOTES Version: 1.0 DateModified: 25/Mar/2014 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # Param1 GPO Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Name of the GPO to be created', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $gpoName, # Param2 NTP servers [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'NTP Servers to be used for time sync', Position = 1)] [string] $NtpServer, # Param3 AnnounceFlags for reliable time server [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'AnnounceFlags for reliable time server', Position = 2)] [ValidateNotNullOrEmpty()] [int] $AnnounceFlags, # Param4 Type of Sync [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Type of sync to be used', Position = 3)] [ValidateNotNullOrEmpty()] [ValidateSet('NoSync', 'NTP', 'NT5DS', 'AllSync', ignorecase = $false)] [string] $Type, # Param5 WMIFilter to be created and used [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'WMIFilter to be created and used', Position = 3)] [ValidateNotNullOrEmpty()] $WMIFilter, # Param6 Disable Virtual Machine time sync clock [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Disable Virtual Machine time sync clock', Position = 4)] [switch] $DisableVMTimeSync ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" $msWMIAuthor = (Get-ADUser -Identity $env:USERNAME).Name # Create WMI Filter $WMIGUID = [string]'{'+([Guid]::NewGuid())+'}' $WMIDN = 'CN='+$WMIGUID+',CN=SOM,CN=WMIPolicy,CN=System,{0}' -f ([ADSI]'LDAP://RootDSE').DefaultNamingContext.ToString() $WMICN = $WMIGUID $WMIdistinguishedname = $WMIDN $WMIID = $WMIGUID $now = (Get-Date).ToUniversalTime() $msWMICreationDate = ($now.Year).ToString('0000') + ($now.Month).ToString('00') + ($now.Day).ToString('00') + ($now.Hour).ToString('00') + ($now.Minute).ToString('00') + ($now.Second).ToString('00') + '.' + ($now.Millisecond * 1000).ToString('000000') + '-000' $msWMIName = $WMIFilter[0] $msWMIParm1 = $WMIFilter[1] + ' ' $msWMIParm2 = '1;3;10;' + $WMIFilter[3].Length.ToString() + ';WQL;' + $WMIFilter[2] + ';' + $WMIFilter[3] + ';' # msWMI-Name: The friendly name of the WMI filter # msWMI-Parm1: The description of the WMI filter # msWMI-Parm2: The query and other related data of the WMI filter $Attr = @{ 'msWMI-Name' = $msWMIName 'msWMI-Parm1' = $msWMIParm1 'msWMI-Parm2' = $msWMIParm2 'msWMI-Author' = $msWMIAuthor 'msWMI-ID' = $WMIID 'instanceType' = 4 'showInAdvancedViewOnly' = 'TRUE' 'distinguishedname' = $WMIdistinguishedname 'msWMI-ChangeDate' = $msWMICreationDate 'msWMI-CreationDate' = $msWMICreationDate } $WMIPath = ('CN=SOM,CN=WMIPolicy,CN=System,{0}' -f ([ADSI]'LDAP://RootDSE').DefaultNamingContext.ToString()) $ExistingWMIFilters = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' -Properties 'msWMI-Name', 'msWMI-Parm1', 'msWMI-Parm2' $array = @() } Process { If ($null -ne $ExistingWMIFilters) { foreach ($ExistingWMIFilter in $ExistingWMIFilters) { $array += $ExistingWMIFilter.'msWMI-Name' } } Else { $array += 'no filters' } if ($array -notcontains $msWMIName) { Write-Output ('Creating the {0} WMI Filter...' -f $msWMIName) $WMIFilterADObject = New-ADObject -name $WMICN -type 'msWMI-Som' -Path $WMIPath -OtherAttributes $Attr } Else { Write-Warning -Message ('The {0} WMI Filter already exists.' -f $msWMIName) } $WMIFilterADObject = $null # Get WMI filter $WMIFilterADObject = Get-ADObject -Filter 'objectClass -eq "msWMI-Som"' -Properties 'msWMI-Name', 'msWMI-Parm1', 'msWMI-Parm2' | Where-Object { $_.'msWMI-Name' -eq "$msWMIName" } $ExistingGPO = get-gpo -Name $PSBoundParameters['gpoName'] -ErrorAction 'SilentlyContinue' If ($null -eq $ExistingGPO) { Write-Output ('Creating the {0} Group Policy Object...' -f $PSBoundParameters['gpoName']) # Create new GPO shell $GPO = New-GPO -Name $PSBoundParameters['gpoName'] # Disable User Settings $GPO.GpoStatus = 'UserSettingsDisabled' # Add the WMI Filter $GPO.WmiFilter = ConvertTo-WmiFilter $WMIFilterADObject # Set the three registry keys in the Preferences section of the new GPO $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config' ` -Type DWord -ValueName 'AnnounceFlags' -Value $PSBoundParameters['AnnounceFlags'] $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Parameters' ` -Type String -ValueName 'NtpServer' -Value "$PSBoundParameters['NtpServer']" $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Parameters' ` -Type String -ValueName 'Type' -Value "$PSBoundParameters['Type']" If ($PSBoundParameters['DisableVMTimeSync']) { # Disable the Hyper-V time synchronization integration service. $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Parameters' ` -Type DWord -ValueName 'Enabled' -Value 0 # Used to control how often the time service synchronizes to 15 minutes $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient' ` -Type DWord -ValueName 'SpecialPollInterval' -Value 900 # Set the three registry keys in the Preferences section of the new GPO $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config' ` -Type DWord -ValueName 'MaxPosPhaseCorrection' -Value 3600 # Set the three registry keys in the Preferences section of the new GPO $null = Set-GPPrefRegistryValue -Name $PSBoundParameters['gpoName'] -Action Update -Context Computer ` -Key 'HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config' ` -Type DWord -ValueName 'MaxNegPhaseCorrection' -Value 3600 }#end if # Link the new GPO to the Domain Controllers OU Write-Output ('Linking the {0} Group Policy Object to the OU=Domain Controllers,{1} ...' -f $PSBoundParameters['gpoName'], ([ADSI]'LDAP://RootDSE').DefaultNamingContext.ToString()) $null = New-GPLink -Name $PSBoundParameters['gpoName'] -Target ('OU=Domain Controllers,{0}' -f ([ADSI]'LDAP://RootDSE').DefaultNamingContext.ToString()) } Else { Write-Warning -Message ('The {0} Group Policy Object already exists.' -f $PSBoundParameters['gpoName']) Write-Output ('Adding the {0} WMI Filter...' -f $msWMIName) $ExistingGPO.WmiFilter = ConvertTo-WmiFilter $WMIFilterADObject } } End { Write-Output "Completed.`n" Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating the Time Policy GPO." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function New-TimePolicyGPO #EndRegion - New-TimePolicyGPO.ps1 #Region - New-WsusObjects.ps1 Function New-WsusObjects { <# .Synopsis Create WSUS Objects and Delegations .DESCRIPTION Create the WSUS Objects used to manage this organization by following the defined Delegation Model. .EXAMPLE New-WsusObjects .INPUTS .NOTES Version: 1.1 DateModified: 22/Apr/2021 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" ################################################################################ # Initialisations Import-Module ActiveDirectory -Verbose:$false #Get the OS Instalation Type $OsInstalationType = Get-ItemProperty -Path 'HKLM:Software\Microsoft\Windows NT\CurrentVersion' | Select-Object -ExpandProperty InstallationType } # End Bigin Process { # Check if AD module is installed If(-not((Get-WindowsFeature -Name RSAT-AD-PowerShell).Installed)) { Install-WindowsFeature -Name RSAT-AD-PowerShell -IncludeAllSubFeature } # Check if feature is installed, if not then proceed to install it. If(-not((Get-WindowsFeature -Name UpdateServices-Services).Installed)) { Install-WindowsFeature -Name UpdateServices, UpdateServices-Services, UpdateServices-WidDB -Restart } If($OsInstalationType -ne 'Server Core') { Install-WindowsFeature -Name UpdateServices-RSAT -IncludeAllSubFeature } # Configure Download Location #Create WSUS folder # Create Folder where to store all Delegation Model scripts & files $WsusFolder = ('{0}\WSUS\' -f $env:SystemDrive) if(-not(Test-Path $WsusFolder)) { New-Item -ItemType Directory -Force -Path $WsusFolder } # Create a new Windows Script Shell $sh = New-Object -comobject 'Wscript.Shell' [String]$cmd = '"C:\Program Files\Update Services\Tools\WsusUtil.exe" PostInstall CONTENT_DIR=C:\WSUS' $sh.Run($cmd,1,'true') # Download Microsoft System CLR Types for SQL Server 2014 #$URL = 'https://download.microsoft.com/download/1/3/0/13089488-91FC-4E22-AD68-5BE58BD5C014/ENU/x64/SQLSysClrTypes.msi' # Download Microsoft System CLR Types for SQL Server 2012 $URL = 'http://download.microsoft.com/download/F/E/D/FEDB200F-DE2A-46D8-B661-D019DFE9D470/ENU/x64/SQLSysClrTypes.msi' Start-BitsTransfer -Source $URL -Destination $env:TEMP -Priority High -TransferType Download -RetryInterval 60 -RetryTimeout 180 -ErrorVariable err if ($err) { write-Error -Message 'Microsoft Microsoft System CLR Types for SQL Server 2014 could not be downloaded!. Please download and install it manually to use WSUS Reports.' } # Download MICROSOFT� REPORT VIEWER 2015 RUNTIME #$URL = 'https://download.microsoft.com/download/A/1/2/A129F694-233C-4C7C-860F-F73139CF2E01/ENU/x86/ReportViewer.msi' # Download MICROSOFT� REPORT VIEWER 2012 RUNTIME $URL = 'https://download.microsoft.com/download/F/B/7/FB728406-A1EE-4AB5-9C56-74EB8BDDF2FF/ReportViewer.msi' Start-BitsTransfer -Source $URL -Destination $env:TEMP -Priority High -TransferType Download -RetryInterval 60 -RetryTimeout 180 -ErrorVariable err if ($err) { write-Error -Message 'Microsoft REPORT VIEWER 2015 RUNTIME could not be downloaded!. Please download and install it manually to use WSUS Reports.' } # Install Microsoft System CLR Types for SQL Server 2014 $Arguments = '/i "{0}\SQLSysClrTypes.msi" /qn /quiet /norestart' -f $env:TEMP $setup = Start-Process -FilePath 'msiexec.exe' -Verb RunAs -ArgumentList $Arguments -Wait -PassThru -Verbose $setup.WaitForExit() if ($setup.exitcode -eq 0) { write-verbose -Message 'Microsoft System CLR Types for SQL Server 2017 Successfully installed' } else { write-error -Message 'Microsoft System CLR Types for SQL Server 2017 did not install correctly. Please download and install it manually to use WSUS Reports.' } # Install REPORT VIEWER 2015 RUNTIME $Arguments = '/i "{0}\ReportViewer.msi" /qn /quiet /norestart' -f $env:TEMP $setup = Start-Process -FilePath 'msiexec.exe' -Verb RunAs -ArgumentList $Arguments -Wait -PassThru -Verbose $setup.WaitForExit() if ($setup.exitcode -eq 0) { write-verbose -Message 'Microsoft REPORT VIEWER 2015 RUNTIME Successfully installed' } else { write-error -Message 'Microsoft REPORT VIEWER 2015 RUNTIME did not install correctly. Please download and install it manually to use WSUS Reports.' } # Cannot be imported in the bigin section due features installation Import-Module -Name WebAdministration -Force -Verbose:$false # Set Application Pool Maximum Private memory #Clear-ItemProperty IIS:\AppPools\WsusPool -Name Recycling.periodicRestart.privatememory #[int32] $PrivMemMax = 4GB #[int32] $PrivMemMax = 8GB [int32] $PrivMemMax = 0 Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name Recycling.periodicRestart.privateMemory -Value $PrivMemMax # ( C:\Program Files\Update Services\WebServices\ClientWebService\web.config ) for WSUS: Replace <httpRuntime maxRequestLength="4096" /> with <httpRuntime maxRequestLength="204800" executionTimeout="7200"/> <# This one are failing Set-WebConfiguration -Filter "/system.applicationHost/applicationPools/add[@name='WsusPool']/recycling/periodicRestart/@privateMemory" -Value 0 Set-WebConfiguration -Filter "/system.applicationHost/applicationPools/add[@name='WsusPool']/processModel/@maxProcesses" -Value 0 #> # Other "Unexpected error" hacks Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name queueLength -Value 25000 Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name cpu.resetInterval -Value "00.00:15:00" Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name failure.loadBalancerCapabilities -Value "TcpLevel" Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name failure.rapidFailProtectionInterval -Value "00.00:30:00" Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name failure.rapidFailProtectionMaxCrashes -Value 60 Set-ItemProperty -Path IIS:\AppPools\WsusPool -Name ProcessModel.MaxProcesses -Value 0 # Get WSUS Server Object $wsus = Get-WSUSServer # Connect to WSUS server configuration $wsusConfig = $wsus.GetConfiguration() ### Remove WSUS configuration pop-up when opening WSUS Management Console $wsusConfig.OobeInitialized = $true $wsusConfig.Save() #Check WSUS services. Mark those as automatic Set-Service WSusCertServer -StartupType Automatic Set-Service WsusService -StartupType Automatic Set-Service wuauserv -StartupType Automatic #Start Services Start-Service WSusCertServer, WsusService, wuauserv -Verbose # Get a new certificate from CA1 using WebServerV2 template $Splat = @{ Template = 'WebServerV2' DnsName = ('{0}.{1}' -f $env:COMPUTERNAME, $env:USERDNSDOMAIN).ToLower() Url = 'ldap:' CertStoreLocation = 'cert:\LocalMachine\My' SubjectName = ('CN={0}' -f $env:COMPUTERNAME).ToLower() } $WsusCert = Get-Certificate @Splat # Get the binding as object $bind = Get-WebBinding -Name 'WSUS Administration' -Protocol https # Merge the 2 objects $bind.AddSslCertificate($WsusCert.Certificate.Thumbprint, "My") # Set all corresponding virtual directories to use SSL $Splat = @{ PSPath = 'MACHINE/WEBROOT/APPHOST' Filter = "system.webServer/Security/access" Name = "sslFlags" Value ="Ssl" } Set-WebConfigurationProperty @Splat -Location 'WSUS Administration/ApiRemoting30' Set-WebConfigurationProperty @Splat -Location 'WSUS Administration/ClientWebService' Set-WebConfigurationProperty @Splat -Location 'WSUS Administration/DSSAuthWebService' Set-WebConfigurationProperty @Splat -Location 'WSUS Administration/ServerSyncWebService' Set-WebConfigurationProperty @Splat -Location 'WSUS Administration/SimpleAuthWebService' # Final SSL configuration [String]$cmd = '"C:\Program Files\Update Services\Tools\WsusUtil.exe" configuressl {0}' -f ('{0}.{1}' -f $env:COMPUTERNAME, $env:USERDNSDOMAIN).ToLower() $sh.Run($cmd,1,'true') # Get WSUS Server Object $wsus = Get-WSUSServer # Refresh WSUS server configuration $wsusConfig = $wsus.GetConfiguration() # Set to download updates from Microsoft Updates Set-WsusServerSynchronization -SyncFromMU # Set Update Languages to English and save configuration settings $wsusConfig.AllUpdateLanguagesEnabled = $false $wsusConfig.SetEnabledUpdateLanguages('en') $wsusConfig.GetContentFromMU = $True $wsusConfig.AutoApproveWsusInfrastructureUpdates = $True $wsusConfig.AutoRefreshUpdateApprovals = $True $wsusConfig.AutoRefreshUpdateApprovalsDeclineExpired = $True $wsusConfig.HostBinariesOnMicrosoftUpdate = $True $wsusConfig.Save() # Get WSUS Subscription and perform initial synchronization to get latest categories $subscription = $wsus.GetSubscription() $subscription.StartSynchronizationForCategoryOnly() while ($subscription.GetSynchronizationProgress().ProcessedItems -ne $subscription.GetSynchronizationProgress().TotalItems) { Write-Progress -PercentComplete ( $subscription.GetSynchronizationProgress().ProcessedItems*100/($subscription.GetSynchronizationProgress().TotalItems) ) -Activity "WSUS Sync Progress" } # Disable all previously selected products Get-WsusProduct | Set-WsusProduct -Disable # Configure the Platforms that we want WSUS to receive updates Get-WsusProduct | where-Object { $_.Product.Title -in ( 'Active Directory', 'Developer Tools, Runtimes, and Redistributables', 'Forefront Client Security', 'Forefront Identity Manager 2010 R2', 'Forefront Identity Manager 2010', 'Forefront Protection Category', 'Forefront Server Security Category', 'Forefront Threat Management Gateway, Definition Updates for HTTP Malware Inspection', 'Forefront TMG MBE', 'Forefront TMG', 'Forefront', 'Microsoft Advanced Threat Analytics', 'Microsoft BitLocker Administration and Monitoring v1', 'Microsoft BitLocker Administration and Monitoring', 'Microsoft Edge', 'Microsoft Security Essentials', 'MS Security Essentials', 'Report Viewer 2005', 'Report Viewer 2008', 'Report Viewer 2010', 'Security Essentials', 'Visual Studio 2015', 'Visual Studio 2017', 'Windows 10, version 1809 and later, Upgrade & Servicing Drivers', 'Windows 10', 'Windows Admin Center', 'Windows Defender', 'Windows Dictionary Updates', 'Windows Server 2016 and Later Servicing Drivers', 'Windows Server 2016', 'Windows Server 2019 and later, Servicing Drivers', 'Windows Server 2019 and later, Upgrade & Servicing Drivers', 'Windows Server 2019', 'Windows Server Drivers', 'Windows Server Solutions Best Practices Analyzer 1.0', 'Windows Server, version 1903 and later' ) } | Set-WsusProduct # Configure the Classifications write-Output 'Setting WSUS Classifications' Get-WsusClassification | Where-Object { $_.Classification.Title -in ( 'Critical Updates', 'Definition Updates', 'Feature Packs', 'Security Updates', 'Service Packs', 'Update Rollups', 'Updates') } | Set-WsusClassification # Configure Default Approval Rule [void][reflection.assembly]::LoadWithPartialName('Microsoft.UpdateServices.Administration') $rule = $wsus.GetInstallApprovalRules() | Where-Object { $_.Name -eq 'Default Automatic Approval Rule' } $class = $wsus.GetUpdateClassifications() | Where-Object {$_.Title -In ( 'Critical Updates', 'Definition Updates', 'Security Updates', 'Service Packs', 'Update Rollups', 'Updates') } $class_coll = New-Object Microsoft.UpdateServices.Administration.UpdateClassificationCollection $class_coll.AddRange($class) $rule.SetUpdateClassifications($class_coll) $rule.Enabled = $True $rule.Save() # Configure Synchronizations write-Output 'Enabling WSUS Automatic Synchronisation' $subscription.SynchronizeAutomatically=$true # Set synchronization scheduled for midnight each night $subscription.SynchronizeAutomaticallyTimeOfDay= (New-TimeSpan -Hours 0) $subscription.NumberOfSynchronizationsPerDay=1 $subscription.Save() # Kick off a synchronization $subscription.StartSynchronization() ### Create computer target group $wsus.CreateComputerTargetGroup("DCs") $wsus.CreateComputerTargetGroup("PAWs") $wsus.CreateComputerTargetGroup("Infrastructure Servers") $wsus.CreateComputerTargetGroup("Tier1") $wsus.CreateComputerTargetGroup("Tier2") } # End Process End { Write-Verbose -Message ('Function {0} created Wsus objects and Delegations successfully.' -f $MyInvocation.InvocationName) Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } # End end } # end function New-WsusObjects Export-ModuleMember -Function New-WsusObjects #EndRegion - New-WsusObjects.ps1 #Region - Revoke-Inheritance.ps1 function Revoke-Inheritance { <# .Synopsis Function to remove NTFS inheritance of a folder .DESCRIPTION Function to remove NTFS inheritance of a folder .EXAMPLE Revoke-Inheritance path .INPUTS Param1 path = The path to the folder .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([String])] Param ( # Param1 path to the resource|folder [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Add help message for user', Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $path ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { Try { $isProtected = $true $preserveInheritance = $true $DirectorySecurity = Get-Acl -Path $path # SetAccessRuleProtection, which is a method to control whether inheritance from the parent folder should # be blocked ($True means no Inheritance) and if the previously inherited access rules should # be preserved ($False means remove previously inherited permissions). $DirectorySecurity.SetAccessRuleProtection($isProtected, $preserveInheritance) Set-Acl -Path $path -AclObject $DirectorySecurity } Catch { Throw } } End { Write-Verbose -Message ('The folder {0} was removed inheritance.' -f $path) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Revoke-Inheritance #EndRegion - Revoke-Inheritance.ps1 #Region - Revoke-NTFSPermissions.ps1 function Revoke-NTFSPermissions { <# .Synopsis Function to remove NTFS permissions to a folder .DESCRIPTION Function to remove NTFS permissions to a folder .EXAMPLE Revoke-NTFSPermissions path object permission .INPUTS Param1 path = The path to the folder Param2 object = the identity which will get the permissions Param3 permission = the permissions to be modified .NOTES Version: 1.0 DateModified: 31/Mar/2015 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( # Param1 path to the resource|folder [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 0)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $path, # Param2 object or SecurityPrincipal [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 1)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $object, # Param3 permission [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 2)] [ValidateNotNull()] [ValidateNotNullOrEmpty()] [string] $permission ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { Try { $FileSystemRights = [Security.AccessControl.FileSystemRights]$permission $InheritanceFlag = [Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit' $PropagationFlag = [Security.AccessControl.PropagationFlags]'None' $AccessControlType = [Security.AccessControl.AccessControlType]::Allow $Account = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList ($object) $FileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType) $DirectorySecurity = Get-Acl -Path $path $DirectorySecurity.RemoveAccessRuleAll($FileSystemAccessRule) Set-Acl -Path $path -AclObject $DirectorySecurity } Catch { Throw } } End { Write-Verbose -Message ('The User/Group {0} was removed {1} from folder {2}.' -f $object, $permission, $path) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Revoke-NTFSPermissions #EndRegion - Revoke-NTFSPermissions.ps1 #Region - Set-AdAclDelegateComputerAdmin.ps1 # Group together all COMPUTER admin delegations function Set-AdAclDelegateComputerAdmin { <# .Synopsis The function will consolidate all rights used for Computer object container. .DESCRIPTION .EXAMPLE Set-AdAclDelegateComputerAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Set-AdAclDelegateComputerAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" -RemoveRule .INPUTS Param1 Group:........[STRING] for the Delegated Group Name Param2 LDAPPath:.....[STRING] Distinguished Name of the OU where given group will fully manage a computer object. Param3 RemoveRule:...[SWITCH] If present, the access rule will be removed .NOTES Version: 1.0 DateModified: 19/Oct/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # PARAM1 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Identity of the group getting the delegation, usually a DomainLocal group.', Position = 0)] [ValidateNotNullOrEmpty()] [String] $Group, # PARAM2 Distinguished Name of the OU where given group can read the computer password [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the OU where given group will fully manage a computer object', Position = 1)] [ValidateNotNullOrEmpty()] [String] $LDAPpath, # PARAM3 Distinguished Name of the quarantine OU [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the quarantine OU', Position = 2)] [ValidateNotNullOrEmpty()] [String] $QuarantineDN, # PARAM4 SWITCH If present, the access rule will be removed. [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'If present, the access rule will be removed.', Position = 3)] [ValidateNotNullOrEmpty()] [Switch] $RemoveRule ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" $parameters = $null # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } } Process { try { $parameters = @{ Group = $PSBoundParameters['Group'] LDAPPath = $PSBoundParameters['LDAPpath'] } # Check if RemoveRule switch is present. If($PSBoundParameters['RemoveRule']) { # Add the parameter to remove the rule $parameters.Add('RemoveRule', $true) } # Create/Delete Computers Set-AdAclCreateDeleteComputer @parameters # Reset Computer Password Set-AdAclResetComputerPassword @parameters # Change Computer Password Set-AdAclChangeComputerPassword @parameters # Validated write to DNS host name Set-AdAclValidateWriteDnsHostName @parameters # Validated write to SPN Set-AdAclValidateWriteSPN @parameters # Change Computer Account Restriction Set-AdAclComputerAccountRestriction @parameters # Change DNS Hostname Info Set-AdAclDnsInfo @parameters # Change MS TerminalServices info Set-AdAclMsTsGatewayInfo @parameters # Access to BitLocker & TMP info Set-AdAclBitLockerTPM @parameters # Grant the right to delete computers from default container. Move Computers Set-DeleteOnlyComputer -Group $PSBoundParameters['Group'] -LDAPPath $PSBoundParameters['QuarantineDN'] # Set LAPS Set-AdAclLaps -ResetGroup $PSBoundParameters['Group'] -ReadGroup $PSBoundParameters['Group'] -LDAPPath $PSBoundParameters['LDAPpath'] } catch { throw } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished delegating Computer Admin." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Set-AdAclDelegateComputerAdmin #EndRegion - Set-AdAclDelegateComputerAdmin.ps1 #Region - Set-AdAclDelegateGalAdmin.ps1 # Group together all USER admin delegations function Set-AdAclDelegateGalAdmin { <# .Synopsis The function will consolidate all rights used for GAL admin. .DESCRIPTION .EXAMPLE Set-AdAclDelegateGalAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Set-AdAclDelegateGalAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" -RemoveRule .INPUTS Param1 Group:........[STRING] for the Delegated Group Name Param2 LDAPPath:.....[STRING] Distinguished Name of the OU where given group will manage a User GAL. Param3 RemoveRule:...[SWITCH] If present, the access rule will be removed .NOTES Version: 1.1 DateModified: 12/Feb/2018 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # PARAM1 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Identity of the group getting the delegation, usually a DomainLocal group.', Position = 0)] [ValidateNotNullOrEmpty()] [String] $Group, # PARAM2 Distinguished Name of the OU where given group will manage a User GAL. [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the OU where given group will manage a User GAL.', Position = 1)] [ValidateNotNullOrEmpty()] [String] $LDAPpath, # PARAM3 SWITCH If present, the access rule will be removed. [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'If present, the access rule will be removed.', Position = 2)] [ValidateNotNullOrEmpty()] [Switch] $RemoveRule ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" $parameters = $null } Process { try { $parameters = @{ Group = $PSBoundParameters['Group'] LDAPPath = $PSBoundParameters['LDAPpath'] } # Check if RemoveRule switch is present. If($PSBoundParameters['RemoveRule']) { # Add the parameter to remove the rule $parameters.Add('RemoveRule', $true) } # Change Group Membership Set-AdAclUserGroupMembership @parameters # Change Personal Information Set-AdAclUserPersonalInfo @parameters # Change Public Information Set-AdAclUserPublicInfo @parameters # Change General Information Set-AdAclUserGeneralInfo @parameters # Change Web Info Set-AdAclUserWebInfo @parameters # Change Email Info Set-AdAclUserEmailInfo @parameters } catch { throw } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished delegating GAL Admin." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Set-AdAclDelegateGalAdmin #EndRegion - Set-AdAclDelegateGalAdmin.ps1 #Region - Set-AdAclDelegateUserAdmin.ps1 # Group together all USER admin delegations function Set-AdAclDelegateUserAdmin { <# .Synopsis The function will consolidate all rights used for USER object container. .DESCRIPTION .EXAMPLE Set-AdAclDelegateComputerAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Set-AdAclDelegateComputerAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" -RemoveRule .INPUTS Param1 Group:........[STRING] for the Delegated Group Name Param2 LDAPPath:.....[STRING] Distinguished Name of the OU where given group will fully manage a User object. Param3 RemoveRule:...[SWITCH] If present, the access rule will be removed .NOTES Version: 1.1 DateModified: 12/Feb/2018 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # PARAM1 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Identity of the group getting the delegation, usually a DomainLocal group.', Position = 0)] [ValidateNotNullOrEmpty()] [String] $Group, # PARAM2 Distinguished Name of the OU where given group can read the User password [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the OU where given group will fully manage a User object', Position = 1)] [ValidateNotNullOrEmpty()] [String] $LDAPpath, # PARAM3 SWITCH If present, the access rule will be removed. [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'If present, the access rule will be removed.', Position = 2)] [ValidateNotNullOrEmpty()] [Switch] $RemoveRule ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" $parameters = $null } Process { try { $parameters = @{ Group = $PSBoundParameters['Group'] LDAPPath = $PSBoundParameters['LDAPpath'] } # Check if RemoveRule switch is present. If($PSBoundParameters['RemoveRule']) { # Add the parameter to remove the rule $parameters.Add('RemoveRule', $true) } # Create/Delete Users Set-AdAclCreateDeleteUser @parameters # Reset User Password Set-AdAclResetUserPassword @parameters # Change User Password Set-AdAclChangeUserPassword @parameters # Enable and/or Disable user right Set-AdAclEnableDisableUser @parameters # Unlock user account Set-AdAclUnlockUser @parameters # Change User Restrictions Set-AdAclUserAccountRestriction @parameters # Change User Account Logon Info Set-AdAclUserLogonInfo @parameters } catch { throw } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished delegating User Admin." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Set-AdAclDelegateUserAdmin #EndRegion - Set-AdAclDelegateUserAdmin.ps1 #Region - Set-AdAclLaps.ps1 # Delegate Local Administration Password Service (LAPS) function Set-AdAclLaps { <# .Synopsis The function will consolidate all rights used for LAPS on a given container. .DESCRIPTION .EXAMPLE Set-AdAclLaps -ResetGroup "SG_SiteAdmins_XXXX" -ReadGroup "SG_GalAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Set-AdAclLaps -ResetGroup "SG_SiteAdmins_XXXX" -ReadGroup "SG_GalAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" -RemoveRule .INPUTS Param1 ReadGroup:....[STRING] Identity of the group getting being able to READ the password Param2 ResetGroup:...[STRING] Identity of the group getting being able to RESET the password Param3 LDAPPath:.....[STRING] Distinguished Name of the OU where LAPS will apply to computer object. Param4 RemoveRule:...[SWITCH] If present, the access rule will be removed .NOTES Version: 1.0 DateModified: 19/Oct/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # PARAM1 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Identity of the group getting being able to READ the password.', Position = 0)] [ValidateNotNullOrEmpty()] [String] $ReadGroup, # PARAM2 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Identity of the group getting being able to RESET the password.', Position = 1)] [ValidateNotNullOrEmpty()] [String] $ResetGroup, # PARAM3 Distinguished Name of the OU where given group can read the computer password [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the OU where LAPS will apply to computer object', Position = 2)] [ValidateNotNullOrEmpty()] [String] $LDAPpath, # PARAM4 SWITCH If present, the access rule will be removed. [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'If present, the access rule will be removed.', Position = 3)] [ValidateNotNullOrEmpty()] [Switch] $RemoveRule ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -Name 'AdmPwd.PS' -Verbose:$false $guidmap = $null $guidmap = @{} $guidmap = Get-AttributeSchemaHashTable } Process { if(-not($null -eq $guidmap["ms-Mcs-AdmPwdExpirationTime"])) { Write-Verbose -Message "LAPS is supported on this environment. We can proceed to configure it." Set-AdmPwdComputerSelfPermission -Identity $LDAPpath Set-AdmPwdReadPasswordPermission -AllowedPrincipals $ReadGroup -Identity $LDAPpath Set-AdmPwdResetPasswordPermission -AllowedPrincipals $ResetGroup -Identity $LDAPpath } else { Write-Error -Message "Not Implemented. Schema does not contains the requiered attributes." } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished delegating LAPS Admin." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Set-AdAclLaps #EndRegion - Set-AdAclLaps.ps1 #Region - Start-AdAclDelegateComputerAdmin.ps1 # Group together all COMPUTER admin delegations function Set-AdAclDelegateComputerAdmin { <# .Synopsis The function will consolidate all rights used for Computer object container. .DESCRIPTION .EXAMPLE Set-AdAclDelegateComputerAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" Set-AdAclDelegateComputerAdmin -Group "SG_SiteAdmins_XXXX" -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" -RemoveRule .INPUTS Param1 Group:........[STRING] for the Delegated Group Name Param2 LDAPPath:.....[STRING] Distinguished Name of the OU where given group will fully manage a computer object. Param3 RemoveRule:...[SWITCH] If present, the access rule will be removed .NOTES Version: 1.0 DateModified: 19/Oct/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( # PARAM1 STRING for the Delegated Group Name [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Identity of the group getting the delegation, usually a DomainLocal group.', Position = 0)] [ValidateNotNullOrEmpty()] [String] $Group, # PARAM2 Distinguished Name of the OU where given group can read the computer password [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the OU where given group will fully manage a computer object', Position = 1)] [ValidateNotNullOrEmpty()] [String] $LDAPpath, # PARAM3 Distinguished Name of the quarantine OU [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished Name of the quarantine OU', Position = 2)] [ValidateNotNullOrEmpty()] [String] $QuarantineDN, # PARAM4 SWITCH If present, the access rule will be removed. [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'If present, the access rule will be removed.', Position = 3)] [ValidateNotNullOrEmpty()] [Switch] $RemoveRule ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" $parameters = $null # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } } Process { try { $parameters = @{ Group = $PSBoundParameters['Group'] LDAPPath = $PSBoundParameters['LDAPpath'] } # Check if RemoveRule switch is present. If($PSBoundParameters['RemoveRule']) { # Add the parameter to remove the rule $parameters.Add('RemoveRule', $true) } # Create/Delete Computers Set-AdAclCreateDeleteComputer @parameters # Reset Computer Password Set-AdAclResetComputerPassword @parameters # Change Computer Password Set-AdAclChangeComputerPassword @parameters # Validated write to DNS host name Set-AdAclValidateWriteDnsHostName @parameters # Validated write to SPN Set-AdAclValidateWriteSPN @parameters # Change Computer Account Restriction Set-AdAclComputerAccountRestriction @parameters # Change DNS Hostname Info Set-AdAclDnsInfo @parameters # Change MS TerminalServices info Set-AdAclMsTsGatewayInfo @parameters # Access to BitLocker & TMP info Set-AdAclBitLockerTPM @parameters # Grant the right to delete computers from default container. Move Computers Set-DeleteOnlyComputer -Group $PSBoundParameters['Group'] -LDAPPath $PSBoundParameters['QuarantineDN'] # Set LAPS Set-AdAclLaps -ResetGroup $PSBoundParameters['Group'] -ReadGroup $PSBoundParameters['Group'] -LDAPPath $PSBoundParameters['LDAPpath'] } catch { throw } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished delegating Computer Admin." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Start-AdAclDelegateComputerAdmin #EndRegion - Start-AdAclDelegateComputerAdmin.ps1 #Region - Start-AdCleanOU.ps1 # Clean OU from default BuiltIn groups function Start-AdCleanOU { <# .Synopsis The function will remove some of the default premission on the provided OU. It will remove the "Account Operators" and "Print Operators" built-in groups. .DESCRIPTION Long description .EXAMPLE Start-AdCleanOU -LDAPPath "OU=Users,OU=XXXX,OU=Sites,DC=EguibarIT,DC=local" .INPUTS Param1 LDAPPath:................... [STRING] Distinguished name of the OU to be cleaned. Param2 RemoveAuthenticatedUsers:... [SWITCH] Remove Authenticated Users. Param3 RemoveUnknownSIDs:.......... [SWITCH] Remove Unknown SIDs. .NOTES Version: 1.2 DateModified: 19/Dec/2017 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] param ( #PARAM1 Distinguished name of the OU to be cleaned [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Distinguished name of the OU to be cleaned.', Position = 0)] [ValidateNotNullOrEmpty()] [String] $LDAPpath, #PARAM2 Remove Authenticated Users [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Remove Authenticated Users.', Position = 1)] [switch] $RemoveAuthenticatedUsers, #PARAM3 Remove Unknown SIDs [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'Remove Unknown SIDs.', Position = 2)] [switch] $RemoveUnknownSIDs ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Write-Verbose -Message 'Removing Account Operators and Print Operators' $Parameters = $null } process { $parameters = @{ Group = 'Account Operators' LDAPPath = $PSBoundParameters['LDAPPath'] RemoveRule = $true } # Remove the Account Operators group from ACL to Create/Delete Users Set-AdAclCreateDeleteUser @parameters # Remove the Account Operators group from ACL to Create/Delete Computers Set-AdAclCreateDeleteComputer @parameters # Remove the Account Operators group from ACL to Create/Delete Groups Set-AdAclCreateDeleteGroup @parameters # Remove the Account Operators group from ACL to Create/Delete Contacts Set-AdAclCreateDeleteContact @parameters # Remove the Account Operators group from ACL to Create/Delete inetOrgPerson Set-CreateDeleteInetOrgPerson @parameters # Remove the Print Operators group from ACL to Create/Delete PrintQueues Set-AdAclCreateDeletePrintQueue @parameters # Remove Pre-Windows 2000 Compatible Access group from Admin-User Remove-PreWin2000 -LDAPPath $PSBoundParameters['LDAPPath'] # Remove Pre-Windows 2000 Access group from OU Remove-PreWin2000FromOU -LDAPPath $PSBoundParameters['LDAPPath'] # Remove ACCOUNT OPERATORS 2000 Access group from OU Remove-AccountOperator -LDAPPath $PSBoundParameters['LDAPPath'] # Remove PRINT OPERATORS 2000 Access group from OU Remove-PrintOperator -LDAPPath $PSBoundParameters['LDAPPath'] If($PsBoundParameters['RemoveAuthenticatedUsers']) { # Remove AUTHENTICATED USERS group from OU Remove-AuthUser -LDAPPath $PSBoundParameters['LDAPPath'] Write-Verbose -Message 'Removing Authenticated Users' } If($PsBoundParameters['$RemoveUnknownSIDs']) { # Remove Un-Resolvable SID from a given object Remove-UnknownSID -LDAPPath $PSBoundParameters['LDAPPath'] -RemoveSID Write-Verbose -Message 'Remove Un-Resolvable / Unknown SIDs' } } end { Write-Verbose -Message('Builtin groups were removed correctly from object {0}.' -f $PSBoundParameters['LDAPPath']) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Start-AdCleanOU #EndRegion - Start-AdCleanOU.ps1 #Region - Start-AdDelegatedSite.ps1 # Delegate Rights to SITE groups function Start-AdDelegateSite { <# .Synopsis The function will create .DESCRIPTION Long description .EXAMPLE Start-AdDelegateSite -ConfigXMLFile "C:\PsScripts\Config.xml" -ouName "GOOD" -QuarantineDN "Quarantine" -CreateExchange -DMscripts "C:\PsScripts\" .INPUTS Param1 ConfigXMLFile:....[String] Full path to the Configuration.XML file Param1 ouName:...........[String] Enter the Name of the Site OU Param2 QuarantineDN:.....[String] Enter the Name new redirected OU for computers Param3 CreateExchange:...[String] If present It will create all needed Exchange objects and containers. Param4 DMscripts:........[String] Path to all the scripts and files needed by this function .NOTES Version: 1.3 DateModified: 12/Feb/2019 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'ParamOptions')] param ( # PARAM1 full path to the configuration.xml file [Parameter(Mandatory=$true, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ValueFromRemainingArguments=$false, HelpMessage='Full path to the configuration.xml file', Position=0)] [string] $ConfigXMLFile, #PARAM2 [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, ParameterSetName = 'ParamOptions', HelpMessage = 'Enter the Name of the Site OU', Position = 1)] [ValidateNotNullOrEmpty()] [String] $ouName, #PARAM3 [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, ParameterSetName = 'ParamOptions', HelpMessage = 'Enter the Name new redirected OU for computers', Position = 2)] [ValidateNotNullOrEmpty()] [String] $QuarantineDN, # Param4 Create Exchange Objects [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'If present It will create all needed Exchange objects and containers.', Position = 3)] [switch] $CreateExchange, # Param5 Location of all scripts & files [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 4)] [string] $DMscripts = "C:\PsScripts\", # PARAM6 Switch indicating if local server containers has to be created. Not recommended due TIer segregation [Parameter(Mandatory = $false, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True, ValueFromRemainingArguments = $false, HelpMessage='Switch indicating if local server containers has to be created. Not recommended due TIer segregation', Position=5)] [switch] $CreateSrvContainer ) begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Write-Verbose -Message 'Delegate Rights Site Groups' ################################################################################ #region Declarations try { # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Check if Config.xml file is loaded. If not, proceed to load it. If(-Not (Test-Path -Path variable:confXML)) { # Check if the Config.xml file exist on the given path If(Test-Path -Path $PSBoundParameters['ConfigXMLFile']) { #Open the configuration XML file $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) } #end if } #end if } catch { throw } # Naming conventions hashtable $NC = @{'sl' = $confXML.n.NC.LocalDomainGroupPreffix; 'sg' = $confXML.n.NC.GlobalGroupPreffix; 'su' = $confXML.n.NC.UniversalGroupPreffix; 'Delim' = $confXML.n.NC.Delimiter; 'T0' = $confXML.n.NC.AdminAccSufix0; 'T1' = $confXML.n.NC.AdminAccSufix1; 'T2' = $confXML.n.NC.AdminAccSufix2 } #('{0}{1}{2}{1}{3}' -f $NC['sg'], $NC['Delim'], $confXML.n.Admin.lg.PAWM, $NC['T0']) # SG_PAWM_T0 ############################################################################### #region Get all newly created Groups and store on variable # Iterate through all Site-DomainLocalGroups child nodes Foreach($node in $confXML.n.Sites.LG.ChildNodes) { $TempName = '{0}{1}{2}{1}{3}' -f $NC['sl'], $NC['Delim'], $node.Name, $PSBoundParameters['ouName'] Write-Verbose -Message ('Get group {0}' -f $TempName) New-Variable -Name "$($TempName)" -Value (Get-AdGroup $TempName) -Force } #endregion ############################################################################### # Sites OU Distinguished Name If(-Not (Test-Path -Path variable:ouNameDN)) { $ouNameDN = 'OU={0},OU={1},{2}' -f $ouName, $confXML.n.Sites.OUs.SitesOU.name, $AdDn } $OuSiteDefComputer = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteComputer.name, $ouNameDN $OuSiteDefLaptop = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLaptop.name, $ouNameDN if($PSBoundParameters['CreateSrvContainer']) { $OuSiteDefLocalServer = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteLocalServer.name, $ouNameDN $OuSiteDefFilePrint = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteFilePrint.name, $ouNameDN } $OuSiteDefMailbox = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteMailbox.name, $ouNameDN $OuSiteDefDistGroup = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteDistGroup.name, $ouNameDN $OuSiteDefContact = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteContact.name, $ouNameDN # parameters variable for splatting CMDlets $parameters = $null #endregion ############################################################################### } process { Write-Verbose -Message 'START USER Site Delegation' ############################################################################### #region USER Site Administrator Delegation $OuSiteDefUser = 'OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteUser.name, $ouNameDN $parameters = @{ Group = $SL_PwdRight.SamAccountName LDAPPath = $OuSiteDefUser } # Reset User Password Set-AdAclResetUserPassword @parameters #Set-AdAclResetUserPassword -Group $SL_CreateUserRight.SamAccountName -LDAPPath $OuSiteDefUser # Change User Password Set-AdAclChangeUserPassword @parameters # Unlock user account Set-AdAclUnlockUser @parameters $parameters = @{ Group = $SL_CreateUserRight.SamAccountName LDAPPath = $OuSiteDefUser } # Create/Delete Users Set-AdAclCreateDeleteUser @parameters # Enable and/or Disable user right Set-AdAclEnableDisableUser @parameters # Change User Restrictions Set-AdAclUserAccountRestriction @parameters # Change User Account Logon Info Set-AdAclUserLogonInfo @parameters #### GAL $parameters = @{ Group = $SL_GALRight.SamAccountName LDAPPath = $OuSiteDefUser } # Change Group Membership Set-AdAclUserGroupMembership @parameters # Change Personal Information Set-AdAclUserPersonalInfo @parameters # Change Public Information Set-AdAclUserPublicInfo @parameters # Change General Information Set-AdAclUserGeneralInfo @parameters # Change Web Info Set-AdAclUserWebInfo @parameters # Change Email Info Set-AdAclUserEmailInfo @parameters #endregion USER Site Delegation ############################################################################### Write-Verbose -Message 'START COMPUTER Site Delegation' ############################################################################### #region COMPUTER Site Admin Delegation # Create/Delete Computers Set-AdAclDelegateComputerAdmin -Group $SL_PcRight.SamAccountName -LDAPPath $OuSiteDefComputer -QuarantineDN $PSBoundParameters['QuarantineDN'] Set-AdAclDelegateComputerAdmin -Group $SL_PcRight.SamAccountName -LDAPPath $OuSiteDefLaptop -QuarantineDN $PSBoundParameters['QuarantineDN'] # Grant the right to delete computers from default container. Move Computers Set-DeleteOnlyComputer -Group $SL_PcRight.SamAccountName -LDAPPath $PSBoundParameters['QuarantineDN'] #### GAL # Change Personal Info Set-AdAclComputerPersonalInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefComputer Set-AdAclComputerPersonalInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefLaptop # Change Public Info Set-AdAclComputerPublicInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefComputer Set-AdAclComputerPublicInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefLaptop if($PSBoundParameters['CreateSrvContainer']) { # Create/Delete Computers Set-AdAclDelegateComputerAdmin -Group $SL_LocalServerRight.SamAccountName -LDAPPath $OuSiteDefFilePrint -QuarantineDN $PSBoundParameters['QuarantineDN'] Set-AdAclDelegateComputerAdmin -Group $SL_LocalServerRight.SamAccountName -LDAPPath $OuSiteDefLocalServer -QuarantineDN $PSBoundParameters['QuarantineDN'] # Grant the right to delete computers from default container. Move Computers Set-DeleteOnlyComputer -Group $SL_LocalServerRight.SamAccountName -LDAPPath $PSBoundParameters['QuarantineDN'] #### GAL # Change Personal Info Set-AdAclComputerPersonalInfo -Group $SL_LocalServerRight.SamAccountName -LDAPPath $OuSiteDefFilePrint Set-AdAclComputerPersonalInfo -Group $SL_LocalServerRight.SamAccountName -LDAPPath $OuSiteDefLocalServer # Change Public Info Set-AdAclComputerPublicInfo -Group $SL_LocalServerRight.SamAccountName -LDAPPath $OuSiteDefFilePrint Set-AdAclComputerPublicInfo -Group $SL_LocalServerRight.SamAccountName -LDAPPath $OuSiteDefLocalServer } #endregion COMPUTER Site Delegation ############################################################################### Write-Verbose -Message 'START GROUP Site Delegation' ############################################################################### #region GROUP Site Admin Delegation # Create/Delete Groups Set-AdAclCreateDeleteGroup -Group $SL_GroupRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteGroup.name, $ouNameDN) #### GAL # Change Group Properties Set-AdAclChangeGroup -Group $SL_GroupRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteGroup.name, $ouNameDN) #endregion GROUP Site Delegation ############################################################################### Write-Verbose -Message 'START PRINTQUEUE Site Admin Delegation' ############################################################################### #region PRINTQUEUE Site Admin Delegation # Create/Delete Print Queue Set-AdAclCreateDeletePrintQueue -Group $SL_SiteRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSitePrintQueue.name, $ouNameDN) #endregion PRINTQUEUE Site Admin Delegation ############################################################################### Write-Verbose -Message 'START PRINTQUEUE Site GAL Delegation' ############################################################################### #region PRINTQUEUE Site GAL Delegation Set-AdAclChangePrintQueue -Group $SL_GALRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSitePrintQueue.name, $ouNameDN) #endregion PRINTQUEUE Site GAL Delegation ############################################################################### Write-Verbose -Message 'START VOLUME Site Admin Delegation' ############################################################################### #region VOLUME Site Admin Delegation # Create/Delete Volume Set-AdAclCreateDeleteVolume -Group $SL_SiteRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteShares.name, $ouNameDN) #endregion VOLUME Site Admin Delegation ############################################################################### Write-Verbose -Message 'START VOLUME Site GAL Delegation' ############################################################################### #region VOLUME Site GAL Delegation # Change Volume Properties Set-AdAclChangeVolume -Group $SL_GALRight.SamAccountName -LDAPPath ('OU={0},{1}' -f $confXML.n.Sites.OUs.OuSiteShares.name, $ouNameDN) #endregion VOLUME Site GAL Delegation ############################################################################### Write-Verbose -Message 'START Exchange Related delegation' ############################################################################### #region Exchange Related delegation ############################################################################### If($PSBoundParameters['CreateExchange']) { # USER class # Create/Delete Users Set-AdAclCreateDeleteUser -Group $SL_CreateUserRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Reset User Password Set-AdAclResetUserPassword -Group $SL_PwdRight.SamAccountName -LDAPPath $OuSiteDefMailbox #Set-AdAclResetUserPassword -Group $SL_CreateUserRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change User Password Set-AdAclChangeUserPassword -Group $SL_PwdRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change User Restrictions Set-AdAclUserAccountRestriction -Group $SL_SiteRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change User Account Logon Info Set-AdAclUserLogonInfo -Group $SL_SiteRight.SamAccountName -LDAPPath $OuSiteDefMailbox #-------------------------------------------------- # Change Group Membership Set-AdAclUserGroupMembership -Group $SL_SiteRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change Personal Information Set-AdAclUserPersonalInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change Public Information Set-AdAclUserPublicInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change General Information Set-AdAclUserGeneralInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change Web Info Set-AdAclUserWebInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefMailbox # Change Email Info Set-AdAclUserEmailInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefMailbox # GROUP Class # Create/Delete Groups Set-AdAclCreateDeleteGroup -Group $SL_GroupRight.SamAccountName -LDAPPath $OuSiteDefDistGroup #-------------------------------------------------- # Change Group Properties Set-AdAclChangeGroup -Group $SL_GroupRight.SamAccountName -LDAPPath $OuSiteDefDistGroup # CONTACT Class # Create/Delete Contacts Set-AdAclCreateDeleteContact -Group $SL_SiteRight.SamAccountName -LDAPPath $OuSiteDefContact #-------------------------------------------------- # Change Personal Info Set-AdAclContactPersonalInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefContact # Change Web Info Set-AdAclContactWebInfo -Group $SL_GALRight.SamAccountName -LDAPPath $OuSiteDefContact } #endregion Exchange Related delegation ############################################################################### } end { Write-Verbose -Message ('Site delegation was completed succesfully to {0}' -f $PSBoundParameters['ouName']) Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Start-AdDelegatedSite #EndRegion - Start-AdDelegatedSite.ps1 #Region - Test-IPv4MaskString.ps1 function Test-IPv4MaskString { <# .SYNOPSIS Tests whether an IPv4 network mask string (e.g., "255.255.255.0") is valid. .DESCRIPTION Tests whether an IPv4 network mask string (e.g., "255.255.255.0") is valid. .PARAMETER MaskString Specifies the IPv4 network mask string (e.g., "255.255.255.0"). .EXAMPLE Test-IPv4MaskString -MaskString "255.255.255.0" .INPUTS Param1 MaskString:............ [STRING] Specifies the IPv4 network mask string #> [CmdletBinding(ConfirmImpact = 'Medium')] Param ( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = "Specifies the IPv4 network mask string (e.g., 255.255.255.0)", Position = 1)] [String] $MaskString ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { $validBytes = '0|128|192|224|240|248|252|254|255' $maskPattern = ('^((({0})\.0\.0\.0)|' -f $validBytes) + ('(255\.({0})\.0\.0)|' -f $validBytes) + ('(255\.255\.({0})\.0)|' -f $validBytes) + ('(255\.255\.255\.({0})))$' -f $validBytes) $MaskString -match $maskPattern } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Test-IPv4MaskString #EndRegion - Test-IPv4MaskString.ps1 #Region - Test-RegistryValue.ps1 function Test-RegistryValue { <# .Synopsis Function to Test Registry Values .DESCRIPTION .INPUTS Param1 Path:...[STRING] Registry path to be tested Param2 Value:..[STRING] Registry value to be tested .EXAMPLE Test-RegistryValue -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Value "AutoAdminLogon" Test-RegistryValue "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" "AutoAdminLogon" .NOTES Version: 1.0 DateModified: 16/Ene/2018 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([Bool])] Param ( [parameter(Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Registry path to be tested', Position = 0)] [ValidateNotNullOrEmpty()] [string] $Path, [parameter(Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Registry value to be tested', Position = 1)] [ValidateNotNullOrEmpty()] [string] $Value ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { try { Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null return $true } catch { return $false } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished testing registry." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } Export-ModuleMember -Function Test-RegistryValue #EndRegion - Test-RegistryValue.ps1 ### --- PRIVATE FUNCTIONS --- ### #Region - Add-AdGroupNesting.ps1 # http://blogs.technet.com/b/lrobins/archive/2011/06/23/quot-admin-free-quot-active-directory-and-windows-part-1-understanding-privileged-groups-in-ad.aspx # http://blogs.msmvps.com/acefekay/2012/01/06/using-group-nesting-strategy-ad-best-practices-for-group-strategy/ function Add-AdGroupNesting { <# .SYNOPSIS Same as Add-AdGroupMember but with error handling and loging .DESCRIPTION Same as Add-AdGroupMember but with error handling and loging .EXAMPLE Add-AdGroupNesting -Identity "Domain Admins" -Members TheUgly .NOTES Version: 1.0 DateModified: 22/Jun/2016 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param ( # Param1 Group which membership is to be changed [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Group which membership is to be changed', Position = 0)] [ValidateNotNullOrEmpty()] $Identity, # Param2 ID of New Member of the group [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'ID of New Member of the group. Can be a single string or array.', Position = 1)] [ValidateNotNullOrEmpty()] $Members ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ActiveDirectory -Verbose:$false # Active Directory Domain Distinguished Name If(-Not (Test-Path -Path variable:AdDn)) { New-Variable -Name 'AdDn' -Value ([ADSI]'LDAP://RootDSE').rootDomainNamingContext.ToString() -Option ReadOnly -Force } # Define an empty array $CurrentMembers = @() $NewMembers = @() $parameters = $null If($identity.GetType() -eq [Microsoft.ActiveDirectory.Management.AdGroup]) { $Group = Get-AdGroup -Identity $Identity.ObjectGUID } If($identity.GetType() -eq [System.String]) { If($identity -ccontains $AdDn) { $Group = Get-AdGroup -Filter { distinguishedName -eq $Identity } } ELSE { $Group = Get-AdGroup -Filter { samAccountName -eq $Identity } } } } Process { # Get group members Get-AdGroupMember -Identity $Group.SID | Select-Object -ExpandProperty sAMAccountName | ForEach-Object { $CurrentMembers += $_ } try { Write-Verbose -Message ('Adding members to group..: {0}' -f $Group.SamAccountName) Foreach ($item in $Members) { If($CurrentMembers -notcontains $item) { $NewMembers += $item } else { Write-Verbose -Message ('{0} is already member of {1} group' -f $item.SamAccountName, $Group.SamAccountName) } } If($NewMembers.Count -gt 0) { $parameters = @{ Identity = $Group Members = $NewMembers } Add-AdGroupMember @parameters } #Add-AdGroupMember @parameters Write-Verbose -Message ('Member {0} was added correctly to group {1}' -f $Members, $Group.sAMAccountName) } catch { throw } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) adding members to the group." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' } } #EndRegion - Add-AdGroupNesting.ps1 #Region - Get-AdObjectType.ps1 function Get-AdObjectType { [CmdletBinding(ConfirmImpact = 'Medium')] Param ( # Param1 [Parameter(Mandatory = $true,HelpMessage = 'Add help message for user', ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, Position = 0)] [ValidateNotNullOrEmpty()] $Identity ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" $ReturnValue = $null } Process { If($Identity -is [Microsoft.ActiveDirectory.Management.ADAccount]) { Write-Verbose -Message 'AD User Object' return [Microsoft.ActiveDirectory.Management.ADAccount]$ReturnValue = $Identity } If($Identity -is [Microsoft.ActiveDirectory.Management.ADComputer]) { Write-Verbose -Message 'AD Computer Object' return [Microsoft.ActiveDirectory.Management.ADComputer]$ReturnValue = $Identity } If($Identity -is [Microsoft.ActiveDirectory.Management.AdGroup]) { Write-Verbose -Message 'AD Group Object' return [Microsoft.ActiveDirectory.Management.AdGroup]$ReturnValue = $Identity } If($Identity -is [String]) { Write-Verbose -Message 'Simple String' $newObject = get-AdObject -filter { SamAccountName -eq $Identity } Switch ($newObject.ObjectClass) { 'user' { Write-Verbose -Message 'AD User Object from STRING' return [Microsoft.ActiveDirectory.Management.ADAccount]$ReturnValue = Get-AdUser -Identity $Identity } 'group' { Write-Verbose -Message 'AD Group Object from STRING' return [Microsoft.ActiveDirectory.Management.AdGroup]$ReturnValue = Get-ADGroup -Identity $Identity } 'computer' { Write-Verbose -Message 'AD Computer Object from STRING' return [Microsoft.ActiveDirectory.Management.AdGroup]$ReturnValue = Get-AdComputer -Identity $Identity } } } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished getting AD object type." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } #EndRegion - Get-AdObjectType.ps1 #Region - Get-IniContent.ps1 function Get-IniContent { <# .Synopsis Gets the content of an INI file .Description Gets the content of an INI file and returns it as a hashtable .Notes Author : Oliver Lipkau <oliver@lipkau.net> Blog : http://oliver.lipkau.net/blog/ Source : https://github.com/lipkau/PsIni http://gallery.technet.microsoft.com/scriptcenter/ea40c1ef-c856-434b-b8fb-ebd7a76e8d91 Version : 1.0 - 2010/03/12 - Initial release 1.1 - 2014/12/11 - Typo (Thx SLDR) Typo (Thx Dave Stiff) #Requires -Version 2.0 .Inputs System.String .Outputs System.Collections.Hashtable .Parameter FilePath Specifies the path to the input file. .Example $FileContent = Get-IniContent "C:\myinifile.ini" ----------- Description Saves the content of the c:\myinifile.ini in a hashtable called $FileContent .Example $inifilepath | $FileContent = Get-IniContent ----------- Description Gets the content of the ini file passed through the pipe into a hashtable called $FileContent .Example C:\PS>$FileContent = Get-IniContent "c:\settings.ini" C:\PS>$FileContent["Section"]["Key"] ----------- Description Returns the key "Key" of the section "Section" from the C:\settings.ini file .Link Out-IniFile #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([System.Collections.Hashtable])] Param( [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipeline = $true,HelpMessage = 'Path and Filename to the ini file to be read',Mandatory = $true)] [string]$FilePath ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Processing file: $PSBoundParameters['FilePath']" $ini = @{} switch -regex -file $PSBoundParameters['FilePath'] { '^\[(.+)\]$' # Section { $section = $matches[1] $ini[$section] = @{} $CommentCount = 0 } '^(;.*)$' # Comment { if (!($section)) { $section = 'No-Section' $ini[$section] = @{} } $value = $matches[1] $CommentCount = $CommentCount + 1 $name = 'Comment' + $CommentCount $ini[$section][$name] = $value } '(.+?)\s*=\s*(.*)' # Key { if (!($section)) { $section = 'No-Section' $ini[$section] = @{} } $name, $value = $matches[1..2] $ini[$section][$name] = $value } } Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Finished Processing file: $PSBoundParameters['FilePath']" Return $ini } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished reading content from $PSBoundParameters['FilePath'] file." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } #EndRegion - Get-IniContent.ps1 #Region - Get-RandomHex.ps1 Function Get-RandomHex { param ([int]$Length) $Hex = '0123456789ABCDEF' [string]$Return = $null For ($i=1;$i -le $length;$i++) { $Return += $Hex.Substring((Get-Random -Minimum 0 -Maximum 16),1) } Return $Return } #EndRegion - Get-RandomHex.ps1 #Region - IsUniqueOID.ps1 Function IsUniqueOID { [CmdletBinding(ConfirmImpact = 'low')] [OutputType([System.Boolean])] param ( $cn, $TemplateOID, $Server, $ConfigNC ) $Search = Get-ADObject -Server $Server ` -SearchBase "CN=OID,CN=Public Key Services,CN=Services,$ConfigNC" ` -Filter {cn -eq $cn -and msPKI-Cert-Template-OID -eq $TemplateOID} If ($Search) {$False} Else {$True} } #EndRegion - IsUniqueOID.ps1 #Region - New-AdDelegatedGroup.ps1 function New-AdDelegatedGroup { <# .SYNOPSIS Same as New-AdGroup but with error handling, Security changes and loging .DESCRIPTION Native New-AdGroup throws an error exception when the group already exists. This error is handeled as a "correct" within this function due the fact that group might already exist and operation should continue after writting a log. .EXAMPLE New-AdDelegatedGroup -Name "Poor Admins" -GroupCategory Security -GroupScope DomainLocal -DisplayName "Poor Admins" -Path 'OU=Groups,OU=Admin,DC=EguibarIT,DC=local' -Description 'New Admin Group' .PARAMS PARAM1........: [STRING] Name PARAM2........: [ValidateSet] GroupCategory PARAM3........: [ValidateSet] GroupScope PARAM4........: [STRING] DisplayName PARAM5........: [STRING] Path PARAM6........: [STRING] Description PARAM7........: [SWITCH] ProtectFromAccidentalDeletion PARAM8........: [SWITCH] RemoveAccountOperators PARAM9........: [SWITCH] RemoveEveryone PARAM10.......: [SWITCH] RemoveAuthUsers PARAM11.......: [SWITCH] RemovePreWin2000 .NOTES Version: 1.1 DateModified: 15/Feb/2017 LasModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar Information Technology S.L. http://www.eguibarit.com #> [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([Microsoft.ActiveDirectory.Management.AdGroup])] Param ( # Param1 Group which membership is to be changed [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Name of the group to be created. SamAccountName', Position = 0)] [ValidateNotNullOrEmpty()] $Name, # Param2 Group category, either Security or Distribution [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Group category, either Security or Distribution', Position = 1)] [ValidateSet('Security','Distribution')] $GroupCategory, # Param3 Group Scope, either DomainLocal, Global or Universal [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Group Scope, either DomainLocal, Global or Universal', Position = 2)] [ValidateSet('DomainLocal','Global','Universal')] $GroupScope, # Param4 Display Name of the group to be created [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Display Name of the group to be created', Position = 3)] [ValidateNotNullOrEmpty()] $DisplayName, # Param5 DistinguishedName of the container where the group will be created. [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'DistinguishedName of the container where the group will be created.', Position = 4)] [ValidateNotNullOrEmpty()] $path, # Param6 Description of the group. [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Description of the group.', Position = 5)] [ValidateNotNullOrEmpty()] $Description, # Param7 Protect from accidental deletion. [Parameter(Mandatory = $False, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Protect from accidental deletion.', Position = 6)] [Switch] $ProtectFromAccidentalDeletion, # Param8 Remove Account Operators Built-In group. [Parameter(Mandatory = $False, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Remove Account Operators Built-In group', Position = 7)] [Switch] $RemoveAccountOperators, # Param9 Remove Everyone Built-In group. [Parameter(Mandatory = $False, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Remove Everyone Built-In group', Position = 8)] [Switch] $RemoveEveryone, # Param10 Remove Authenticated Users Built-In group. [Parameter(Mandatory = $False, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Remove Authenticated Users Built-In group', Position = 9)] [Switch] $RemoveAuthUsers, # Param11 Remove Pre-Windows 2000 Built-In group. [Parameter(Mandatory = $False, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Remove Pre-Windows 2000 Built-In group', Position = 10)] [Switch] $RemovePreWin2000 ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" Import-Module -name ActiveDirectory -Verbose:$false Import-Module -name EguibarIT.Delegation -Verbose:$false $parameters = $null $newGroup = $null } Process { try { # Get the group and store it on variable. $newGroup = Get-AdGroup -Filter { SamAccountName -eq $Name } ### Using $PSBoundParameters['Name'] throws an Error. Using variable instead. If(-not($newGroup)) { $parameters = @{ Name = $PSBoundParameters['Name'] SamAccountName = $PSBoundParameters['Name'] GroupCategory = $PSBoundParameters['GroupCategory'] GroupScope = $PSBoundParameters['GroupScope'] DisplayName = $PSBoundParameters['DisplayName'] Path = $PSBoundParameters['path'] Description = $PSBoundParameters['Description'] } New-ADGroup @parameters } else { Write-Warning -Message ('Groups {0} already exists. Modifying the group!' -f $PSBoundParameters['Name']) $newGroup | Set-AdObject -ProtectedFromAccidentalDeletion $False Try { $parameters = @{ Identity = $PSBoundParameters['Name'] Description = $PSBoundParameters['Description'] DisplayName = $PSBoundParameters['DisplayName'] GroupCategory = $PSBoundParameters['GroupCategory'] GroupScope = $PSBoundParameters['GroupScope'] } Set-AdGroup @parameters If(-not($newGroup.DistinguishedName -ccontains $PSBoundParameters['path'])) { # Move object to the corresponding OU Move-ADObject -Identity $newGroup -TargetPath $PSBoundParameters['path'] } } catch { throw } } # Get the group again and store it on variable. $newGroup = Get-AdGroup -Filter { SamAccountName -eq $Name } # Protect From Accidental Deletion If($PSBoundParameters['ProtectFromAccidentalDeletion']) { $newGroup | Set-ADObject -ProtectedFromAccidentalDeletion $true } # Remove Account Operators Built-In group If($PSBoundParameters['RemoveAccountOperators']) { Remove-AccountOperator -LDAPPath $newGroup.DistinguishedName } # Remove Everyone Built-In group If($PSBoundParameters['RemoveEveryone']) { Remove-Everyone -LDAPPath $newGroup.DistinguishedName } # Remove Authenticated Users Built-In group If($PSBoundParameters['RemoveAuthUsers']) { Remove-AuthUser -LDAPPath $newGroup.DistinguishedName } # Remove Pre-Windows 2000 Built-In group If($PSBoundParameters['RemovePreWin2000']) { Remove-PreWin2000 -LDAPPath $newGroup.DistinguishedName } } catch { throw Write-Warning -Message ('An unhandeled error was thrown when creating Groups {0}' -f $PSBoundParameters['Name']) } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished creating Delegated Group." Write-Verbose -Message '' Write-Verbose -Message '--------------------------------------------------------------------------------' Write-Verbose -Message '' #Return the group object. return $newGroup } } #EndRegion - New-AdDelegatedGroup.ps1 #Region - New-Template.ps1 Function New-Template { [CmdletBinding(ConfirmImpact = 'Medium')] Param( $DisplayName, $TemplateOtherAttributes ) #grab DC $Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0] #grab Naming Context $ConfigNC = (Get-ADRootDSE -Server $Server).configurationNamingContext #Create OID $OID = New-TemplateOID -Server $Server -ConfigNC $ConfigNC $TemplateOIDPath = "CN=OID,CN=Public Key Services,CN=Services,$ConfigNC" $OIDOtherAttributes = @{ 'DisplayName' = $DisplayName 'flags' = [System.Int32]'1' 'msPKI-Cert-Template-OID' = $OID.TemplateOID } New-ADObject -Path $TemplateOIDPath -OtherAttributes $OIDOtherAttributes -Name $OID.TemplateName -Type 'msPKI-Enterprise-Oid' -Server $Server #Create Template itself $TemplateOtherAttributes+= @{ 'msPKI-Cert-Template-OID' = $OID.TemplateOID } $TemplatePath = "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC" New-ADObject -Path $TemplatePath -OtherAttributes $TemplateOtherAttributes -Name $DisplayName -DisplayName $DisplayName -Type pKICertificateTemplate -Server $Server } #EndRegion - New-Template.ps1 #Region - New-TemplateOID.ps1 Function New-TemplateOID { [CmdletBinding(ConfirmImpact = 'Medium')] [OutputType([System.Collections.Hashtable])] Param( $Server, $ConfigNC ) <# OID CN/Name [10000000-99999999].[32 hex characters] OID msPKI-Cert-Template-OID [Forest base OID].[1000000-99999999].[10000000-99999999] <--- second number same as first number in OID name #> do { $OID_Part_1 = Get-Random -Minimum 1000000 -Maximum 99999999 $OID_Part_2 = Get-Random -Minimum 10000000 -Maximum 99999999 $OID_Part_3 = Get-RandomHex -Length 32 $OID_Forest = Get-ADObject -Server $Server ` -Identity "CN=OID,CN=Public Key Services,CN=Services,$ConfigNC" ` -Properties msPKI-Cert-Template-OID | Select-Object -ExpandProperty msPKI-Cert-Template-OID $msPKICertTemplateOID = "$OID_Forest.$OID_Part_1.$OID_Part_2" $Name = "$OID_Part_2.$OID_Part_3" } until (IsUniqueOID -cn $Name -TemplateOID $msPKICertTemplateOID -Server $Server -ConfigNC $ConfigNC) Return @{ TemplateOID = $msPKICertTemplateOID TemplateName = $Name } } #EndRegion - New-TemplateOID.ps1 #Region - Out-IniFile.ps1 Function Out-IniFile { <# .Synopsis Write hash content to INI file .Description Write hash content to INI file .Notes Author : Oliver Lipkau <oliver@lipkau.net> Blog : http://oliver.lipkau.net/blog/ Source : https://github.com/lipkau/PsIni http://gallery.technet.microsoft.com/scriptcenter/ea40c1ef-c856-434b-b8fb-ebd7a76e8d91 Version : 1.0 - 2010/03/12 - Initial release 1.1 - 2012/04/19 - Bugfix/Added example to help (Thx Ingmar Verheij) 1.2 - 2014/12/11 - Improved handling for missing output file (Thx SLDR) #Requires -Version 2.0 .Inputs System.String System.Collections.Hashtable .Outputs System.IO.FileSystemInfo .Parameter Append Adds the output to the end of an existing file, instead of replacing the file contents. .Parameter InputObject Specifies the Hashtable to be written to the file. Enter a variable that contains the objects or type a command or expression that gets the objects. .Parameter FilePath Specifies the path to the output file. .Parameter Encoding Specifies the type of character encoding used in the file. Valid values are "Unicode", "UTF7", "UTF8", "UTF32", "ASCII", "BigEndianUnicode", "Default", and "OEM". "Unicode" is the default. "Default" uses the encoding of the system's current ANSI code page. "OEM" uses the current original equipment manufacturer code page identifier for the operating system. .Parameter Force Allows the cmdlet to overwrite an existing read-only file. Even using the Force parameter, the cmdlet cannot override security restrictions. .Parameter PassThru Passes an object representing the location to the pipeline. By default, this cmdlet does not generate any output. .Example Out-IniFile $IniVar "C:\myinifile.ini" ----------- Description Saves the content of the $IniVar Hashtable to the INI File c:\myinifile.ini .Example $IniVar | Out-IniFile "C:\myinifile.ini" -Force ----------- Description Saves the content of the $IniVar Hashtable to the INI File c:\myinifile.ini and overwrites the file if it is already present .Example $file = Out-IniFile $IniVar "C:\myinifile.ini" -PassThru ----------- Description Saves the content of the $IniVar Hashtable to the INI File c:\myinifile.ini and saves the file into $file .Example $Category1 = @{“Key1”=”Value1”;”Key2”=”Value2”} $Category2 = @{“Key1”=”Value1”;”Key2”=”Value2”} $NewINIContent = @{“Category1”=$Category1;”Category2”=$Category2} Out-IniFile -InputObject $NewINIContent -FilePath "C:\MyNewFile.INI" ----------- Description Creating a custom Hashtable and saving it to C:\MyNewFile.INI .Link Get-IniContent #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] Param( [switch]$Append, [ValidateSet('Unicode','UTF7','UTF8','UTF32','ASCII','BigEndianUnicode','Default','OEM', ignorecase = $false)] [string]$Encoding = 'Unicode', [ValidateNotNullOrEmpty()] [Parameter(Mandatory = $true,HelpMessage = 'Path and Filename to write the file to.')] [string]$FilePath, [switch]$Force, [ValidateNotNullOrEmpty()] [Parameter(ValueFromPipeline = $true,HelpMessage = 'The HashTable object name to create the file from',Mandatory = $true)] [Hashtable]$InputObject, [switch]$Passthru ) Begin { Write-Verbose -Message '|=> ************************************************************************ <=|' Write-Verbose -Message (Get-Date).ToShortDateString() Write-Verbose -Message (' Starting: {0}' -f $MyInvocation.Mycommand) #display PSBoundparameters formatted nicely for Verbose output $NL = "`n" # New Line $HTab = "`t" # Horizontal Tab [string]$pb = ($PSBoundParameters | Format-Table -AutoSize | Out-String).TrimEnd() Write-Verbose -Message "Parameters used by the function... $NL$($pb.split($NL).Foreach({"$($HTab*4)$_"}) | Out-String) $NL" } Process { Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Writing to file: $PSBoundParameters['FilePath']" if ($PSBoundParameters['Append']) { $outfile = Get-Item -Path $PSBoundParameters['FilePath'] } else { $outfile = New-Item -ItemType file -Path $PSBoundParameters['FilePath'] -Force:$PSBoundParameters['Force'] } if (!($outfile)) { Throw 'Could not create File' } foreach ($i in $InputObject.keys) { if (!($($InputObject[$i].GetType().Name) -eq 'Hashtable')) { #No Sections Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Writing key: $i" Add-Content -Path $outfile -Value "$i=$($InputObject[$i])" -Encoding $PSBoundParameters['Encoding'] } else { #Sections Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Writing Section: [$i]" Add-Content -Path $outfile -Value "[$i]" -Encoding $PSBoundParameters['Encoding'] Foreach ($j in $($InputObject[$i].keys | Sort-Object)) { if ($j -match '^Comment[\d]+') { Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Writing comment: $j" Add-Content -Path $outfile -Value "$($InputObject[$i][$j])" -Encoding $PSBoundParameters['Encoding'] } else { Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Writing key: $j" Add-Content -Path $outfile -Value "$j=$($InputObject[$i][$j])" -Encoding $PSBoundParameters['Encoding'] } } Add-Content -Path $outfile -Value '' -Encoding $PSBoundParameters['Encoding'] } } Write-Verbose -Message "$($myInvocation.MyCommand.Name):: Finished Writing to file: $path" if ($PSBoundParameters['Passthru']) { Return $outfile } } End { Write-Verbose -Message "Function $($MyInvocation.InvocationName) finished writing to $PSBoundParameters['FilePath'] INI file." Write-Verbose -Message '' Write-Verbose -Message '-------------------------------------------------------------------------------' Write-Verbose -Message '' } } #EndRegion - Out-IniFile.ps1 #Region - PublishCert.ps1 Function PublishCert { Param ( $CertDisplayName ) #Publish Template #grab DC $Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0] #grab Naming Context $ConfigNC = (Get-ADRootDSE -Server $Server).configurationNamingContext ### WARNING: Issues on all available CAs. Test in your environment. $EnrollmentPath = "CN=Enrollment Services,CN=Public Key Services,CN=Services,$ConfigNC" $CAs = Get-ADObject -SearchBase $EnrollmentPath -SearchScope OneLevel -Filter * -Server $Server ForEach ($CA in $CAs) { Set-ADObject -Identity $CA.DistinguishedName -Add @{certificateTemplates=$CertDisplayName.Replace(' ','')} -Server $Server } } #EndRegion - PublishCert.ps1 |