Creating a certificate template usually starts with opening certtmpl.msc, duplicating an existing template and working through the tabs. Give it a name, select the cryptographic settings, configure the subject and permissions, and publish it on the issuing CA. For a single template, that works perfectly fine. When you need to repeat the same configuration across different environments, I prefer having those choices written down in a script.
After working on scripts for requesting certificates and exporting certificates and private keys, I wanted to take the next step, creating and configuring the certificate templates themselves.
That turned into a small PowerShell project. Along the way, I also ran into a few details worth sharing. Copying a template involves more than changing its name, and a successful command does not always mean the object you expected was actually found.
Update – 26 October 2026, 21:00 – Version 1.1.0
Community feedback highlighted something my initial tests had missed, the name of the templates associated object in the AD OID container. Earlier versions used a random GUID, which could leave that object behind when deleting the template through certtmpl.msc. Version 1.1.0 corrects the naming. I tested deletion for both newly created and imported templates and confirmed that both objects were removed.
This release also adds JSON export and import, including template settings and optional preservation of permissions within the same forest. The complete round trip, including publication and certificate enrollment, passed my lab test.
The tools now have their own home: ADCertificateTemplate on GitHub.
Please use the updated version for new templates. Existing OID registrations created by earlier versions are not automatically repaired. Thanks for the feedback it helped catch an important part of the template lifecycle!
Creating a template versus publishing it
Certificate templates are stored in the Configuration partition of Active Directory, under:
CN=Certificate Templates,
CN=Public Key Services,
CN=Services,
CN=Configuration,<forest distinguished name>The template is an AD object containing settings such as the validity period, enrollment flags, application policies and cryptographic configuration. Its permissions determine who can read, enroll against or manage it.
Publishing is a separate operation. It adds an existing template to an issuing CA’s list of templates available for issuance. This distinction also explains why Add-CATemplate does not duplicate templates. It publishes an existing one. Microsoft explicitly documents that limitation in the Add-CATemplate documentation.
The script therefore handles creation first. Publishing is optional and only happens after the new template has been read back and verified.
What the script does
The starting point is an existing version 1 or version 2 template. I tested the built-in Web Server and User templates as sources.
The script discovers a writable domain controller, reads the source template and prepares the new configuration. It creates a unique template OID and its registration, creates the template object, applies the permissions and verifies the saved settings. The configurable settings include:
- CA and certificate-recipient compatibility.
- Legacy CSP or Key Storage Provider, provider selection, RSA key size and request hash.
- Validity and renewal periods.
- Subject and SAN information supplied in the request or built from AD.
- Certificate manager approval and private-key export.
- Additional application policies.
- Read, Enroll and optional Autoenroll permissions for selected groups.
This version supports RSA. ECDSA and other algorithms are outside its current scope. It also creates new templates only, an existing template with the same internal name causes the script to stop.
Requirements
Run the script in Windows PowerShell 5.1 as Administrator. This version deliberately uses the native Windows PowerShell management tools.
If the ActiveDirectory module is missing, the script installs the corresponding RSAT tools. On Windows Server that is RSAT-AD-PowerShell, supported Windows clients use the AD DS/LDS RSAT capability. The required component source must be available. The script does not restart the machine automatically. Local administrator rights are only part of the picture. Your account also needs the appropriate permissions in AD to create the template and OID objects and configure the DACL. Publishing requires the relevant CA permissions as well.
Without -Publish, you can run the script from a domain-connected management machine. With -Publish, run it on the issuing enterprise CA. The script reads the active local CA configuration, there is no remote-CA parameter in this version.
Example 1: a web server template
Let’s start with a web server certificate using RSA 3072 and the Microsoft Software Key Storage Provider. The enrollment group in these examples must already exist. Replace it with a group appropriate for your environment.
$Settings = @{
Name = 'MWWebServer01'
DisplayName = 'MW Web Server 01'
SourceTemplate = 'WebServer'
ProviderSelection = 'SelectedProviders'
Provider = 'Microsoft Software Key Storage Provider'
MinimumKeySize = 3072
RequestHash = 'SHA256'
ValidityYears = 1
EnrollmentGroup = 'GG-PKI-WebServer-Enroll'
Publish = $true
}
# Preview the operation
.\New-ADCertificateTemplate-v1.0.ps1 @Settings -WhatIf -Verbose
# Create and publish the template
.\New-ADCertificateTemplate-v1.0.ps1 @Settings -VerboseThe default subject-name mode is Supply in the request. You provide the subject and DNS SANs when requesting the certificate. Multiple DNS names can be included in the same request; they are not stored as a fixed list in this template.
The default compatibility choices are Windows Server 2012 R2 for the CA and Windows 10 / Windows Server 2016 for the recipient. These are minimum compatibility settings, not a detection of the operating systems in your environment. If you use CEP/CES, review Microsoft’s compatibility limitation before selecting the Windows 10/Server 2016 level.
The script returns a result object with the configuration and separate verification and publication status:
Verified : True
Published : True
PublicationStatus : SucceededLeaving out Publish creates the template in AD without making it available on a CA.
Example 2: computer certificates and autoenrollment
For computer certificates, the CA can build the subject and SAN from the requesting computer’s AD information.
$Settings = @{
Name = 'MWComputer01'
DisplayName = 'MW Computer 01'
ProviderSelection = 'SelectedProviders'
Provider = 'Microsoft Software Key Storage Provider'
SubjectNameMode = 'ActiveDirectory'
SubjectNameFormat = 'DNS name'
SubjectAlternativeName = 'DNS name'
ApplicationPolicy = 'Client Authentication'
EnrollmentGroup = 'GG-PKI-Computer-Enroll'
EnrollmentPermission = 'EnrollAndAutoenroll'
Publish = $true
}
.\New-ADCertificateTemplate-v1.0.ps1 @Settings -WhatIf
.\New-ADCertificateTemplate-v1.0.ps1 @SettingsThe group must contain the computer accounts, and the applicable computer autoenrollment policy must be enabled through GPO. Giving your administrator account enrollment rights does not give those rights to the computer. Application policies are additive. Because the default source is WebServer, this example retains Server Authentication and adds Client Authentication.
Example 3: multiple SAN types from AD
For a user certificate, we can use the User template as the source and include both UPN and email in the SAN extension.
.\New-ADCertificateTemplate-v1.0.ps1 `
-Name 'MWUserMultiSAN01' `
-DisplayName 'MW User Multi SAN 01' `
-SourceTemplate User `
-SubjectNameMode ActiveDirectory `
-SubjectNameFormat 'Common name' `
-SubjectAlternativeName @('UPN', 'E-mail name') `
-EnrollmentGroup 'GG-PKI-User-Enroll' `
-PublishRequest this certificate in the user’s context. The corresponding userPrincipalName and mail attributes must be populated in AD.
The existing purposes from User are retained. In my lab that included Secure Email, Client Authentication and Encrypting File System. Adding a group also does not remove any existing permissions from the source. Review those source permissions before treating the new group as an exclusive enrollment boundary.
A few settings worth explaining
The full parameter list is included in the script help and accompanying README. These are some useful additional choices:
| Parameter | Purpose |
|---|---|
RenewalWeeks | Set the renewal period, otherwise retain the source value |
RequireManagerApproval | Require CA certificate manager approval |
AllowPrivateKeyExport | Allow export of newly generated private keys |
ReuseSubjectOnRenewal | Reuse subject/SAN information during autoenrollment renewal in SupplyInRequest mode |
ApplicationPolicy | Add policy names or OIDs while removing duplicates |
Server | Override automatic domain controller discovery; this does not select a CA |
For example, add -RequireManagerApproval $true and -AllowPrivateKeyExport $true to enable approval and private-key export.
Validity is expressed in years of 365 days. The issued certificate can still have a shorter lifetime because of CA policy or the remaining validity of the CA certificate.
Note!, Request hash is exactly that: the hash used to sign the certificate request. A template configured for SHA512 can still produce a certificate signed by the CA using SHA256. To inspect the request signature, inspect the original CSR rather than the issued certificate.
Certutil documentation that the utility is not recommended for production code and does not provide application compatibility guarantees. Keep that limitation in mind if you extend this administrative script into a wider automation platform.
Validation and download
I tested ten scenarios covering legacy CSP and KSP, different compatibility settings, provider selection, permissions, application policies, approval, export settings, computer autoenrollment and user enrollment. Two additional tests covered multiple SAN types from AD and multiple DNS names supplied in a request.
Those tests checked the resulting settings and certificate enrollment. Actual subject reuse during renewal and independent inspection of the CSR signature hash remain separate tests. Selecting an older compatibility level in a modern lab also does not establish interoperability with an actual Windows XP or Server 2003 client. The script, README and scenario runner are available here:
https://github.com/mfgjwaterman/ADCertificateTemplate
To view the complete help:
Get-Help .\New-ADCertificateTemplate-v1.0.ps1 -FullFinal thoughts
What started as copying the Web Server template turned into a useful way to make template configuration repeatable. The individual settings are familiar from the UI, but putting them into parameters makes it easier to see what has been chosen and reproduce it elsewhere.
I hope this helps if you are building out a lab, preparing a new environment or simply want to spend a little less time clicking through the same template settings. If you try it and find something worth improving, let me know. There is always another scenario to test.
Until next time!
Leave a Reply