As part of the work I have been doing around generating and managing lab environments using Lability and DSC, one of the things I needed to do was change the permissions on a certificate template within a DSC configuration. Previously, when deploying to Azure, I used the PSPKI PowerShell modules within code executed by the Custom Script extension. I was very focused on sticking with DSC this time, which ruled out PSPKI. Whilst there is a DSC module available to configure Certificate Services itself, this does not extend to managing Certificate Templates.
Nobody seemed to have done exactly this before. I used the following links as references in creating the code:
Get Effective template permissions with PowerShell by Vadims Podans
Duplicate AD Object Without Active Directory PS Tools
Add Object Specific ACEs using Active Directory PowerShell
Using Scripts to Manage Active Directory Security
The script finds the WebServer template and grants the Enroll extended permission to the Domain Computers AD group. This allows me to use xCertificate in the DSC configuration of domain member servers to request new certificates using the WebServer template.
Here is the code I include in my DSC configuration. $DomainCreds is a PSCredential object for the domain admin ( I create the AD domain in an earlier step using xActiveDirectory).
#Enable Enroll on WebServer certificate template
Script EnableWebServerEnroll {
DependsOn = "[xAdcsCertificationAuthority]CertAuth"
PsDscRunAsCredential = $DomainCreds
GetScript = {
return @{ 'Result' = $true}
}
TestScript = {
#Find the webserver template in AD and grant the Enroll extended right to the Domain Computers
$filter = "(cn=WebServer)"
$ConfigContext = ([ADSI]"LDAP://RootDSE").configurationNamingContext
$ConfigContext = "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigContext"
$ds = New-object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$ConfigContext",$filter)
$Template = $ds.Findone().GetDirectoryEntry()
if ($Template -ne $null) {
$objUser = New-Object System.Security.Principal.NTAccount("Domain Computers")
# The following object specific ACE is to grant Enroll
$objectGuid = New-Object Guid 0e10c968-78fb-11d2-90d4-00c04f79dc55
ForEach ($AccessRule in $Template.ObjectSecurity.Access) {
If ($AccessRule.ObjectType.ToString() \-eq $objectGuid) {
If ($AccessRule.IdentityReference -like "*$($objUser.Value)") {
Write-Verbose "TestScript: WebServer Template Enroll permission for Domain Computers exists. Returning True"
return $true
}
}
}
}
return $false
}
SetScript = {
#Find the webserver template in AD and grant the Enroll extended right to the Domain Computers
$filter = "(cn=WebServer)"
$ConfigContext = ([ADSI]"LDAP://RootDSE").configurationNamingContext
$ConfigContext = "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigContext"
$ds = New-object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$ConfigContext",$filter)
$Template = $ds.Findone().GetDirectoryEntry()
if ($Template -ne $null) {
$objUser = New-Object System.Security.Principal.NTAccount("Domain Computers")
# The following object specific ACE is to grant Enroll
$objectGuid = New-Object Guid 0e10c968-78fb-11d2-90d4-00c04f79dc55
$ADRight = [System.DirectoryServices.ActiveDirectoryRights]"ExtendedRight"
$ACEType = [System.Security.AccessControl.AccessControlType]"Allow"
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList $objUser,$ADRight,$ACEType,$objectGuid
$Template.ObjectSecurity.AddAccessRule($ACE)
$Template.commitchanges()
Write-Verbose "SetScript: Completed WebServer additional permission"
}
}
}