Enable Certificate Enrollment Policy and Request a Cert using PowerShell
I presume your certificate requests are made using a template. If that's the case then use the Public Key Policies/Certificate Services Client - Auto-Enrollment Settings
GPO to enforce auto enrollment. You'll also want to ensure the template ACL has Enroll
and AutoEnroll
marked for either domain computers or domain users (or whatever acl object, depending on the intended audience) There's a user config and computer config policy to leverage depending on whether or not it's a machine cert or user cert you're trying to push. Enrollment begins as soon as when the policy is pushed (usually about 15 minutes) after the GPO is linked and enforced.
This is the process I have used on Windows 2012 R2 and higher. All PowerShell code was run from an elevated PowerShell prompt. Complete automation is left as an exercise for the user.
Prerequisite
Ensure that you have a Template on your Certificate Server that has the "Supply in the request" radio button selected in the Subject tab. Because this is not an AD machine, the certificate server cannot adequately query Active Directory for the information.
Export the Root
Export the Trusted Root Certification Authority Certificate on your Certificate Server and then copy that certificate file to your Target Server
certutil --% -ca.cert <name of certificate file>
Trust the Root
Import that certificate to the Trusted Root Certification Authority on your Target Server
$PathToCertificate=<name of certificate file>
$RootCertificate=Get-PfxCertificate -FilePath $PathToCertificate
$AlreadyExists=Get-ChildItem -Path "Cert:\LocalMachine\Root" | Where-Object { $_.Thumbprint -eq $RootCertificate.Thumbprint }
if ($AlreadyExists -eq $null) { Import-Certificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath $PathToCertificate }
else { Write-Warning "Root certificate already installed" }
Active Directory Policy Provider
Determine the URL for the Active Directory Policy Provider
# Get AD Configuration Context
$RootDSE=[System.DirectoryServices.DirectoryEntry]::new("LDAP://RootDSE")
$ConfigContext="CN=Enrollment Services,CN=Public Key Services,CN=Services,"+$RootDSE.configurationNamingContext
# Get name of Enterprise Root Certificate Autority server
$Server=Get-ADObject -SearchBase $ConfigContext -Filter "*"
if ($Server.Count -eq 1) { throw "No Enterprise Root Certificate Autority server exists" }
else { $Server=$Server[1].Name }
# Get Enrollment URL
$ConfigContext="CN=$Server,"+$ConfigContext
$EnrollmentURL=(Get-ADObject -SearchBase $ConfigContext -Filter "*" -Properties "msPKI-Enrollment-Servers" | Select-Object -ExpandProperty "msPKI-Enrollment-Servers").Split("`n") | Where-Object { $_ -like "http*" }
if ($EnrollmentURL -eq $null) { $EnrollmentURL="" }
# Get AD Enrollment Policy URL
$Server=$Server+$RootDSE.configurationNamingContext.Value.Replace("CN=Configuration","").Replace(",DC=",".")
$WMI=Get-WmiObject -ComputerName $Server -Namespace "root\WebAdministration" -Class Application | Where-Object { $_.Path -eq "/ADPolicyProvider_CEP_UsernamePassword" }
if ($WMI -ne $null) { $PolicyURL="https://"+$Server+$WMI.Path+"/service.svc/CEP" }
else { $PolicyURL="" }
Write-Output "Enrollment URL = $EnrollmentURL"
Write-Output "Policy URL = $PolicyURL"
Enrollment Policy
Add the Enrollment Policy to the Target Server (This only works on Windows 2012 and higher. For GUI instructions, see below). Make sure that the Policy is added after you create the non-domain template, otherwise it will not appear as it the policy does not get refreshed.
$User="<your domain name>\<your domain user name>"
$Pass="<Your domain password>"
$SecPass=ConvertTo-SecureString -String $Pass -AsPlainText -Force
$Cred=[System.Management.Automation.PSCredential]::new($User,$SecPass)
Add-CertificateEnrollmentPolicyServer -Url $PolicyURL -context Machine -NoClobber -AutoEnrollmentEnabled -Credential $Cred
Get the certificate
You should now be able to enroll for a certificate using the desired template
$DNS="<FQDN of your server>"
$URL=Get-CertificateEnrollmentPolicyServer -Scope All -Context Machine | Select-Object -ExpandProperty Url | Select-Object -ExpandProperty AbsoluteUri
$Enrollment=Get-Certificate -Url $URL -Template "<Template name (not display name)>" -SubjectName "CN=$DNS" -DnsName $DNS -Credential $Cred -CertStoreLocation cert:\LocalMachine\My
$Enrollment.Certificate.FriendlyName=$DNS
Enrollment Policy Pre-Windows 2012 R2
- Open the certificates MMC
- Drill down to the Personal Certificate Store
- Right click "Certificates" and selet All Tasks/Advanced Operations/Manage
- Enrollment Policies from the context menu
- Click the "Add" button
- Paste the URL for the enrollment policy
- Select Username/password as the Authentication type
- Click the "Validate Server" button and enter your domain credentials, including the domain
- Assuming you have been able to successfully validate, click the "Add" button
- Select the enrollment policy and click the "Properties" button
- Make sure that the "Enable for automatic enrollment and renewal" box is checked
- I have never checked the "Require strong validation during enrollment" so I don't know what it does