TameMyCerts is a policy module for Microsoft Active Directory Certificate Services (AD CS) enterprise certification authorities that enables security automation for a lot of use cases in the PKI field.
It is developed in germany by PKI expert Uwe Gradenegger (https://www.gradenegger.eu/), with contributions from all over the world.
The module supports, amongst other functions, inspecting certificate requests for certificate templates that allow the subject information to be specified by the enrollee against a defined policy. If any of the requested identities violates the defined rules, the certificate request automatically gets denied by the certification authority. Requested identities can also be mapped against Active Directory to apply restrictions based on group memberships, or even to pull certificate content from AD.
Therefore, the TameMyCerts policy module for Microsoft Active Directory Certificate Services helps you to tame your certs! It has already proven itself in countless productive deployments of enterprise-grade scale.
TameMyCerts is Open Source Software. Find it on GitHub (https://github.com/Sleepw4lker/TameMyCerts).
For enterprise deployments, commercial support and maintenance agreements are being offered as well.
Enterprises in a modern, digitalized, highly connected world strongly rely on digital certificates. Certificates are used for a variety of use cases like…
Organizations around the world rely on Microsoft Active Directory Certificate Services (AD CS) (https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/active-directory-certificate-services-overview) for issuing digital certificates within their Microsoft identity ecosystem. Microsoft AD CS is a suite of roles provided by the Microsoft Windows Server operating system. Its main role is the certification authority (CA), which is responsible for processing certificate requests and issuing digital certificates.
The core of a digital certificate is the identity it provides. A CAs main responsibility is to verify and attest the enrollees identity. Trusting a certification authority means trusting the content of the digital certificates it is issuing and the identities it attests.
AD CS uses the concept of certificate templates to define rules that shall be applied to incoming certificate requests and issued certificates.
AD CS knows of two kinds of certificate templates and requests:
The fact whether a certificate template qualifies as online or offline derives from the settings within the “Subject” tab of the certificate template settings.
AD CS was originally designed around the Microsoft Active Directory ecosystem and as such to heavily rely on online certificate templates for authentication of enrollees and ensuring their identities.
However, many modern use cases require switching the certification authority to use offline certificate templates, where the certification authority has no control over the issued certificates content. This opens up a large surface for various attacks against the certification authority. In a worst case, the entire Active Directory environment of a company could be compromised because of an abused certification authority or certificate template (refer to https://posts.specterops.io/certified-pre-owned-d95910965cd2 for further details).
AD CS uses on the concept of policy modules (https://learn.microsoft.com/en-us/windows/win32/seccrypto/certificate-services-architecture) to determine if a certificate shall be issued. A policy module is a piece of software that is loaded into the certification authority process on start-up of the CA service. Think of it as a plug-in.
A policy module for AD CS has two main purposes:
Microsoft designed AD CS in a way so that custom policy modules could be developed by individual contributors to enhance the provided functionality. TameMyCerts is such a policy module, which allows to extend the functionality that is provided by AD CS. Unique about TameMyCerts is that it is made available to the public via a free license.
Refer to the Typical use cases for the TameMyCerts policy module chapter in the Appendix section of the document to learn more on typical use cases where TameMyCerts can add value.
The caveat in developing a custom policy module is that there can only be one module active at a time. Usually this means that all the functionality of the Windows Default policy module would have to be re-implemented by the custom module, which is complex and prone to errors.
TameMyCerts solves the issue: It shims the Windows Default policy module, which means all the original functionality is preserved, but additional checks can be performed afterwards.
TameMyCerts passes incoming certificate requests to the Windows Default policy module and only gets active afterwards, if a configuration has been made. This means all certificate templates that don’t have a policy configuration file specified are completely left untouched and behave exactly as without having TameMyCerts installed.
This approach was adopted from a code sample that initially was published by Microsoft (a mirror can be found at https://github.com/Sleepw4lker/capolmod) and is in alignment with their recommendations for the development of custom policy modules (https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc783853(v=ws.10)#certificate-services-architecture).
You configure your certificate templates as usual. You then define your rules in eXtended Markup Language (XML) files, one per certificate template you want to “tame”. During installation, you point TameMyCerts to the path where it shall search for your configuration files. If there is no configuration file defined for a given certificate template, TameMyCerts does not apply any additional logic, thus preserving the original behavior of the Windows Default policy module.
TameMyCerts is intended to be installed on a server with the Certification Authority role installed.
The following modes for the certification authority role are supported by TameMyCerts:
CA mode | Support status |
---|---|
Enterprise Root | supported |
Enterprise Issuing | supported |
Standalone Root | not supported |
Standalone Issuing | not supported |
The module was successfully tested and is supported with the following operating systems:
Other Microsoft Windows Server operating systems may work but are not supported.
TameMyCerts requires the .NET Desktop Runtime 8.0 (https://dotnet.microsoft.com/en-us/download/dotnet/8.0).
Ensure that the prerequisites are being met by the destination machine prior to installing TameMyCerts.
If you signed up for a maintenance contract, you get a ZIP file containing the module binary as well as an installer script and some example configuration files to get you started.
To install the module, first create a directory on the certification authority where you intend to store the policy configuration files.
Then run install.ps1
as local Administrator. The script
will register the module, create the required registry values and
configure the policy module as the active one for the certification
authority.
The installation script restarts the certification authority service during installation and uninstallation.
You must specify the -PolicyDirectory
Parameter which
specifies the local path for the XML configuration files you define for
each certificate template.
Example:
.\install.ps1 -PolicyDirectory C:\PolicyFiles
Afterwards, TameMyCerts is automatically enabled as the active policy module, which can be reviewed in the properties dialog of the certification authority in the certification authority management console (certsrv.msc).
As the policy module daisy-chains the Windows default policy module, it also uses all of its registry settings. Therefore, the install script copies this data from the Windows Default module registry key to a new one for the TameMyCerts policy module. Each change you perform with certutil commands that would configure the Windows Default policy module is now written to the TameMyCerts policy module registry key. Should you decide to uninstall it later on, use the provided installer script as well to ensure the settings get copied back so that they stay consistent.
The process of upgrading from a previous version is the same as installing the module. Simply proceed as you would install TameMyCerts for the first time.
Depending on the version you previously used, it may be necessary to adjust your policy configuration files. Refer to the upgrade instructions in the Technical Reference section of the document.
To uninstall the module, run install.ps1
as
Administrator. You must specify the -Uninstall
parameter.
The installation script restarts the certification authority service during installation and uninstallation.
Example:
.\install.ps1 -Uninstall
The script will unregister the module, copy the registry settings back and configure the Windows Default policy module as the active one.
The TameMyCerts policy module uses eXtended Markup Language (XML) files to describe what shall be done with incoming certificate requests for a given certificate template. This approach has the benefit that changes can easily be tracked with version control systems like Git and annotated with inline comments.
Create a policy configuration file in XML format for each certificate template you want to apply a policy for in the folder you specified during Installing the TameMyCerts policy module.
Please ensure the file is encoded as UTF-8 if you plan to support special characters like german “Umlauts”.
Name the file exactly as the certificate template (“cn” LDAP attribute) that shall get examined.
For example, if your certificate template is named “TameMyCertsWebServer”, you create a policy configuration file named “TameMyCertsWebServer.xml”. You can get the object name of the certificate template from the certificate template management console or via Windows PowerShell.
Note that certificate template names allow several characters that are not valid for file names (e.g. “<>|*?\/). If you have such a template, simply omit these characters when naming the file.
Each policy configuration file starts with a basic definition of a CertificateRequestPolicy as shown below:
CertificateRequestPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<<!-- Directives go here -->
CertificateRequestPolicy> </
The distribution package of TameMyCerts contains various example files (https://github.com/Sleepw4lker/TameMyCerts/tree/main/examples) to get started with the most common use cases.
The policy configuration files get loaded when an incoming certificate request is processed. Therefore it is not necessary to restart the certification authority service after a policy configuration file has been created or changed. As long as the configuration file does not change, subsequent certificate requests for the same certificate template will be served from an internal cache.
If TameMyCerts is not able to parse the policy configuration file (e.g. because of a syntax error), the certificate request gets denied and an entry is written into the servers event log, pointing to the possible cause of the issue.
You can now configure the file as desired. Some of the settings described in subsequent chapters apply only to offline requests and will have no effect when configured for online certificate templates.
A basic policy configuration file that restricts all certificate
request for a given offline certificate template to having a
commonName
of “Hello World”, and nothing else. All
certificate requests that do not comply with these settings will get
denied.
CertificateRequestPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Subject>
<SubjectRule>
<Field>commonName</Field>
<Mandatory>true</Mandatory>
<Patterns>
<Pattern>
<Expression>^Hello World$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</Subject>
</CertificateRequestPolicy> </
TameMyCerts supports the following flags to modify global (affecting request processing regardless of template configuration) behavior.
Flag | Numerical value | Description |
---|---|---|
TMC_DENY_IF_NO_POLICY |
0x1 |
Denies certificate request in case there is no policy configuration defined. Note that this causes the certification authority to globally deny all certificate requests by default until a policy configuration has been defined the published certificate templates (“failure-close” configuration). |
TMC_WARN_ONLY_ON_INSECURE_FLAGS |
0x2 |
Causes the policy module to not deny a certificate request when it
contains the “san” request attribute and the
EDITF_ATTRIBUTESUBJECTALTNAME2 flag has been enabled on the
certification authority. Refer to section Denying certificate requests for insecure
combinations for more information. It is recommended to not
enable this flag. |
TMC_DONT_RESOLVE_NESTED_GROUP_MEMBERSHIPS |
0x4 |
Instructs Directory Services Mapping to
not resolve nested Group Memberships using the use the
msds-TokenGroupNames (https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1d810083-9741-4b0a-999b-30d9f2bc1f95)
Active Directory Attribute. |
Flags can be combined with each other.
To enable one or more flags, enter the following
commands into an elevated (“run as Administrator”) command prompt (the
example uses the TMC_DENY_IF_NO_POLICY
flag with numerical
value of 0x1
, adjust to your needs):
certutil -setreg Policy\TmcFlags +0x1
To disable a flag, enter the following commands into
an elevated (“run as Administrator”) command prompt (the example uses
the TMC_DENY_IF_NO_POLICY
flag with numerical value of
0x1
, adjust to your needs):
certutil -setreg Policy\TmcFlags -0x1
As registry settings are applied on service startup, the certification authority service must be restarted for the settings to apply after a change.
net stop certsvc
net start certsvc
Applies to online and offline certificate templates.
TameMyCerts supports an Audit-only mode, in which certificate requests get allowed regardless of the verification result. This helps by sharpending policies before applying them to existing deployments. If a certificate request would be denied in regular mode, TameMyCerts will log this to the event log of the certification authority to allow administrators further research.
Also refer to the How it works section to get an understanding of the verification flow.
You enable Audit only mode by configuring the AuditOnly
directive.
AuditOnly>true</AuditOnly> <
Applies to online and offline certificate templates.
The “Windows Default” policy is only capable to enforce a minimum key length, but not the key algorithm and not the maximum key length to be used. This may lead to issuance of certificates using weak keys, e.g. when submitting a request using a small RSA key to a certificate template that is configured to use an ECC key.
You can specify the following parameters for the private key:
The MinimumKeyLength
directive specifies the minimum key
length the certificate request must use. Defaults to “0” (any key size
is allowed). Though the Windows Default policy module also verifies
this, this may become handy in a migration scenario where you publish
the same template both on the old and new certification authority and
plan to increase key size when switching to the new one whilst keeping
the productive system unchanged.
The MaximumKeyLength
directive specifies the maximum key
length the certificate request can use. Defaults to “0” (any key size is
allowed).
The key algorithm is automatically determined based on the settings of the used certificate template and is enforced automatically.
Key size must exactly be 384 bits, assuming the certificate template uses an ECC key and specifies a minimum key size of 384 bits (thus minimum and maximum key size are equal).
MaximumKeyLength>384</MaximumKeyLength> <
Key size must exactly be 384 bits, assuming the certificate template uses an ECC key and specifies a lower key size.
MinimumKeyLength>384</MinimumKeyLength>
<MaximumKeyLength>384</MaximumKeyLength> <
Key size must be between 2048 and 4096 bits, assuming the certificate template uses an RSA key and specifies a lower key size.
MinimumKeyLength>2048</MinimumKeyLength>
<MaximumKeyLength>4096</MaximumKeyLength> <
Applies to online and offline certificate templates.
Certificate requests can contain information about which cryptographic provider (https://www.gradenegger.eu/en/basics-cryptographic-service-provider-csp-and-key-storage-provider-ksp/) was used to create the key pair. This information can be used to apply a policy which providers are permitted to get a certificate issued and which are not.
Please be aware that only certificate requests that have been made with the Microsoft API (e.g. Autoenrollment, MMC, certreq, PSCertificateEnrollment (https://www.powershellgallery.com/packages/PSCertificateEnrollment) and similar apps) will contain information about the provider that was used to create the certificate request.
Please be also aware that the provider information may potentially be manipulated by the enrollee during the request creation process. Therefore, this method is less secure than serious attestation methods for TPMs (https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/tpm-key-attestation) or Smartcards.
The AllowedCryptoProviders
directive contains a list of
one or more Cryptographic Service Provider (CSP) or Key Storage Provider
(KSP) names that are permitted for the creation of the certificate
requests private key. For example, you could configure a certificate
template to use the machines Trusted Platform Module (TPM) by specifying
the Microsoft Platform Crypto Provider and a fallback to the Microsoft
Software Key Storage Provider, whereas the policy for TameMyCerts would
only permit requests for the Microsoft Platform Crypto Provider to be
issued. This way, you could identify machines where the TPM is in a
nonfunctional state by evaluating denied certificate requests.
The DisallowedCryptoProviders
directive contains a list
of one or more Cryptographic Service Provider (CSP) or Key Storage
Provider (KSP) names that are disallowed for the creation of the
certificate requests private key.
Configured values are processed case-insensitive.
Key Storage Providers shipped with Windows include:
Cryptographic Service Provider shipped with Windows include:
Some providers are whitelisted and all others are forbidden:
AllowedCryptoProviders>
<string>Microsoft Platform Crypto Provider</string>
<string>Microsoft Software Key Storage Provider</string>
<AllowedCryptoProviders> </
Some providers are blacklisted and all others are allowed:
DisallowedCryptoProviders>
<string>Microsoft Platform Crypto Provider</string>
<DisallowedCryptoProviders> </
Applies to online and offline certificate templates.
Certificate requests can contain information about which process was used to create the key pair. This information can be used to apply a policy which processes are permitted to get a certificate issued and which are not (e.g. you want to allow only Autoenrollment but not manually requesting a certificate).
Please be aware that only certficate requests that have been made with the Microsoft API (e.g. Autoenrollment, MMC, certreq, PSCertificateEnrollment (https://www.powershellgallery.com/packages/PSCertificateEnrollment) and similar apps) will contain information about the process that was used to create the certificate request.
Please be also aware that the process information may be manipulated by the enrollee during the request creation process. This is therefore an enforcement on a best-effort basis.
Reading the process names from the certificate request requires parsing the inline certificate request from the certification authority database. There are rare cases where this might fail. Should this happen, the process name is treated as nonexistent, which will lead to the request being denied if a proces rule is configured for the certificate template.
A certificate request can be inspected for the required process
information by dumping it with the certutil
command.
certutil -dump <request-file-name>
The AllowedProcesses
directive contains a list of one or
more process names that are permitted to get a certificate issued. For
example, if you would like to restrict certificate enrollment for a
certificate template to Autoenrollment only, you would permit
“taskhostw.exe”.
The DisallowedProcesses
directive contains a list of one
or more process names that are disallowed to get a certificate issued.
For example, if you would like to deny certificate enrollment via
certreq.exe, you could enter it here.
Though both directives can be used at the same time, it is recommended to only use either AllowedProcesses or DisallowedProcesses in a policy.
Commonly used process names could be:
Process name | Description |
---|---|
taskhostw.exe | Windows Autoenrollment |
mmc.exe | Manual certificate enrollment with the Microsoft Management Console (MMC) |
certreq.exe | Manual or scripted certificate enrollment with certreq.exe |
powershell.exe | Manual or scripted certificate enrollment with a PowerShell module like PSCertificateEnrollment (https://www.powershellgallery.com/packages/PSCertificateEnrollment) |
Configured values are processed case-insensitive.
This configuration ensures that a certificate can
only be requested via Windows AutoEnrollment (which is
triggered by the Task Scheduler process,
taskhostw.exe
).
AllowedProcesses>
<string>taskhostw.exe</string>
<AllowedProcesses> </
This configuration blacklists some common processes, but allows all others:
DisallowedProcesses>
<string>mmc.exe</string>
<string>powershell.exe</string>
<string>certutil.exe</string>
<DisallowedProcesses> </
Applies only to offline certificate templates.
TameMyCerts allows to take control about which certificate content can be requested via an “offline” certificate template.
You can apply the following rules:
Rules for Subject RDNs get specified within a
SubjectRule
node under Subject
section.
Any Subject RDN that is not defined is considered forbidden and will result in any certificate request containing it getting denied.
A SubjectRule
can/must contain the following nodes:
Parameter | Mandatory | Description |
---|---|---|
Field |
yes | Specifies the type of the certificate field. See the below list for possible values. Please be aware that this parameter is interpreted case-sensitive. |
Mandatory |
no | Specifies if this field must (true) or
may (false) appear in the certificate request
presented. Defaults to false . |
MaxOccurrences |
no | Specifies how often this field may appear within a certificate
request. Should be 1 for most Subject RDN types. Defaults
to 1 . Note that more than one field of same type can only
be used when the ReadSubjectFromRequest directive is set
to true . |
MinLength |
no | Specifies the minimum amount of characters the field must contain,
to avoid empty RDNs being requested. Defaults to 1 . Note
that you also can define minimum lengths for parts or the entire field
content via regular expressions in the Patterns directive. |
MaxLength |
no | Specifies the maximum amount of characters the field may contain.
Defaults to 128 . Note that there is also an upper limit set
by the certification authority (https://learn.microsoft.com/en-us/windows/win32/seccrypto/name-properties).
Also note that you also can define maximum lengths for parts or the
entire field content via regular expressions in the Patterns
directive. |
Patterns |
yes | For any field type you can define one or more Pattern
directives describing expressions of which the requested field content
must match at least one of to get either permitted or denied. The node
is required, so if you would want to allow any content, simply configure
a Pattern directive with ^.*$ as expression. For
instructions on how to configure the Patterns directive,
consult the Pattern section within the Technical Reference chapter of this
document. |
To define a policy for one or more subject Relative Distinguished Name (RDN) types, adjust the “field” to one of the following (as defined in ITU-T X.520 (https://www.itu.int/itu-t/recommendations/rec.aspx?rec=X.520) and IETF RFC 4519 (https://datatracker.ietf.org/doc/html/rfc4519#section-2)).
Each RDN type can only be defined once in a policy definition file! Though you may specify that a certificate request contains more than one RDN of the same type, you would have to specify the criteria for all of them in the same rule. It is advised to allow each RDN type only once in a certificate request.
The following RDN types are enabled/allowed by default on AD CS and are therefore useable with TameMyCerts:
countryName
commonName
domainComponent
emailAddress
organizationName
organizationalUnitName
localityName
stateOrProvinceName
The following RDNs can additionally be defined in a policy configuration but must explicitly be enabled in the certification authority configuration by modifying its SubjectTemplate registry value (https://learn.microsoft.com/en-us/windows/win32/seccrypto/name-properties):
givenName
initials
surname
streetAddress
title
unstructuredName
unstructuredAddress
serialNumber
Please be aware that the SubjectTemplate registry value of the CA uses a different syntax for field type names than AD CS does.
Under certain circumstances, it is also possible to modify the Subject Distinguished Name (DN) using values from a mapped Active Directory object or from static values.
Incoming requests must contain exactly one
commonName
which must be a DNS-Name beneath the
tamemycerts.com
Domain. The whole content may not be longer
than 64 characters in total.
Subject>
<SubjectRule>
<Field>commonName</Field>
<Mandatory>true</Mandatory>
<MaxLength>64</MaxLength>
<Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</Subject> </
Incoming requests must contain exactly one
commonName
which must be a DNS-Name beneath the
tamemycerts.com
Domain. The whole content may not be longer
than 64 characters in total. It may not contain the blacklisted words
“porn” or “gambling”.
Subject>
<SubjectRule>
<Field>commonName</Field>
<Mandatory>true</Mandatory>
<MaxLength>64</MaxLength>
<Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</Expression>
<Pattern>
</Pattern>
<Expression>^.*(porn|gambling).*$</Expression>
<Action>Deny</Action>
<Pattern>
</Patterns>
</SubjectRule>
</Subject> </
Incoming requests must contain exactly one
commonName
which must be a DNS-Name beneath the
tamemycerts.com
Domain. It also may
contain exactly one countryName but if so, it must be “DE” or
“US”.
Subject>
<SubjectRule>
<Field>commonName</Field>
<Mandatory>true</Mandatory>
<MaxLength>64</MaxLength>
<Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</SubjectRule>
<Field>countryName</Field>
<Mandatory>false</Mandatory>
<Patterns>
<Pattern>
<Expression>^(DE|US)$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</Subject> </
You should use this only if there is a definitve requirement to do so. Avoid using it in any other case.
Processing certificate requests with RDNs that are not part of the
default set requires enabling the
CRLF_REBUILD_MODIFIED_SUBJECT_ONLY
flag (https://www.gradenegger.eu/en/use-of-undefined-relative-distinguished-names-rdn-in-issued-certificates/)
on the certification authority, which should be used with extreme
caution.
A common use case for this feature is supporting the requirements of the eIDAS regulation (https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32014R0910) in form of adding an organization identifier (OI) to a certificate request and thus to an issued certificate.
This mode may have trouble with malformed certificate requests.
By default, TameMyCerts will use the data from the record provided by the certification authority (“how the certificate would get issued”) to analyze the Subject Distinguished Name. This allows for best compatibility and security, but has its drawbacks. The certification authority design assumes that there is only a specific set of field types and that there is only one per type.
If you have the need to inspect Subject Relative Distinguished Names
that are not part of the default set, you can instruct TameMyCerts to
parse the Subject Distinguished Name from the original certificate
request (“how the certificate was originally requested”) by setting the
ReadSubjectFromRequest
directive.
ReadSubjectFromRequest>true<ReadSubjectFromRequest> <
Now, the following additional RDNs can be used in a subject rule:
postalCode
description
postOfficeBox
telephoneNumber
OID.1.2.3.4
.Applies only to offline certificate templates.
Rules for the Subject Alternative Name (SAN) get specified within a
SubjectRule
node under SubjectAlternativeName
section. The syntax and logic for the SubjectRule
is the
exact same as for Rules for the Subject
Distinguished Name (Subject DN).
To define a policy for one or more subject alternative name (SAN)
type, adjust the Field
to one of the following (as defined
in IETF RFC 5280 (https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6).
dNSName
iPAddress
rfc822Name
uniformResourceIdentifier
userPrincipalName
Other SAN types are currently not supported. However, the ones that are supported should be sufficient for the majority of use cases.
Under certain circumstances, it is also possible to supplement DNS Names and IP Addresses from the Subject Distinguished Name into the Subject Alternative Name extension.
Incoming requests may contain exactly one
userPrincipalName
, but if present, it must be beneath the
tamemycerts.com
Domain.
SubjectAlternativeName>
<SubjectRule>
<Field>userPrincipalName</Field>
<<!-- other directives have been left out for simplicity -->
Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9\.]*\@tamemycerts\.com$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</SubjectAlternativeName> </
Applies only to offline certificate templates.
IETF RFC 2818 (https://www.rfc-editor.org/rfc/rfc2818) states that
identities in certificates intended to be used with HTTP over TLS (aka
HTTPS) shall get presented in form of one or more entries of type
dNSName
in the Subject Alternative Name. It is deprecated
and discouraged to use the commonName
field in the Subject
Distinguished Name for this purpose. Google started to enforce the IETF
RFC in 2019, so any browser that is based on Chromium (e.g. Chrome,
Edge, Opera) will distrust HTTPS certificates that dont contain a
Subject Alternative Name. Other recent browsers behave in a similar
manner.
Sadly, some applications are still unable to generate appropriate certificate requests. The feature for supplementing DNS names allows to transfer all DNS names or IP addresses that are found in the commonName of a certificate request into a Subject Alternative Name certificate extension (either adding to an existing or creating a newly-constructed one). Therefore, non-compliant certificate requests are automatically made compliant.
Enabling this feature will also mean you will have to make the commonName mandatory in your policy under rules for the Subject Distinguished Name of a CSR.
You enable the feature by configuring SupplementDnsNames
directive.
SupplementDnsNames>true</SupplementDnsNames> <
By default, TameMyCerts will supplement both qualified
(e.g. host.domain.tld
) and unqualified DNS names
(e.g. host
). You can suppress supplementation of
unqialified names by setting the SupplementUnqualifiedNames
to false
.
SupplementDnsNames>true</SupplementDnsNames>
<SupplementUnqualifiedNames>false</SupplementUnqualifiedNames> <
This configuration accepts certificate requests with a
commonName
and dNSName
within the
tamemycerts.com
DNS domain. Whilst the
commonName
field is mandatory, the dNSName
field is optional. Should the request not contain a SAN in form of a
dNSName, the value within the commonName
will be used to
create a SAN extension containing it in form of a
dNSName
.
Subject>
<SubjectRule>
<Field>commonName</Field>
<Mandatory>true</Mandatory>
<Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</Subject>
</SubjectAlternativeName>
<SubjectRule>
<Field>dNSName</Field>
<Mandatory>false</Mandatory>
<Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</SubjectAlternativeName>
</SupplementDnsNames>true</SupplementDnsNames> <
Applies to online and offline certificate templates.
TameMyCerts allows to configure certificates issued for a specific certificate template to expire at an exactly configured point in time. This can be useful in scenarios where you want to ensure that e.g. certificates with weak keys get phased out until a specified point in time.
The behavior is as follows:
You configure the expiration date with the NotAfter
directive in your policy configuration file.
The time gets specified as an ISO 8601 compliant string in the following syntax:
'yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffzzz'
See the original Microsoft documentation (https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings) for further explanation.
All certificates will expire on Dec 31, 2022 23:59:59 Europe/Berlin (UTC+1) time. After that date has passed, all certificate requests for this template get denied.
NotAfter>2022-12-31T23:59:59.0000000+01:00</NotAfter> <
Applies to online and offline certificate templates.
Directory Services mapping allows you to map an identity in a certificate request back to an Active Directory object. This way, a variety of policies can be applied, containing:
When using DS mapping with an offline certificate template, Directory Services mapping setting get processed after Rules for the Subject Distinguished Name (Subject Distinguished Name) and Rules for the Subject Alternative Name (SAN), so ensure you have these configured as well.
Note that for Directory Services mapping to work properly, the certification authority server must be member of the Built-in
Pre-Windows 2000 Compatible Access
security group. By default, certification authorities are implicitly members of this group via their membership in theCert Publishers
security group.
Rules for Directory Mapping get specified within the
DirectoryServicesMapping
node.
When using an online certificate template, the object category as well as certificate and directory services attributes are determined automatically.
When using an offline certificate template, the certificate attribute that was chosen for DS mapping is mandatory to occur in the certificate request and must occur only once. Ensure this via an appropriate Subject rules or Subject Alternative Name rules.
TameMyCerts is only able to map exactly one of the requested identities to an Active Directory object. Usually a certificate request contains multiple fields that can be used as identity (e.g. commonName and userPrincipalName). Which field of the issued certificate is used by to determine the certificate holders identity depends on the verifying application. You should therefore overwrite other identites by either modifying the Subject DN or the Subject Alternative Name with values from Active Directory (e.g. map userPrincipalName and overwrite commonName from the mapped Active Directory object to ensure strict rule enforcement.
Parameter | Mandatory | Description |
---|---|---|
Action |
no | Specifies what should happen with the certificate request in case a
matching object was found in the directory. Can be Allow or
Deny . Defaults to Allow . |
CertificateAttribute |
no | The field which is taken from the certificate request as the
identity to map to a corresponding Active Directory object. May contain
any identity that is listed above for either the Subject Distinguished
Name, or for the Subject Alternative Name. Defaults to
userPrincipalName . Automatically determined for
online certificate templates. |
DirectoryServicesAttribute |
no | The attribute of the Active Directory object that must match the
certificate attribute. May be cn , name ,
sAMAccountName , userPrincipalName or
dNSHostName . Defaults to userPrincipalName .
Automatically determined for online certificate
templates. |
ObjectCategory |
no | The category of the Active Directory object to be searched for. May
be computer or user . Defaults to
user for offline certificate templates.
Automatically determined for online certificate templates. |
SearchRoot |
no | The distinguished name of the LDAP path the search for the Active Directory object shall start from. Defaults to using the global catalog for the entire forest. |
AllowedSecurityGroups |
no | A list of distinguished names of security groups the account must be member of (request gets denied if it is not member of at least one of them). |
DisallowedSecurityGroups |
no | A list of distinguished names of security groups the account must not be member of (request gets denied if it is member of at least one of them). |
AllowedOrganizationalUnits |
no | A list of distinguished names of organizational units the account must be member of (request gets denied if it is not member of at least one of them). |
DisallowedOrganizationalUnits |
no | A list of distinguished names of organizational units the account must not be member of (request gets denied if it is member of at least one of them). |
PermitDisabledAccounts |
no | Permits certificates to get issued even if the Active Directory object is disabled. |
SupplementServicePrincipalNames |
no | Set to true to supplement DNS names found in the
ServicePrincipalName attribute of the mapped AD object. See Supplementing Service Principal Names for
more details. |
DirectoryObjectRules |
no | You can define one or more DirectoryObjectRule
directives. See Configuring directory object
rules for further reference. |
AddSidUniformResourceIdentifier |
no | Adds the security identifier (SID) of the mapped AD object into the
Subject Alternative Name (SAN) certificate extension of the issued
certificate. The entry will be in form of a
uniformResourceIdentifier
(tag:microsoft.com,2022-09-14:sid:<value> ). This
“strong” mapping method was introduced by Microsoft in April 2023 (https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/preview-of-san-uri-for-certificate-strong-mapping-for-kb5014754/bc-p/3794144#M965). |
The
AllowedOrganizationalUnits
andDisallowedOrganizationalUnits
directives match also for nested organizational units. E.g. if you whitelistDC=intra,DC=tamemycerts,DC=com
and the object resides inOU=Users,DC=intra,DC=tamemycerts,DC=com
, this will match as well. If you configure TameMyCerts to add the SID uniform resource identifier, you should ensure that the resulting certificate will contain a Subject Alternative Name of typedNSName
(for mapped computer objects) or userPrincipalName (for mapped user objects) as this will be used to map the certificate to the AD object during authentication. You can either achieve this by having the field being put into the certificate request (and governing requested certificate content), or add the Subject Alternative Name from Active Directory via Directory Services mapping.
Please be aware of the following limitations:
sAMAccountName
Active Directory attribute is only
unique per Domain, but not on Forest level. TameMyCerts denies a
certificate request if more than one account with the same identifier is
found. Avoid this by either using unique directory attributes, or by
specifying the SearchRoot
parameter accordingly.userPrincipalName
attribute may not be populated by
default for user accounts.=
,
,
, \
) with a backward slash (\
),
if present, for SearchRoot
,
AllowedSecurityGroups
and
DisallowedSecurityGroups
.SearchRoot
is not explicitly specified, or nested Group
Memberships are going to be resolved. Consult the official Microsoft
documentation (https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/config-firewall-for-ad-domains-and-trusts)
for further information.By default, TameMyCerts resolves nested Group Memberships for mapped objects.
This allows to use the primary group of a mapped
Active Directory object (e.g. Domain Users
,
Domain Guests
) for use with the
AllowedSecurityGroups
and
DisallowedSecurityGroups
directives, and group memberships
from any domain can be resolved.
However, as TameMyCerts will use the
msds-TokenGroupNames
(https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/1d810083-9741-4b0a-999b-30d9f2bc1f95)
Active Directory Attribute, which is only available on Windows Server
2016 and newer Domain Controllers, if TameMyCerts cannot retrieve the
msds-TokenGroupNames
attribute for a mapped object,
certificate requests will get denied due to security reasons.
It is possible to disable resolving nested Group Memberships by
enabling the TMC_DONT_RESOLVE_NESTED_GROUP_MEMBERSHIPS
global flag. TameMyCerts will then use the
MemberOf
(https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-ada2/cc24555b-61c7-49a2-9748-167b8ce5a512)
attribute (against the mapped accounts domain) to determine Group
Memberships of mapped objects.
Make sure you understand the following limitations when enabling this setting:
Domain Users
, Domain Guests
) for use
with the AllowedSecurityGroups
and
DisallowedSecurityGroups
directives.Enabling the mapping with default values for user
objects in an offline template:
DirectoryServicesMapping /> <
Enabling the mapping with default values for user
and computer
objects in an online
template:
DirectoryServicesMapping /> <
Enabling the mapping with default values for computer
objects in an offline template:
DirectoryServicesMapping>
<CertificateAttribute>dNSName</CertificateAttribute>
<DirectoryServicesAttribute>dNSHostName</DirectoryServicesAttribute>
<ObjectCategory>computer</ObjectCategory>
<DirectoryServicesMapping> </
Specifying an LDAP path as search root:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
SearchRoot>OU=TameMyCerts Users,DC=tamemycerts,DC=local</SearchRoot>
<DirectoryServicesMapping> </
Specifying an LDAP path as search root with escaping of LDAP-reserved characters:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
SearchRoot>OU=Users\,Computers\,and others,DC=tamemycerts,DC=local</SearchRoot>
<DirectoryServicesMapping> </
Permitting the issuance of certificates for disabled accounts:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
PermitDisabledAccounts>true</PermitDisabledAccounts>
<DirectoryServicesMapping> </
Filtering on security group memberships of a mapped object:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
AllowedSecurityGroups>
<string>CN=An allowed Group,DC=tamemycerts,DC=local</string>
<AllowedSecurityGroups>
</DisallowedSecurityGroups>
<string>CN=A forbidden Group,DC=tamemycerts,DC=local</string>
<DisallowedSecurityGroups>
</DirectoryServicesMapping> </
Filtering on Organizational Unit placement of a mapped object:
DirectoryServicesMapping>
<<!-- other directives have been removed for this example -->
AllowedOrganizationalUnits>OU=some-allowed-OU,DC=tamemycerts,DC=local</AllowedOrganizationalUnits>
<DisallowedOrganizationalUnits>OU=some-disallowed-OU,DC=tamemycerts,DC=local</DisallowedOrganizationalUnits>
<DirectoryServicesMapping> </
Adding the SID uniform resource identifier to the certificates SAN:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
AddSidUniformResourceIdentifier>true</AddSidUniformResourceIdentifier>
<DirectoryServicesMapping> </
This policy will deny a certificate request, should a matching object be found in the directory.
DirectoryServicesMapping>
<Action>Deny</Action>
<<!-- other directives have been left out for simplicity -->
DirectoryServicesMapping> </
For an example on how to add the SID certificate extension to an issued certificate, see section “Working with the SID certificate extension”.
Applies to online and offline certificate templates. Requires Directory Services Mapping to be enabled.
Directory services mapping can be configured to apply conditions that must match for attributes of a mapped directory object.
The configuration goes as follows:
Parameter | Mandatory | Description |
---|---|---|
DirectoryServicesAttribute |
yes | The attribute of the mapped object that shall be evaluated. |
Mandatory |
no | Specified if the attribute may be omitted if it is invalid or empty. If set to “true”, requests will get denied in such a case. |
Patterns |
yes | You can define one or more “Pattern” directives describing
expressions of which the sAMAccountName attribute of the
mapped AD object must match at least one of to get either permitted or
denied. |
For a list of supported Active Directory attributes, consult the DirectoryServicesAttribute section within the Technical Reference chapter of this document.
For instructions on how to configure the Patterns
directive, consult the Pattern section within the
Technical Reference chapter of this
document.
DirectoryServicesMapping>
<<!-- other directives have been removed for this example -->
DirectoryObjectRules>
<DirectoryObjectRule>
<DirectoryServicesAttribute>description</DirectoryServicesAttribute>
<Mandatory>true</Mandatory>
<Patterns>
<Pattern>
<Expression>^Admin$</Expression>
<TreatAs>RegEx</TreatAs>
<Action>Deny</Action>
<Pattern>
</Patterns>
</DirectoryObjectRule>
</DirectoryObjectRules>
</DirectoryServicesMapping> </
Applies only to offline certificate templates. Certificates from online certificate templates automatically get a SID certificate extension from the Windows Default policy module.
The SID certificate extension gets processed after Rules for the Subject Distinguished Name (Subject DN) and Rules for the Subject Alternative Name (SAN), so ensure you have these configured as well. If you plan to add the SID extension from an Active Directory object to an issued certificate, you must also configure Directory Services mapping.
Microsoft introduced another mapping method in form of a uniformResourceIndicator in April 2023 (https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/preview-of-san-uri-for-certificate-strong-mapping-for-kb5014754/bc-p/3794144#M965), which is also supported by TameMyCerts and can be configured within Directory Services mapping.
The security identifier certificate extension was introduced by Microsoft with the May 2022 cumulative update for Windows Server (KB5014754) (https://support.microsoft.com/en-us/topic/kb5014754-certificate-based-authentication-changes-on-windows-domain-controllers-ad2c23b0-15d8-4340-a468-4d4f3b188f16). The patch causes Active Directory to require this certificate extension to process certificate-bases logons. There is a compatibility mode, which Microsoft plans to automatically disable on February 11, 2025.
As Microsoft only ensured that the extension will be present in certificates originating from online certificate templates, this probably will cause trouble when certificates originating from offline certificate templates (e.g. mobile devices managed by Intune, AirWatch/Workspace One, MobileIron and the like) are used for certificate-bases logons against Active Directory. A popular example is Wifi or VPN logons that use the Microsoft Network Policy Server.
TameMyCerts is able to process the new certificate extension in a variety of ways:
If TameMyCerts shall process the SID certificate extension, you
configure it with the SecurityIdentifierExtension
directive
within a policy configuration file.
You can configure four modes:
Action | Description |
---|---|
Deny |
Default Action. All certificate requests that contain a security identifier certificate extension will get denied if this is set. |
Allow |
If a certificate request contains a security identifier extension, it will get passed as-is into the issued certificate. |
Add |
Adds the value of the objectSid (https://learn.microsoft.com/en-us/windows/win32/adschema/a-objectsid) attribute of the Active Directory object belonging to the certificate request to the issued certificate. Can therefore only be used in combination with Directory Services mapping. |
Remove |
If a certificate request contains a security identifier extension, it will not get passed into the issued certificate. |
If you configure TameMyCerts to add the SID certificate extension, you should ensure that the resulting certificate will contain a Subject Alternative Name of type dNSName (for mapped computer objects) or userPrincipalName (for mapped user objects) as this will be used to map the certificate to the AD object during authentication. You can either achieve this by having the field being put into the certificate request (and governing requested certificate content), or add the Subject Alternative Name from Active Directory via Directory Services mapping.
All certificate requests that contain a security identifier certificate extension will get denied.
SecurityIdentifierExtension>Deny</SecurityIdentifierExtension> <
All certificate requests that contain a security identifier certificate extension will get allowed and the resulting certificate will contain the requested SID extension.
SecurityIdentifierExtension>Allow</SecurityIdentifierExtension> <
All certificate requests that contain a security identifier certificate extension will get allowed and the resulting certificate will not contain the requested SID extension
SecurityIdentifierExtension>Remove</SecurityIdentifierExtension> <
All certificate requests get the SID extension built from a mapped Active directory object (requires Directory Services mapping to be configured).
SecurityIdentifierExtension>Add</SecurityIdentifierExtension> <
TameMyCerts allows to add custom certificate extensions with static values.
Custom certificate extensions are not marked as mandatory.
Field | Mandatory | Description |
---|---|---|
Oid | yes | The Object Identifier of the extension. |
Value | yes | The BASE64-encoded value of the extension. |
Examples for this might be:
Extension | Object Identifier | Value |
---|---|---|
OCSP must-staple | 1.3.6.1.5.5.7.1.24 | MAMCAQU= |
OCSP NoCheck | 1.3.6.1.5.5.7.48.1.5 | no value |
Microsoft Hyper-V / SCVMM Virtual Machine Connection | 1.3.6.1.4.1.311.62.1.1.1 | AgEE |
Adding the OCSP must-staple certificate extension to an issued certificate.
CustomCertificateExtensions>
<CustomCertificateExtension>
<Oid>1.3.6.1.5.5.7.1.24</Oid>
<Value>MAMCAQU=</Value>
<CustomCertificateExtension>
</CustomCertificateExtensions> </
Adding the OCSP NoCheck certificate extension to an issued certificate.
CustomCertificateExtensions>
<CustomCertificateExtension>
<Oid>1.3.6.1.5.5.7.48.1.5</Oid>
<CustomCertificateExtension>
</CustomCertificateExtensions> </
Adding the Hyper-V / SCVMM Virtual Machine Connection certificate extension to an issued certificate.
CustomCertificateExtensions>
<CustomCertificateExtension>
<Oid>1.3.6.1.4.1.311.62.1.1.1</Oid>
<Value>AgEE</Value>
<CustomCertificateExtension>
</CustomCertificateExtensions> </
Applies to online and offline certificate templates.
TamyMyCerts allows modifying the Subject Distinguished Name (Subject DN) of a certificate before it gets issued. It is capable of retrieving properties from a mapped Active Directory object and put these values into the Subject Distinguished Name of a certificate. The resulting value can be either an attribute of a mapped Active Directory object, a field of the originating certificate request, a static value, or a combination of all.
This is useful in the following scenarios:
cn
Attribute for the commonName
field
(which would be the only combination with the original Microsoft policy
module).You define a OutboundSubject
directive containing one or
more OutboundSubjectRule
rules.
The OutboundSubjectRule directive can be configured as follows:
Parameter | Mandatory | Description |
---|---|---|
Field |
yes | The Relative Distinguished Name that shall be populated. |
Value |
yes | The value that shall be put into the configured certificate field. Can contain variables. |
Mandatory |
no | Specified if the configured value may be omitted if one of the
variables is invalid or empty. If set to “true”, requests will get
denied in such a case. Defaults to false . |
Force |
no | Specifies how to act when the originating certificate request
already contains a field of the specified type. If set to true and a
field of same type is present, it gets overwritten with the
configured value. If set to false, no action is made. Defaults
to false . |
You may specify the following Relative Distinguished Names (RDN) for the “Field” directive:
RDN | Maximum length | Typical AD attributes | Remarks |
---|---|---|---|
emailAddress |
128 | ||
commonName |
64 | name, sAMAccountName, displayName, userPrincipalName | |
organizationName |
64 | company | |
organizationalUnitName |
64 | department | |
localityName |
128 | l | |
stateOrProvinceName |
128 | st | |
countryName |
2 | c | |
title |
64 | title | not enabled by default |
givenName |
16 | givenName | not enabled by default |
initials |
5 | initials | not enabled by default |
surname |
40 | sn | not enabled by default |
streetAddress |
30 | streetAddress | not enabled by default |
unstructuredName |
1024 | n/a | |
unstructuredAddress |
1024 | n/a | |
serialNumber |
1024 | n/a |
The field names are processed case-sensitive.
The Value
may contain a static string, or can be
combined with attributes of mapped Active Directory objects, or content
from the certificate request.
It is also possible to remove a requested relative distinguished name from an issued certificate by setting the
Value
to an empty string.
You configure variables with the following syntax:
{Modifier:PropertyNameGoesHere}
The following modifiers are currently supported:
Modifier | Description |
---|---|
ad |
Attributes of mapped Active Directory objects. For a list of supported Active Directory attributes, consult the DirectoryServicesAttribute section within the Technical Reference chapter of this document. |
sdn |
Fields from the Subject Distinguished Name of the certificate request. |
san |
Fields from the Subject Alternative Name of the certificate request. |
yk |
Fields from YubiKey PIV Attestation of the certificate request. |
Note that if you plan to insert attributes from mapped Active Directory objects, you need to configure DirectoryServicesMapping.
Note that if you plan to inser attributes from a YubiKey, you need to configure YubiKey PIV attestation.
Field
will lead to certificate
requests getting denied.Value
that violates length constraints
for the selected Field
will lead to certificate requests
getting denied.Value
to an empty string. A more advanced variant of
this is to transfer a value from one requested RDN to another one and
then remove the original one.Issued certificates will have a commonName
field which
will contain the content of the userPrincipalName
Active
Directoy attribute of the mapped object. Furthermore, the
emailAddress
field will be populated with the content of
the mail
AD attribute. Should the
userPrincipalName
AD attribute not be populated in AD, the
request will get denied. Should the mail
AD attribute not
be populated in AD, the certificate will get issued but not include an
emailAddress
field.
DirectoryServicesMapping />
<OutboundSubject>
<OutboundSubjectRule>
<Field>commonName</Field>
<Value>{ad:userPrincipalName}</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubjectRule>
<Field>emailAddress</Field>
<Value>{ad:mail}</Value>
<OutboundSubjectRule>
</OutboundSubject> </
The commonName
will be built out of the two Active
Directory attributes sn
(surname) and
givenName
. Assuming the given name is “John” and the
surname is “Doe”, the commonName
in the issued certificate
will be “Doe, John”.
DirectoryServicesMapping />
<OutboundSubject>
<OutboundSubjectRule>
<Field>commonName</Field>
<Value>{ad:sn}, {ad:givenName}</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
The commonName
will be built out of the
name
Active Directory attribute and a static string.
Assuming the name
attribute contains “John Doe”, the
commonName
in the issued certificate will be “John Doe is
an awesome fellow!”.
DirectoryServicesMapping />
<OutboundSubject>
<OutboundSubjectRule>
<Field>commonName</Field>
<Value>{ad:name} is an awesome fellow!</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
The commonName
will be built out of the
displayName
Active Directory attribute. The
organizationName
will be set to “TameMyCerts”, regardless
if the originating certificate request did contain this field or
not.
OutboundSubject>
<OutboundSubjectRule>
<Field>commonName</Field>
<Value>{ad:displayName}</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubjectRule>
<Field>organizationName</Field>
<Value>TameMyCerts</Value>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
Transfering the first dNSName
of the
Subject Alternative Name into the commonName
field of the
issued certificate.
<!-- does not require DirectoryServicesMapping -->
OutboundSubject>
<OutboundSubjectRule>
<Field>commonName</Field>
<Value>{san:dNSName}</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
The content of the stateOrProvinceName
field will be
removed from the issueed certificate, if present in the certificate
request.
DirectoryServicesMapping />
<OutboundSubject>
<OutboundSubjectRule>
<Field>stateOrProvinceName</Field>
<Value></Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
The content of the stateOrProvinceName
field will be
transferred from the certificate request into the
serialNumber
field of the issued certificate, and the
stateOrProvinceName
field will be removed from the issued
certificate.
DirectoryServicesMapping />
<OutboundSubject>
<OutboundSubjectRule>
<Field>stateOrProvinceName</Field>
<Value></Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubjectRule>
<Field>serialNumber</Field>
<Value>{sdn:stateOrProvinceName}</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
Applies to online and offline certificate templates.
TamyMyCerts allows modifying the Subject Alternative Name (SAN) of a certificate before it gets issued. It is capable of retrieving properties from a mapped Active Directory object and put these values into the SAN of a certificate. The resulting value can be either an attribute of a mapped AD object, a field of the originating certificate request, a static value, or a combination of all.
You define a OutboundSubjectAlternativeName
directive
containing OutboundSubjectRule
rules.
The OutboundSubjectRule
directive can be configured as
follows:
Parameter | Mandatory | Description |
---|---|---|
Field |
yes | The Relative Distinguished Name that shall be populated. |
Value |
yes | The value that shall be put into the configured certificate field. Can contain variables. |
Mandatory |
no | Specified if the configured value may be omitted if one of the
variables is invalid or empty. If set to “true”, requests will get
denied in such a case. Defaults to false . |
Force |
no | Specifies how to act when the originating certificate request
already contains a field of the specified type. If set to true and a
field of same type is present, an additional entry with the
configured value gets added to the SAN. If set to
false , no action is performed. Defaults to
false . |
You may specify the following Subject Alternative Name types for the “Field” directive:
dnsName
rfc822Name
uniformResourceIdentifier
userPrincipalName
ipAddress
The field names are processed case-sensitive.
The Value
may contain a static string, or can be
combined with attributes of mapped Active Directory objects, or content
from the certificate request.
You configure variables with the following syntax:
{Modifier:PropertyNameGoesHere}
The following modifiers are currently supported:
Modifier | Description |
---|---|
ad |
Attributes of mapped Active Directory objects. For a list of supported Active Directory attributes, consult the DirectoryServicesAttribute section within the Technical Reference chapter of this document. |
sdn |
Fields from the Subject Distinguished Name of the certificate request. |
san |
Fields from the Subject Alternative Name of the certificate request. |
Note that if you plan to insert attributes from mapped Active Directory objects, you need to configure DirectoryServicesMapping.
The SAN gets supplemented with a dNSName
containing the
name
attribute of a computer object (so that the
unqualified DNS name is part of the SAN) .
DirectoryServicesMapping />
<OutboundSubjectAlternativeName>
<OutboundSubjectRule>
<Field>dNSName</Field>
<Value>{ad:name}</Value>
<Mandatory>true</Mandatory>
<OutboundSubjectRule>
</OutboundSubjectAlternativeName> </
The commonName
from the Subject DN is transferred to the
Subject Alternative Name (SAN) in form of a dNSName
.
<!-- does not require DirectoryServicesMapping -->
OutboundSubjectAlternativeName>
<OutboundSubjectRule>
<Field>dNSName</Field>
<Value>{sdn:commonName}</Value>
<Mandatory>true</Mandatory>
<OutboundSubjectRule>
</OutboundSubjectAlternativeName> </
Applies to online and offline certificate templates. Requires Directory Services Mapping to be enabled.
TameMyCerts can add DNS names found in the Service Principal Names (https://learn.microsoft.com/en-us/windows/win32/ad/service-principal-names) (SPNs) of mapped AD objects to the Subject Alternative Name (SAN) extension of issued certificates.
This allows to automatically add aliases and custom names required for Kerberos authentication to issued certificates.
This feature might be dangerous in cases there are no strict controls about how SPNs are registered for your AD accounts. Please use the feature carefully!
As the Service Principal Names (SPNs) usually also contain the non-qualified hostname of a machine, this identity gets added to the SAN as well.
You enable the feature by configuring
SupplementServicePrincipalNames
directive.
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
SupplementServicePrincipalNames>true</SupplementServicePrincipalNames>
<DirectoryServicesMapping> </
By default, TameMyCerts will supplement both qualified
(e.g. host.domain.tld
) and unqualified DNS names
(e.g. host
). You can suppress supplementation of
unqialified names by setting the SupplementUnqualifiedNames
to false
.
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
SupplementServicePrincipalNames>true</SupplementServicePrincipalNames>
<DirectoryServicesMapping>
</SupplementUnqualifiedNames>false</SupplementUnqualifiedNames> <
Applies to online and offline certificate templates.
TameMyCerts allows to create custom certificate extensions for Certificate Revocation List Distribution Points (CDP), Authority Information Access (AIA) and Online Certificate Status Protocol (OCSP) on a per-template basis.
The directives are:
Each of those can contain one or more uniform resource identifiers (URIs). TameMyCerts supports the same token variables as the original Microsoft product (https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc737264(v=ws.10)), namely:
Microsoft Token name | Description | Variable |
---|---|---|
ServerDNSName | The DNS name of the CA server | %1 |
ServerShortName | The NetBIOS name of the CA server | %2 |
CaName | The name of the CA | %3 |
Cert_Suffix | The renewal extension of the CA | %4 |
ConfigurationContainer | The location of the configuration container in Active Directory | %6 |
CATruncatedName | The “sanitized” name of the CA, 32 characters with a hash on the end | %7 |
CRLNameSuffix | The renewal extension for the CRL | %8 |
CDPObjectClass | %10 | |
CAObjectClass | %11 |
Online Certificate Status Protocol (OCSP) URIs should only be configured in combination with Authority Information Access (AIA) URIs as they get written into the same certificate extension.
Issuing CRL Distribution Point (CDP) URIs on a per-template basis:
CrlDistributionPoints>
<string>http://%1/CertData/%3%8%9.crl</string>
<string>ldap:///CN=%7%8,CN=%3,CN=cdp,CN=Public Key Services,CN=Services,%6%10</string>
<CrlDistributionPoints> </
Issuing Authority Information Access (AIA) URIs on a per-template basis:
AuthorityInformationAccess>
<string>http://%1/CertData/%3%4.crt</string>
<string>ldap:///CN=%7,CN=AIA,CN=Public Key Services,CN=Services,%6%11</string>
<AuthorityInformationAccess> </
Issuing Online Certificate Status Protocol (OCSP) URIs on a per-template basis:
OnlineCertificateStatusProtocol>
<string>http://ocsp.tamemycerts.com/ocsp</string>
<OnlineCertificateStatusProtocol> </
Applies to online and offline certificate templates. Does not support Audit only mode. This feature is independent from certificate templates. It can only be enabled used globally on a certification authority level.
The Windows Default policy module allows to specify the exact
expiration date (https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/change-certificates-expiration-date)
(NotAfter) for a certificate by specifying an
ExpirationDate
attribute whilst submitting the certificate
request. TameMyCerts adds support for a StartDate
attribute
which does the exact same for the begin of the certificates validity
period (the “NotBefore” certificate property).
To enable the feature, you must enable the
EDITF_ATTRIBUTEENDDATE
flag for the policy module of the
certification authority and restart the certification authority service
afterwards.
certutil -setreg Policy\Editflags +EDITF_ATTRIBUTEENDDATE
net stop certsvc
net start certsvc
Now you can specify both StartDate
and
ExpirationDate
request attribute in IETF RFC 2616 (https://datatracker.ietf.org/doc/html/rfc2616) compliant
form whilst submitting the certificate request.
A syntax example for a compliant date form could be:
Tue, 1 Mar 2022 08:00:00 GMT
When an invalid date is being requested, the certificate request will
get denied with error code
ERROR_INVALID_TIME
.
TameMyCerts currently only supports specifying
StartDate
whilst submitting the certificate request but not as custom attributes within the certificate request itself. The alternative method of specifyingValidityPeriod
andValidityPeriodUnits
for the expiration date can currently not be used in combination with theStartDate
attribute as it gets applied afterwards and thus won’t deliver the expected result.
Requesting a certificate that shall be valid from Mar 1, 2022 08:00 until Mar 1, 2022 16:00:
certreq.exe -config "caserver.tamemycerts.local\TameMyCerts CA" -attrib "CertificateTemplate:TameMyCertsWebServer\nStartDate:Tue, 1 Mar 2022 08:00:00 GMT\nExpirationDate:Tue, 1 Mar 2022 16:00:00 GMT" -submit "MyCertificateRequest.req"
Applies to online and offline certificate templates.
For any certificate template that has a policy configuration defined, TameMyCerts will ensure that the resulting certificate will contain an identity, either in the Subject Distinguished Name or the Subject Alternative Name. If the resulting certificate would not contain an identity, the certificate request will get denied and an event will be logged.
Should you have the requirement to issue such certificates regardless
of not containing an identity, you may change the behavior with the
PermitEmptyIdentites
directive:
PermitEmptyIdentites>true</PermitEmptyIdentites> <
Applies to online and offline certificate templates.
TameMyCerts will automatically deny certificate requests when they contain a “san” request attribute and the certification authority has the insecure EDITF_ATTRIBUTESUBJECTALTNAME2 (https://www.gradenegger.eu/en/take-over-the-active-directory-overall-structure-with-the-flag-editf_attributesubjectaltname2/) flag set. This combination can allow an attacker to request certificates with arbitrary identities, resulting in a complete takeover of your Active Directory.
This behavior can be altered by configuring Global settings for the policy module. However, it is stongly advised not to do so.
Instead of using the “san” request attribute in combination with
EDITF_ATTRIBUTESUBJECTALTNAME2
, you should ensure that
certificate request already contain a Subject Alternative Name (SAN)
extension. In case where this is not possible, the Supplementing DNS Names and IP
Addresses feature can be used.
Note that TameMyCerts will log the presence of the “san” request attribute whether the flag is enabled or not.
Applies to online and offline certificate templates.
TameMyCerts YubiKey PIV attestation is the first utlizing Event Tracing for Windows (ETW) for logging. YubiKey validation will log which policy was matched in the Operations log, the entry will also include information about the YubiKey.
TameMyCerts can ensure that a key pair has been created and is secured with a YubiKey (https://www.yubico.com/products/yubikey-5-overview/).
This feature is called Personal Identity Verification (PIV) attestation (https://developers.yubico.com/PIV/Introduction/PIV_attestation.html). It can be combined with any other TameMyCerts feature.
It is possible to include the attestation certificates in the Certificate Signing Request by using any of the following means:
For the attestation certificate chain to be properly built, you must
create a YKROOT
certificate store under the
LocalMachine
certificate store on the certification
authority server.
Set-Location -Path Cert:\LocalMachine
New-Item -Name YKROOT
New-Item -Name YKCA
Any YubiKey attestation Root CA certificates must be imported into
the YKROOT
certificate store.
The import could be scripted like the following:
Get-ChildItem -Path *.cer | ForEach-Object -Process { certutil -addstore YKROOT $_.FullName }
Any YubiKey intermediate CA certificates must be imported into the
YKCA
certificate store (only applies to YubiKeys with
Firmware 5.7.4 or newer).
The import could be scripted like the following:
Get-ChildItem -Path *.cer | ForEach-Object -Process { certutil -addstore YKCA $_.FullName }
Note that it is required to restart the certification authority service to reflect any changes that are made to the
YKROOT
andYKCA
certificate stores.
Note that these might need to get updated during the lifetime of the certification authority, as the vendor might introduce devices signed with newer CA certificates.
You define a YubiKeyPolicies
directive containing one or
more YubiKeyPolicy
rules.
Parameter | Mandatory | Description |
---|---|---|
Action |
yes | Specifies if this rule shall cause the certificate request to be
allowed or denied, should it’s conditions match. Can be
Allow or Deny . |
PinPolicy |
no | Specifies which PIN policy must be configured on the YubiKey for the
rule to match. Can be one or more of the following: Once ,
Never , Always , MatchOnlye ,
MatchAlways . |
TouchPolicy |
no | Specifies which Touch policy must be configured on the YubiKey for
the rule to match. Can be one or more of the following:
Always , Never , Cached . |
FormFactor |
no | Specifies of which form factor the YubiKey must be for the rule to
match. Can be one or more of the following: UsbAKeychain ,
UsbCKeychain , UsbANano , UsbCNano ,
UsbCLightning , UsbABiometricKeychain ,
UsbCBiometricKeychain . |
MaximumFirmwareVersion |
no | Specifies the maximum Firmware version the YubiKey must have for the rule to match. |
MinimumFirmwareVersion |
no | Specifies the minimum Firmware version the YubiKey must have for the rule to match. |
Edition |
no | Specifies of which edition the YubiKey must be for the rule to
match. Can be one or more of the following: FIPS ,
Normal , CSPN . |
Slot |
no | Specifies the Slot under which the certificate request must be
stored under for the rule to match. Can be one or more of the following:
9a , 9c , 9d , 9e . |
KeyAlgorithm |
no | Specifies the Key Algorithm of which the certificate request must be
for the rule to match. Can be one or more of the following:
RSA , ECC . |
The YubiKeyPolicies are read one by one.
Allow
action, the default behavior if no rule matched is to
deny the certificate request.Deny
action,
the default behavior if no rule matched is to allow the
certificate request.Allow
action must match, whereas
none of the policies with Deny
action must
match.This is only an example. Refer to the vendor’s documentation (https://developers.yubico.com/yubico-piv-tool/) for more information on how to use the tool.
Certificate requests can be created in various ways. Here is an example using the YubiKey PIV Tool.
First, a key pair has to be created. This will save the public key
into a file named pubkey.key
.
yubico-piv-tool --slot=9a --action=generate --pin-policy=once --touch-policy=cached --algorithm=ECCP384 --output=pubkey.key
Afterwards, a Certificate Signing Request can be created using the
public key. It will be saved into a file called
request.csr
.
yubico-piv-tool --slot=9a --subject="/CN=this-is-a-test/" --input=pubkey.key --attestation --output=request.csr --action=verify-pin --action=request
Attestation Information can be written into the Subject Distinguished Name of the issued certificates using the following tokens:
yk:FormFactor
yk:FirmwareVersion
yk:PinPolicy
yk:TouchPolicy
yk:Slot
yk:SerialNumber
TameMyCerts will transfer the following certificate extensions from the YubiKey attestation certificate into the issued certificate (if present in the attestation certificate):
Extension OID | Description |
---|---|
1.3.6.1.4.1.41482.3.3 |
Firmware version, encoded as 3 bytes, like: 040300 for
version 4.3.0. |
1.3.6.1.4.1.41482.3.7 |
Serial number of the YubiKey, encoded as an integer. |
1.3.6.1.4.1.41482.3.8 |
Two bytes, the first encoding pin policy (01 - never,
02 - once per session, 03 - always) and the
second touch policy (01 - never, 02 - always,
03 - cached for 15 seconds) |
1.3.6.1.4.1.41482.3.9 |
Formfactor, encoded as one byte: USB-A Keychain: 01 and
81 for FIPS Devices, USB-A Nano: 02 and
82 for FIPS Devices, USB-C Keychain: 03 and
83 for FIPS Devices, USB-C Nano: 04 and
84 for FIPS Devices, Lightning and USB-C: 05
and 85 for FIPS Devices |
1.3.6.1.4.1.41482.3.10 |
FIPS Certified YubiKey |
1.3.6.1.4.1.41482.3.11 |
CSPN Certified YubiKey |
It was originally intended to provide an option to include the original attestation data in issued certificates, but as YubiKeys have a size limit of 3052 bytes for issued certificates (see https://docs.yubico.com/yesdk/users-manual/application-piv/attestation.html for more details), this is not feasible.
If you intend to add a proof of attestation into issued certificates, do this by adding an Issuance Policy to issued certificates.
Not all tools that may be used to create certificate requests with PIV attestation support adding a Subject Alternative Name or, for example, do not support the Microsoft-proprietary userPrincipalName SAN type. TameMyCerts can add this information by Modifying the Subject Alternative Name of issued certificates. See the below section for examples.
A simple policy that just ensures the key pair is protected with a YubiKey, without any additional requirements.
YubiKeyPolicies>
<YubiKeyPolicy />
<YubiKeyPolicies> </
Denying certificate requests for ECC keys with a YubiKey with firmware version prior to 5.7.0 (these have a vulnerability, see https://www.yubico.com/support/security-advisories/ysa-2024-03/ for more details).
YubiKeyPolicies>
<YubiKeyPolicy>
<MaximumFirmwareVersion>5.6.9</MaximumFirmwareVersion>
<KeyAlgorithm>
<string>ECC</string>
<KeyAlgorithm>
</Action>Deny</Action>
<YubiKeyPolicy>
</YubiKeyPolicies> </
Transferring the Slot and Serial Number of the YubiKey into the
commonName of the issued certificate (in combination with the
cn
attribute from a mapped Active
Directory object).
Note that the commonName is subject to a length constraint determined by Microsoft AD CS.
YubiKeyPolicies>
<<!-- other directives have been left out for simplicity -->
YubiKeyPolicies>
</OutboundSubject>
<OutboundSubjectRule>
<Field>commonName</Field>
<Value>{ad:cn} [{yk:Slot} {yk:SerialNumber}]</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
Transferring the Serial Number of the YubiKey into the serialNumber of the issued certificate.
YubiKeyPolicies>
<<!-- other directives have been left out for simplicity -->
YubiKeyPolicies>
</OutboundSubject>
<OutboundSubjectRule>
<Field>serialNumber</Field>
<Value>{yk:SerialNumber}]</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
A policy containing all possible combinations.
YubiKeyPolicies>
<YubiKeyPolicy>
<Action>Allow</Action>
<PinPolicy>
<string>Once</string>
<string>Never</string>
<string>Always</string>
<string>MatchOnce</string>
<string>MatchAlways</string>
<PinPolicy>
</TouchPolicy>
<string>Always</string>
<string>Never</string>
<string>Cached</string>
<TouchPolicy>
</FormFactor>
<string>UsbAKeychain</string>
<string>UsbCKeychain</string>
<string>UsbANano</string>
<string>UsbCNano</string>
<string>UsbCLightning</string>
<string>UsbABiometricKeychain</string>
<string>UsbCBiometricKeychain</string>
<FormFactor>
</MaximumFirmwareVersion>9.9.9</MaximumFirmwareVersion>
<MinimumFirmwareVersion>0.0.0</MinimumFirmwareVersion>
<Edition>
<string>FIPS</string>
<string>Normal</string>
<string>CSPN</string>
<Edition>
</Slot>
<string>9a</string>
<string>9c</string>
<string>9d</string>
<string>9e</string>
<Slot>
</KeyAlgorithm>
<string>RSA</string>
<string>ECC</string>
<KeyAlgorithm>
</YubiKeyPolicy>
</YubiKeyPolicies> </
Mapping the User’s Active Directory identity from the commmonName of the certificate to the sAMAccountName of the AD object and adding the user’s userPrincipalName to the Subject Alternative Name of the issued certificate, after verifying PIV attestation.
Subject>
<SubjectRule>
<Field>commonName</Field>
<Mandatory>true</Mandatory>
<Patterns>
<Pattern>
<Expression>^[a-zA-Z0-9]*$</Expression>
<Pattern>
</Patterns>
</SubjectRule>
</Subject>
</DirectoryServicesMapping>
<CertificateAttribute>commonName</CertificateAttribute>
<DirectoryServicesAttribute>sAMAccountName</DirectoryServicesAttribute>
<DirectoryServicesMapping>
</YubiKeyPolicies>
<<!-- other directives have been left out for simplicity -->
YubiKeyPolicies>
</OutboundSubjectAlternativeName>
<OutboundSubjectRule>
<Field>userPrincipalName</Field>
<Value>{ad:userPrincipalName}</Value>
<Mandatory>true</Mandatory>
<OutboundSubjectRule>
</OutboundSubjectAlternativeName> </
Please be aware that if no policy file exists for a given certificate template, the request gets accepted as this would be the original behavior of the Windows Default policy module. This behavior can however be changed by configuring a global setting for TameMyCerts.
If a certificate request violates the defined policy, the certification authority will deny it with one of the below error codes and messages. The CA will log Event with ID 53 (https://www.gradenegger.eu/en/details-of-the-event-with-id-53-of-the-source-microsoft-windows-certificationauthority/). The error code/message will also be handed over to the requesting client over the DCOM protocol as answer to the certificate request.
TameMyCerts will also write its own Logs which contain detailled information about why a certificate request was denied, amongst others.
The following error codes can be thrown by the policy module back to the requestor when a request was denied:
Message | Symbol | Description |
---|---|---|
The permissions on the certificate template do not allow the current user to enroll for this type of certificate. | CERTSRV_E_TEMPLATE_DENIED |
Occurs if the process used to create the certificate request is unknown, not allowed or explicitly disallowed. Also occurs when Directory Services mapping encounters an error. |
The certificate has an invalid name. The name is not included in the permitted list or is explicitly excluded. | CERT_E_INVALID_NAME |
Occurs if the requests Subject Distinguished Name or Subject Alternative Name violates the defined rules. |
The public key does not meet the minimum size required by the specified certificate template. | CERTSRV_E_KEY_LENGTH |
Occurs if the requests public key violates the defined rules for key algorithm or maximum key length. |
An internal error occurred. | ERROR_INVALID_DATA |
Occurs if the policy module is unable to interpret the given policy file. |
The specified time is invalid. | ERROR_INVALID_TIME |
Occurs if an invalid date was requested for the “StartDate” certificate request attribute. |
TameMyCerts features the following caches:
Certificate template configuration is read by TameMyCerts from the CA servers registry every 5 minutes to reduce CPU load.
Note that updates made to a certificate template in Active Directory are not instantly replicated to the CA servers registry, as this part of the registry is only updated every 8 hours.
Certificate Request policy files are loaded on first use and are then served from memory as long as they do not change. This reduces CPU and storage load. When the file gets modified and therefore the modification date of the file gets updated, it will get re-loaded on next use.
Should you, for example, copy a previous version of a policy configuration file back to the configured directory, it will not get read because it would have an older modification date. You would have to save it again so that it has a newer timestamp. Alternatively, you could re-start the certification authority service, as this will invalidate the cache.
TameMyCerts currently does only support the following Subject Alternative Name types:
dnsName
rfc822Name
uniformResourceIdentifier
userPrincipalName
ipAddress
If a certificate request contains an unsupported SAN type, the behavior is as follows:
When an error parsing the policy configuration file is thrown, remember that the actual line may be above or below the one noted in the log entry.
This is expected as there is a chaching involved. The cache is read from the local certificate template cache of the CA server and updated every five minutes. Therefore, you can do one of the following to solve this:
Wait until the local certificate template gets updated automatically. This can take up to eight hours.
Update the local certificate template cache on your own. To do this, run the following command as an administrator:
certutil -pulse
You’ll then still have to wait up to 5 minutes or restart the CA service afterwards for the certificate template to get recognized.
Certificate requests that contain relative distinguished with empty values (e.g. CN=““) are treated as if the RDN was missing when a subject rule is applied. This is because TameMyCerts doesn’t inspect the actual certificate request but how the certification authority would issue the certificate. Microsoft AD CS does remove relative distinguished names containing empty values.
As TameMyCerts follows the original Microsoft concept of certificate templates, it does not support standalone certification authorities (as these do not use certificate templates).
At the moment, TameMyCerts can not be combined with other policy modules except the Windows Default policy module that is shipped with Active Directory Certificate Services. A common example for an incompatible module would be the policy modules shipped with Microsoft Identity Manager Certificate Management (MIM CM).
In addition to the certification authorities regular log entries, the
policy module will also write a detailed log entry if a certificate
request was denied due to a policy violation or failure. Find the logs
under the Application event log with the
TameMyCerts
Event Source.
Logging for the policy module follows the LogLevel
(https://www.gradenegger.eu/en/configure-log-level-log-level-for-the-certification-authority-event-log/)
concept of the certification authority. Increasing the value for the
certification authority also affects the logging amount of
TameMyCerts.
certutil -setreg CA\Loglevel {LogLevel}
net stop certsvc
net start certsvc
Log Level | Description |
---|---|
0 | CERTLOG_MINIMAL |
1 | CERTLOG_TERSE |
2 | CERTLOG_ERROR |
3 | CERTLOG_WARNING (Default Setting) |
4 | CERTLOG_VERBOSE |
5 | CERTLOG_EXHAUSTIVE |
CERTLOG_VERBOSE
){0} policy module version {1} is ready to process incoming certificate requests.
{0}
will contain the policy module
name.{0}
will contain the policy module
version.Occurs if the Windows Default policy was successfully loaded and TameMyCerts is ready to process incoming requests.
CERTLOG_ERROR
)Error initializing Windows Default policy module:
{0}
{0}
will contain the error message.Occurs if the Windows Default policy was not successfully loaded during CA service startup. Will cause the CA service to not start.
CERTLOG_ERROR
)Shutting down Windows Default policy module failed:
{0}
{0}
will contain the error message.Occurs if the Windows Default policy was not successfully unloaded during CA service shutdown.
CERTLOG_MINIMAL
)Audit mode is enabled for {1}. Request {0} would get denied because:
{2}
{0}
will contain the Request ID
number.{1}
will contain the certificate template
name.{2}
will contain one or more reasons why
the certificate request would get denied.Occurs if Audit only mode is enabled for a certificate template and a certificate request would get denied because of a policy violation. Contains a detailed information which kind of policy violation caused the request to get denied.
CERTLOG_WARNING
)Request {0} for {1} was denied because:
{2}
{0}
will contain the Request ID
number.{1}
will contain the certificate template
name.{2}
will contain one or more reasons why
the certificate request was denied.Occurs if a certificate request was denied because of a policy violation. The event description contains detailed information which kind of policy violation caused the request to get denied.
Note that TameMyCerts can also detect abuse of insecure flags set on the certification authority, which can help prevent compromise of the Active Directory environment. Occurrences are logged under this event ID.
CERTLOG_VERBOSE
)Unable to find policy file for {0}. Request {1} will get issued.
{0}
will contain the certificate template
name.{1}
will contain the Request ID
number.Occurs if there is no policy configuration file defined for the certificate template used certificate request. The certificate request gets allowed in this case.
CERTLOG_WARNING
)Unable to find policy file for {0}. Request {1} will get denied.
{0}
will contain the certificate template
name.{1}
will contain the Request ID
number.Occurs if there is no policy configuration file defined for the certificate template used certificate request, and TameMyCerts global flags are configured to deny certificate requests when there is no policy defined. The certificate request gets denied in this case.
CERTLOG_ERROR
)The {0} policy module currently does not support standalone certification authorities.
{0}
will contain the policy module
name.Occurs it the TameMyCerts policy module is loaded on a standalone certification authority, which is unsupported at the moment. Will cause the CA service to not start.
CERTLOG_ERROR
)Request {0} will get denied. Unable to interpret policy for {1} because:
{2}
No certificate template information for request {0} could be retrieved from the certification authority service. The request will get denied.
No certificate template information for request {0} could be retrieved from the local certificate template cache. The request will get denied.
{0}
will contain the Request ID
number.{1}
will contain the certificate template
name.{2}
will contain any additional error
messages.Occurs if a certificate request was denied because because the policy file for the certificate template could not be interpreted.
CERTLOG_VERBOSE
)Request {0} was denied by the Windows Default policy module.
{0}
will contain the Request ID
number.Occurs if the Windows Default policy module denied a certificate request, thus the additional logic of TameMyCerts was not triggered at all for the given request. As this is a normal occurrence during PKI operations, this event is just informational.
CERTLOG_VERBOSE
)Request {0} for {1} will get issued.
{0}
will contain the Request ID
number.{1}
will contain the certificate template
name.This is an informational event containing the request ID and the certificate template name in case TameMyCerts decides that the certificate request shall get issued.
CERTLOG_VERBOSE
)Request {0} for {1} will be put into pending state.
{0}
will contain the Request ID
number.{1}
will contain the certificate template
name.This is an informational event containing the request ID and the certificate template name in case TameMyCerts decides that the certificate request shall be put into pending state.
CERTLOG_WARNING
)The following warnings have been logged during the processing of request {0} for {1}:
{2}
{0}
will contain the Request ID
number.{1}
will contain the certificate template
name.{2}
will contain one or more warnings that
have been logged during the processing of the certificate request.This event gets logged if warnings occurred during the processing of the certificate request. This event will get logged regardless if the certificate gets issued or not.
Warnings might indicate an abnormal condition. It is therefore recommended to collect these events and trigger an alert in your monitoring solution, if present.
Currently, TameMyCerts logs warnings in the following cases:
The Pattern
parameter is defined as follows:
Parameter | Mandatory | Description |
---|---|---|
Expression |
yes | Specifies the expression the field gets matched against. |
TreatAs |
no | Specifies how the expression is to be interpreted by TameMyCerts.
Defaults to RegEx . |
Action |
no | Specifies if a match for the pattern will Allow the
certificate to get issued (the default) or Deny the
certificate request. |
The TreatAs
directive can be configured to one of the
following values:
Value | Description |
---|---|
RegEx |
Treat the value to be analyzed as a case sensitive regular expression (the default). |
RegExIgnoreCase |
Treat the value to be analyzed as a case insensitive regular expression. |
Cidr |
Treat the value to be analyzed as an IP address that must be within
an IPv4 or IPv6 subnet in CIDR notation,
e.g. 192.168.0.0/16 . |
ExactMatch |
The value to be analyzed must exactly match the configured expression (case sensitive). |
ExactMatchIgnoreCase |
The value to be analyzed must exactly match the configured expression (case insensitive). |
The following Active Directory attributes are supported as “DirectoryServicesAttribute”:
Attribute | In Global Catalog | Remarks |
---|---|---|
c | yes | |
co | no | |
company | no | |
department | no | |
departmentNumber | no | |
description | yes | |
displayName | yes | |
division | no | |
dNSHostName | yes | Computer objects only |
employeeID | no | |
employeeNumber | no | |
employeeType | no | |
extensionAttribute1 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute2 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute3 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute4 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute5 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute6 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute7 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute8 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute9 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute12 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute10 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute12 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute11 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute12 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute13 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute14 | no | only available when Microsoft Exchange is used in the environment |
extensionAttribute15 | no | only available when Microsoft Exchange is used in the environment |
facsimileTelephoneNumber | no | |
gecos | no | |
givenName | yes | |
homePhone | yes | |
homePostalAddress | no | |
info | no | |
initials | no | |
l | yes | |
location | yes | Computer objects only |
yes | ||
mailNickname | no | |
middleName | no | |
mobile | no | |
name | yes | |
otherMailbox | no | |
otherMobile | no | |
otherPager | no | |
otherTelephone | no | |
pager | no | |
personalPager | no | |
personalTitle | no | |
postalAddress | no | |
postalCode | no | |
postOfficeBox | no | |
sAMAccountName | yes | |
sn | yes | |
st | yes | |
street | yes | |
streetAddress | no | |
telephoneNumber | no | |
title | no | |
userPrincipalName | yes |
Beginning with Version 1.7, TameMyCerts uses .NET 8.0 instead of the previously used .NET Framewotk 4.7.2. Therefore, you must install the .NET 8.0 Desktop runtime prior to installing the module.
Policy configuration files are now strictly processed, means that there will be errors raised when they contain invalid nodes. This may especially affect the following:
KeyAlgorithm
nodes (which were removed with version 1.6),
these must be removed from the configuration files.Action
directives as well as the
TreatAs
directives for Pattern
directives as
processed case-sensitive, means that they must be specified exactly as
documentated.If you are upgrading from a TameMyCerts version older than 1.6, you must adjust some elements in your policy configuration files.
DirectoryServicesMapping
. The directives have been
renamed and the syntax has changed to enable advanced modifications of
both Subject Distinguished Name (Subject DN) and Subject Alternative
Name (SAN).TameMyCerts version 1.5 and lower used the following syntax:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
SubjectDistinguishedName>
<RelativeDistinguishedName>
<Field>emailAddress</Field>
<DirectoryServicesAttribute>mail</DirectoryServicesAttribute>
<Mandatory>true</Mandatory>
<RelativeDistinguishedName>
</SubjectDistinguishedName>
</DirectoryServicesMapping> </
TameMyCerts version 1.6 and newer now uses the following syntax:
DirectoryServicesMapping>
<<!-- other directives have been left out for simplicity -->
DirectoryServicesMapping>
</OutboundSubject>
<OutboundSubjectRule>
<Field>emailAddress</Field>
<Value>{ad:mail}</Value>
<Mandatory>true</Mandatory>
<Force>true</Force>
<OutboundSubjectRule>
</OutboundSubject> </
If you are upgrading from a TameMyCerts version older than 1.2, you must adjust some elements in your policy configuration files.
organizationalUnit
under SubjectRule
must
be changed to organizationalUnitName
.TameMyCerts version 1.1 and lower used the following syntax:
SubjectRule>
<Field>organizationalUnit</Field>
<<!-- other directives have been left out for simplicity -->
SubjectRule> </
TameMyCerts version 1.2 now uses the following syntax:
SubjectRule>
<Field>organizationalUnitName</Field>
<<!-- other directives have been left out for simplicity -->
SubjectRule> </
If you are upgrading from a TameMyCerts version older than 1.1, you must adjust some elements in your policy configuration files.
AllowedPattern
under SubjectRule
must be
changed to Pattern
with differing syntax.DisallowedPattern
under SubjectRule
must
be changed to Pattern
with differing syntax.TameMyCerts version 1.0 used the following syntax:
SubjectRule>
<Field>commonName</Field>
<AllowedPatterns>
<string>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</string>
<AllowedPatterns>
</DisallowedPatterns>
<string>^.*(porn|gambling).*$</string>
<DisallowedPatterns>
</SubjectRule> </
TameMyCerts version 1.1 now uses the following syntax:
SubjectRule>
<Field>commonName</Field>
<Patterns>
<Pattern>
<Expression>^[-_a-zA-Z0-9]*\.tamemycerts\.com$</Expression>
<Pattern>
</Pattern>
<Expression>^.*(porn|gambling).*$</Expression>
<Action>Deny</Action>
<Pattern>
</Patterns>
</SubjectRule> </
Enterprise use Mobile Device Management (MDM) products to provision and manage their mobile devices like smartphones, tablet computers or even entire desktop computers, over-the-air (OTA).
Common MDM products include:
All these systems follow a similar concept: They act as an intermediary between the managed device, the coprorate directory service, and the certification authority. All of them provide some kind connector to submit certificate requests to a Microsoft AD CS certification authority.
Microsoft Intune uses the Network Device Enrollment Service (NDES) (https://learn.microsoft.com/en-us/windows-server/identity/ad-cs/network-device-enrollment-service-overview) role as a connector between Intune and the certification authority. NDES, like the certificaton authority, allows for custom-developed policy modules. Microsoft provides a policy module for NDES in combination with Intune, therefore it is not possible to add another policy module to an Intune-enabled NDES instance. However, TameMyCerts, as it resides on the CA, can coexist perfectly well with an Intune-enabled NDES instance, including the Intune policy module there.
All MDM systems require the certificate template to be configured as an offline certificate template. This means that the certification authority must accept any identity contained in a certificate request. Furthermore, all certificate requests are submitted to the certification authority using a single service account. If this account is compromised or otherwise abused, if the MDM system is misconfigured or has a software flaw, the certification authority will issue virtually any possible identity, including those of the CEO or highly privileged system accounts and administrators, which can lead to a variety of security disasters.
The default deployment with a Microsoft Certification Authority using Active Directory Certificate Services makes the whole setup vulnerable to the Swiss Cheese Model (see https://en.wikipedia.org/wiki/Swiss_cheese_model for futrher information), in which all participating layers having a small flaw, which in combinations allow disasters to happen.
TameMyCerts can restrict the requested certificate content to precisely-defined certificate fields as well as apply syntax rules to these. In addition, TameMyCerts is able to map requested identities back to their underlying Active Directory objects and can decide whether a certificate shall be issued based on enablement status, group memberships and other criteria.
Many enterprises nowadays want to establish paperless processes to ease and speed up internal approval and signature processes. This has become even more important in the times of employees predominantly working remotely. Whilst Microsoft AD CS is capable of automating certificate issuance processes, its possibilities to influence the certificate content are limited.
TameMyCerts allows to define advanced rules to build the Subject Distinguished names or Subject Alternative Names with either statically defined values, or by pulling the necessary data from Active Directory. This drastically extends the possibilities of certificate Autoenrollment in the Windows ecosystem.
For example, you could populate a certificates Common Name with the displayName Active Directory attribute and set a static value for the organizationName field as well.
Beginning with Version 58, Google decided to remove the support for certificates containing only a Subject Distinguished Name (Subject DN) (https://developer.chrome.com/blog/chrome-58-deprecations/#remove-support-for-commonname-matching-in-certificates). From thereon, certificates not containing a Subject Alternate Name in form of a DNS name were treated as invalid by Google Chrome. Soon, other major browser vendors adopted this approach.
This behavior is in compliance to the IETF RFC 2818 (https://tools.ietf.org/html/rfc2818) dating back to the year 2000. Certificates for web servers must therefore use the Subject Alternative Name (SAN) for their identity. Sadly, there are still a lot of products in use that are not capable of creating a Certificate Signing Request containing a SAN in form of a DNS name.
Sadly, many HowTos on the web instruct CA administrators to enable the EDITF_ATTRIBUTESUBJECTALTNAME2 flag on their CAs in the belief this would enable them the issuance of SANs for certificate requests not containine one. However, doing so opens a large security hole, as this setting allows anyone to request any identity for any certificate template published on the certification authority.
Luckily, there are better ways to reach the intended goal.
With TameMyCerts, there is a secure, yet automatic method available to fix those certificates without the need of enabling insecure flags on the CA. TameMyCerts can be instructed to transfer the content of the Subject Distinguished Name into a Subject Alternative Name (SAN) extension prior to issuing the certificate. Furthermore, TameMyCerts ensures that attempts to abuse the certification authority are detected and such requests wil get denied, should an insecure flag still be enabled.
Attacks on Microsoft certification authorities include the abuse of permissions on certificate templates. In many cases, certificate templates must be configured to allow the enrollee request any kind of identity, which can lead to account impersonation and elevation of privileges. These kinds of attacks are known as ESC1 (https://posts.specterops.io/certified-pre-owned-d95910965cd2) in the security scene.
ESC1 abuses a certificate template that is configured with the “Enrollee supplies subject” setting enabled (also called an “offline” certificate template, because the identity is provided by the enrollee, as opposed to an “online” certificate template where the certificate identity is built from Active Directory based on the enrollee’s logon information). The adversary would have to submit a certificate request containing a “malicious” Subject Alternative Name certificate extension.
TameMyCerts can contain the damage done in such a case, and in even prevent the attack in many cases:
Rule violations are being logged and thus allow alerting on policy violations.
Many HowTos on the web instruct CA administrators to enable the EDITF_ATTRIBUTESUBJECTALTNAME2 flag on their CAs. However, this opens a large security hole, as this setting allows anyone to request any identity for any certificate template. These kinds of attack against Microsoft Active Directory Certificate Services have widely become known as ESC6 and ESC7 (https://posts.specterops.io/certified-pre-owned-d95910965cd2) in the security scene.
ESC6 abuses a certification authority that has the EDITF_ATTRIBUTESUBJECTALTNAME2 flag globally enabled. When this flag is enabled in the certification authoritys configuration - either by lack of knowledge or by accident - an attacker can send a malicious request attribute to the certification authority (https://www.gradenegger.eu/en/take-over-the-active-directory-overall-structure-with-the-flag-editf_attributesubjectaltname2/) whilst submitting a legitimate certificate request, instructing the certification authoritry to add the specified content to the Subject Alternative Name (SAN) extension of the issued certificate, regardless of certificate template security settings.
TameMyCerts ensures that such attempts to abuse the certification authority are detected and requests are denied, should the insecure flag be enabled. The denied certificate request is getting logged, so that an alert can be triggered.
This mechanism was adopted as a core part of the Certiception (https://github.com/srlabs/Certiception) honeypot toolkit for Active Directory Certificate Services and allows spotting adversaries trying to abuse a certification authority.
Administrators sometimes enable the setting to be able to add SANs to certificate requests not containing them (e.g. because the host on which the original certificate request was made is not capable of requesting SANs). In the most common use case of Web Server certificates, certificates without a SAN (in form of a DNS Name) will get rejected by applications (any modern web browser like Mozilla Firefox, Google Chrome, Microsoft Edge, and so on). TameMyCerts provides a secure alternative to this approach in that it is able to detect DNS Names and IP addresses found in the Common Name of a certificate request and automatically transfer them to a newly-built SAN certificate extension.
TameMyCerts has evolved into a reliable, secure and stable enterprise product. Many organizations around the world are relying on it to improve their security and their PKI workflows. Professional development, testing and documentation consumes a considerable amount of time and resources. Whilst still being fully committed on keeping source code available for the community, digitally signed binaries, a print-optimized documentation and priority support are benefits only available for customers with an active maintenance contract.
This version was released on May 29, 2025.
KeyAlgorithm
nodes (which were removed with version 1.6),
these must be removed from the configuration files.Action
directives as well as the
TreatAs
directives for Pattern
directives as
processed case-sensitive, means that they must be specified exactly as
documentated.san
request attribute
will get logged regardless if the dangerous
EDITF_ATTRIBUTESUBJECTALTNAME2
flag is enabled or not.SupplementUnqualifiedNames
switch to use
in combination with supplementing of DNS names (both
SupplementDnsNames
and
SupplementServicePrincipalNames
). To keep compatibility
with the previous behavior, this setting defaults to true
.
If set to false
, supplementation logic will not include DNS
names that are not fully qualified.This version was released on Nov 12, 2023.
This is a major release containing lots of bug fixes for edge-cases as well as many new exciting features, whilst (mostly) staying backwards-compatible to existing configuration files.
CrlDistributionPoints
,
AuthorityInformationAccess
and
OnlineCertificateStatusProtocol
directives.KeyAlgorithm
parameter
has therefore been removed. Existing configurations will continue to
work but without using the configured KeyAlgorithm
.AllowedProcesses
or DisallowedProcesses
directives are configured, as this information cannot be obtained from
the CA directly. There are rare cases where it may not be possible to
parse the inline certificate request. In this case, the requested
properties will be treated as non-existent.commonName
and Subject Alternative Name fields
optional at the same time in a policy, whilst ensuring a certitificate
request has one of them set. The behavior can be disabled with the
PermitEmptyIdentities
parameter.SupplementServicePrincipalNames
directive. This mode allows
to automatically add all DNS names found in the Service Principal Names
(SPNs) of mapped AD objects to the SAN extension of issued
certificates.Pattern
directives like in Subject or SAN rules that can
get applied all of the attributes that can be used for building the
Subject Distingushed Name.AllowedOrganizationalUnits
and
DisallowedOrganizationalUnits
parameters.AddSidIUniformResourceIdentifier
.Pattern
directives now support the new
RegExIgnoreCase
kind for the TreatAs
attribute, which allows a regular expression to be treated
case-insensitive.Pattern
directives now support the new
ExactMatch
and ExactMatchIgnoreCase
kinds for
the TreatAs
attribute, which allow simple value
comparisons, either case sensitive or case-insensitive.Pattern
directives now support matching IPv6 addresses
against CIDR masks when TreatAs
is set to
Cidr
.TreatAs
attribute was specified for a
Pattern
in a Subject or SAN rule.This version was released on Jan 31, 2023.
This is a quality improvement only release. TameMyCerts now uses the interfaces provided by the certification authority to determine Subject and Subject Alternative Name information.
ReadSubjectFromRequest
to true in request
policy.This version was released on Dec 30, 2022.
This is a quality improvement only release. TameMyCerts is now covered by automated integration tests which allow testing parts of the code base otherwise not testable with unit tests.
This version was released on Nov 15, 2022.
StartDate
attribute functionality).szOID_NTDS_CA_SECURITY_EXT
) certificate extension when
provided in a certificate request instead of denying it entirely
(Remove
keyword for the SecurityIdentifierExtension
directive).serialNumber
,
unstructuredName
and unstructuredAddress
relative distinguished name types.0.0.0.0/0
) in a subject rule.This version was released on Aug 11, 2022.
szOID_NTDS_CA_SECURITY_EXT
with object id
1.3.6.1.4.1.311.25.2
) certificate extension that was
introduced with KB5014754
to certificates issued for offline certificate requests (requires
directory mapping). This should enable users to prevent authentication
to fail when strong certificate mapping will be enforced on February 11,
2025.szOID_NTDS_CA_SECURITY_EXT
certificate extension by the
enrollee. Policy can be configured to deny or allow offline requests
containing this extension (default is to deny).StartDate
request attribute and align behavior with Windows
Default policy module.organizationalUnitName
RDN to align with X.520
specifications (it was wrongly called organizationalUnit
in
earlier versions). Note that this breaks existing policy files.
These must be adjusted when upgrading.2.5.29.9
) request extension, as this
is disabled for issuance on AD CS by default anyway.This version was released on Mar 10, 2022.
StartDate
request attribute, in analogy to the
ExpirationDate
request attribute supported by the Windows
Default policy module.san
attribute get denied if
the flag is enabled.ExpirationDate
attribute.SubjectRule
Field
definition is now
processed case insensitive.This version was released on Feb 15, 2022.
This is the initial release of TameMyCerts made publicly available.
Abbreviation | Description |
---|---|
ACME | Automatic Certificate Management Environment |
AD CS | Active Directory Certificate Services |
AD DS | Active Directory Domain Services |
AIA | Authority Information Access |
CA | Certification Authority |
CDP | CRL Distribution Point |
CN | Common Name |
CRL | Certificate Revocation List |
CSR | Certificate Signing Request |
CRLDP | CRL Distribution Point |
DN | Distinguished Name |
DNS | Domain Name System |
ETW | Event Tracing for Windows |
GC | Global Catalog |
HTTP | HyperText Transfer Protocol |
HTTPS | HyperText Transfer Protocol, Secure |
IETF | Internet Engineering Task Force |
IP | Internet Protocol |
IPv4 | Internet Protocol Version 4 |
IPv6 | Internet Protocol Version 6 |
ITU-T | International Telecommunication Union Telecommunication Standardization Sector |
LDAP | Lightweigt Directory Access Protocol |
MDM | Mobile Device Management |
MMC | Microsoft Management Console |
NAC | Network Access Control |
NDES | Network Device Enrollment Service |
OCSP | Online Certificate Status Protocol |
PIV | Personal Identity Verification |
PKI | Public Key Infrastructure |
RA | Registration Authority |
RDN | Relative Distinguished Name |
REST | Representational State Transfer |
RFC | Request for comment |
SAN | Subject Alternative Name |
SCEP | Simple Certificate Enrollment Protocol |
SID | Security Identifier |
URI | Uniform Resource Identifier |
URL | Uniform Resource Locator |
VA | Validation Authority |
XML | eXtended Markup Language |