Support · Requirements · Installation · License · Related Integrations
The Keyfactor ACME CA Gateway Plugin enables certificate enrollment using the ACME protocol (RFC 8555), providing automated certificate issuance via any compliant Certificate Authority. This plugin is designed for enrollment-only workflows — it does not support synchronization or revocation of certificates.
This plugin allows Keyfactor Gateways to:
- Submit CSRs to ACME-based CAs.
- Complete domain validation via DNS-01 challenges.
- Automatically retrieve and return signed certificates.
Once a certificate is issued, the plugin returns the PEM-encoded certificate to the Gateway.
This plugin has been tested and confirmed to work with the following ACME providers:
- Let's Encrypt
- Google ACME (Certificate Authority Service)
- ZeroSSL (functional but known slowness may cause timeouts)
- Buypass
It is designed to be provider-agnostic and should work with any standards-compliant ACME server.
DNS-01 challenge automation is supported through the following providers:
- Google Cloud DNS
- AWS Route 53
- Azure DNS
- Cloudflare
- NS1
Additional DNS providers can be added by extending the included IDnsProvider
interface.
1. Keyfactor Gateway submits CSR and SAN metadata to plugin.
2. Plugin initializes ACME client and creates a new order.
3. For each domain:
a. Retrieve DNS-01 challenge.
b. Use the configured DNS provider to publish challenge record.
c. Wait for DNS propagation and validate record.
d. Notify ACME provider to trigger validation.
4. Once all challenges are valid, finalize the order using CSR.
5. Download the signed certificate from ACME provider.
6. Return PEM certificate to the Gateway.
The plugin uses a modular design that separates ACME communication logic and DNS challenge automation, allowing for future extensibility in both areas.
⚠️ Revocation, certificate synchronization, and renewal tracking are intentionally not implemented in this plugin. All lifecycle tracking must be handled externally (e.g., via Keyfactor monitoring or Gateway automation).
The Acme AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 24.2 and later.
The Acme AnyCA Gateway REST plugin is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com.
To report a problem or suggest a new feature, use the Issues tab. If you want to contribute actual bug fixes or proposed enhancements, use the Pull requests tab.
This plugin automates DNS-01 challenges using pluggable DNS provider implementations. These providers create and remove TXT records to prove domain control to ACME servers.
✅ Supported DNS Providers (Initial Release)
Provider | Auth Methods Supported | Config Keys Required |
---|---|---|
Google DNS | Service Account Key or ADC | Google_ServiceAccountKeyPath , Google_ProjectId |
AWS Route 53 | Access Key/Secret or IAM Role | AwsRoute53_AccessKey , AwsRoute53_SecretKey |
Azure DNS | Client Secret or Managed Identity | Azure_TenantId , Azure_ClientId , Azure_ClientSecret , Azure_SubscriptionId |
Cloudflare | API Token | Cloudflare_ApiToken |
NS1 | API Key | Ns1_ApiKey |
⏱ DNS Propagation Logic
Before submitting ACME challenges, the plugin verifies DNS propagation using multiple public resolvers (Google, Cloudflare, OpenDNS, Quad9). A record must be visible on at least 3 servers to proceed, with up to 3 retries spaced by 10 seconds.
This logic is handled by the DnsVerificationHelper
class and ensures a high-confidence validation before proceeding.
🔑 Credential Flow
Each provider supports multiple credential strategies:
-
Google DNS:
- ✅ Service Account Key (via
Google_ServiceAccountKeyPath
) - ✅ Application Default Credentials (e.g., GCP Workload Identity or developer auth)
- ✅ Service Account Key (via
-
AWS Route 53:
- ✅ Access/Secret Keys (
AwsRoute53_AccessKey
,AwsRoute53_SecretKey
) - ✅ IAM Role via EC2 Instance Metadata (no explicit credentials)
- ✅ Access/Secret Keys (
-
Azure DNS:
- ✅ Client Secret (explicit
TenantId
,ClientId
,ClientSecret
) - ✅ Managed Identity or environment-based credentials via
DefaultAzureCredential
- ✅ Client Secret (explicit
-
Cloudflare:
- ✅ Bearer API Token for zone-level DNS control
-
NS1:
- ✅ API Key passed in header
X-NSONE-Key
- ✅ API Key passed in header
🧩 Adding New DNS Providers
To add support for new DNS services:
-
Implement the
IDnsProvider
interface:public interface IDnsProvider { Task<bool> CreateRecordAsync(string recordName, string txtValue); Task<bool> DeleteRecordAsync(string recordName); }
-
Register the new provider in the
DnsProviderFactory
:case "yourprovider": return new YourCustomDnsProvider(config.YourProviderConfigValues...);
-
Use zone detection logic similar to
GoogleDnsProvider
,AzureDnsProvider
, orNs1DnsProvider
.
Each provider is instantiated dynamically based on the DnsProvider
field in the AcmeClientConfig
.
🔁 This modular DNS system ensures challenge automation works across cloud providers and is easily extensible.
🔒 CA-Level DNS Provider Binding
Each ACME/DNS combination is supported at the CA level, meaning that only one DNS provider is configured per CA entry in Keyfactor. This ensures a clear and isolated challenge path for each ACME CA connector instance.
If you need to support multiple DNS zones/providers (e.g., both AWS and Cloudflare), configure separate CA entries, each with its own DNS provider configuration.
🚫 No Offline Challenge Retry (Initial Release)
In this initial release, there is no background or offline retry for ACME challenges that timeout. If DNS propagation takes too long and the challenge is not verified in time, the certificate request will fail immediately.
⚠️ However, in testing across all supported DNS providers and ACME services (e.g., Let's Encrypt, Google CAS, ZeroSSL, Buypass), propagation has been fast enough to avoid these timeouts in all observed cases.
Each ACME CA (Certificate Authority) has slightly different expectations for account creation and request handling. This plugin supports multiple providers and dynamically handles credentials based on your configuration.
🧩 External Account Binding (EAB) Support
Some providers require External Account Binding (EAB), which includes:
eabKid
: External Account Binding Key IDeabHmacKey
: HMAC Key to sign the JWK thumbprint
Others do not require EAB, and can create accounts automatically with just an email address.
✅ Supported Providers & Credential Expectations
Provider | Directory URL | Requires EAB | Notes |
---|---|---|---|
Let's Encrypt | https://acme-v02.api.letsencrypt.org/directory |
❌ No | Free and public; account created using only an email address |
Buypass | https://api.buypass.com/acme/directory |
❌ No | Free and public; supports long-lived certs; no EAB required |
ZeroSSL | https://acme.zerossl.com/v2/DV90/directory |
✅ Yes | Requires EAB; keys available via ZeroSSL Developer Portal |
Google CAS | https://dv.acme-v02.api.pki.goog/directory |
✅ Yes | Requires EAB; keys issued via Google CAS UI |
⚠️ If a provider requires EAB and it is not supplied, the request will fail during account registration.
📋 Configuration Fields (Per ACME Provider)
These values are set in the Keyfactor Command Gateway Configuration UI for each ACME provider:
Field | Description | Required |
---|---|---|
directoryUrl |
The full ACME directory URL for the CA | ✅ Yes |
email |
Account email address for ACME registration | ✅ Yes |
eabKid |
External Account Binding Key ID (if applicable) | 🚫 Only if EAB |
eabHmacKey |
HMAC key used to sign EAB binding (if applicable) | 🚫 Only if EAB |
🔐 How to Get EAB Credentials
-
ZeroSSL:
Log into your account and go to "ACME EAB Credentials" in the developer section. -
Google CAS:
Enable your CA Pool for ACME and generate EAB credentials under the ACME Integration tab in Google Cloud Console.
⚙️ Plugin Behavior
- If both
eabKid
andeabHmacKey
are provided, they will be used to create the ACME account. - If either is omitted and the provider requires it, account creation will fail.
- If neither is provided and the provider does not require EAB, the account will be created using only the email.
Each provider is configured in the JSON config under acmeProviders
, and only one provider is active per enrollment.
This ACME Gateway implementation uses a local file-based store to persist ACME accounts and their associated cryptographic signers. Accounts are cached on disk using a structured format, and signers (private keys) can be encrypted with a passphrase for enhanced security.
📁 Account Directory Structure
Each account is saved in its own directory within:
%APPDATA%\AcmeAccounts\{host}_{accountId}
Where:
{host}
is the ACME directory host with dots replaced by dashes (e.g.,acme-zerossl-com
){accountId}
is the final segment of the account's KID URL
📄 Files per Account
Registration_v2
: Contains serializedAccountDetails
in JSON formatSigner_v2
: Contains encrypted or plaintext signer key material, depending on passphrase usagedefault_{host}.txt
: Tracks the default account for a given ACME directory host
🔐 Encryption with Passphrase
If the SignerEncryptionPhrase
configuration value is set, the plugin encrypts signer files (Signer_v2
) using AES with a PBKDF2-derived key and IV. The encrypted data includes a prepended salt and IV to support cross-platform decryption.
[Salt (16 bytes)] [IV (16 bytes)] [AES-CBC encrypted signer JSON]
The encryption ensures that even if the account files are accessed on disk, the private keys remain unreadable without the configured passphrase.
🔗 External Account Binding (EAB)
For ACME providers requiring EAB (e.g., ZeroSSL, Google CAS), the gateway constructs a manually signed JWS payload containing:
- Protected Header:
alg
,kid
,url
- Payload: Public JWK of the account signer
- Signature: HMAC using
eabHmacKey
This JWS is included during account creation to bind the account to the pre-provisioned identity provided by the CA.
⚙️ Algorithm Support
- Signers support
ES256
,ES384
,ES512
(ECDSA) andRS256
,RS384
,RS512
(RSA) - EAB HMAC support includes
HS256
,HS384
,HS512
If ES256
key generation fails (e.g., due to platform constraints), the system automatically falls back to RS256
.
On startup or during enrollment/sync, the plugin:
- Attempts to load a cached account for the specified ACME directory.
- If no account is found, it automatically creates a new one, using EAB if configured.
- The new account is saved to disk and set as default for future use.
🔗 External Account Binding (EAB)
For ACME providers requiring EAB (e.g., ZeroSSL, Google CAS), the gateway constructs a manually signed JWS payload containing:
- Protected Header:
alg
,kid
,url
- Payload: Public JWK of the account signer
- Signature: HMAC using
eabHmacKey
This JWS is included during account creation to bind the account to the pre-provisioned identity provided by the CA.
🔧 Algorithm Support
- Signers support
ES256
,ES384
,ES512
(ECDSA) andRS256
,RS384
,RS512
(RSA) - EAB HMAC support includes
HS256
,HS384
,HS512
If ES256
key generation fails (e.g., due to platform constraints), the system automatically falls back to RS256
.
This section outlines all required ports, file access, permissions, and validation behaviors for operating the ACME Gateway Plugin in a Keyfactor Orchestrator environment.
🔌 Port Usage
- None. This plugin does not expose any HTTP or network listeners.
Protocol | Port | Target | Purpose |
---|---|---|---|
HTTPS | 443 | ACME Directory URL | Connect to the ACME CA for account, challenge, and certificate operations |
HTTPS | 443 | DNS Provider APIs | Used for DNS-01 challenge automation (Google DNS, AWS, etc.) |
💾 File System Requirements
Path | Purpose |
---|---|
%APPDATA%\AcmeAccounts\ |
Default base path for ACME account storage |
AcmeAccounts\{account_id}\Registration_v2 |
Contains serialized ACME account metadata |
AcmeAccounts\{account_id}\Signer_v2 |
Contains the encrypted private signer key |
AcmeAccounts\default_{host}.txt |
Stores the default account pointer for a given directory |
Path | Operation | Required Permission |
---|---|---|
Account directory | Create | Write |
Account files | Read/Write | Read , Write |
- Files may be optionally encrypted using AES if a passphrase is configured.
- Ensure the service account under which the orchestrator runs has read/write access to
%APPDATA%
or the custom configured base path.
👤 Windows Account Permissions
- The orchestrator service account (usually
NT AUTHORITY\SYSTEM
or a customNetwork Service
) must have:- File I/O permissions to read/write within the configured base directory.
- Network access to ACME CA endpoints and DNS APIs over HTTPS.
- DNS provider credentials (Cloudflare API token, Google credentials, etc.) stored securely.
🌐 DNS Propagation Check Behavior
-
Initial Release Behavior:
- DNS challenge propagation is checked during the interactive enrollment phase only.
- If propagation takes too long (> 60s), the request will fail. No deferred background polling occurs.
- There is no offline retry mechanism (e.g., for sync jobs) to pick up completed validations that succeeded after a delay.
-
Future Considerations:
- Support for file-based or database-backed challenge persistence may be added to allow background sync to re-check and finalize challenge state.
-
Install the AnyCA Gateway REST per the official Keyfactor documentation.
-
On the server hosting the AnyCA Gateway REST, download and unzip the latest Acme AnyCA Gateway REST plugin from GitHub.
-
Copy the unzipped directory (usually called
net6.0
ornet8.0
) to the Extensions directory:Depending on your AnyCA Gateway REST version, copy the unzipped directory to one of the following locations: Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net6.0\Extensions Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions
The directory containing the Acme AnyCA Gateway REST plugin DLLs (
net6.0
ornet8.0
) can be named anything, as long as it is unique within theExtensions
directory. -
Restart the AnyCA Gateway REST service.
-
Navigate to the AnyCA Gateway REST portal and verify that the Gateway recognizes the Acme plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal.
-
Follow the official AnyCA Gateway REST documentation to define a new Certificate Authority, and use the notes below to configure the Gateway Registration and CA Connection tabs:
-
Gateway Registration
Each ACME CA issues certificates that chain to a specific intermediate and root certificate. For trust validation and proper integration with the Keyfactor Gateway, the following steps are required for every ACME CA used in your environment.
Here is how to obtain the root and intermediate CA certificates from supported ACME providers:
- Root: ISRG Root X1
- Intermediate: R3
How to Get:
- Browse to: https://letsencrypt.org/certificates/
- Download both the ISRG Root X1 and R3 Intermediate Certificate (PEM format).
- Root and Intermediate are custom per CA Pool.
How to Get:
- In the Google Cloud Console, navigate to your CA pool.
- Click the CA name and go to the Certificates tab.
- Download the root and intermediate certificates for the issuing CA in PEM format.
- Root: USERTrust RSA Certification Authority
- Intermediate: ZeroSSL RSA Domain Secure Site CA
How to Get:
- Visit: https://zerossl.com
- Download the full certificate chain in PEM format.
- Extract individual certs if needed using OpenSSL or a text editor.
- Root: Buypass Class 3 Root CA
- Intermediate: Buypass Class 3 CA 1 / G2 (depends on issuance)
How to Get:
- Go to: https://www.buypass.com
- Download both root and intermediate in PEM or DER format.
Once downloaded, the root and intermediate certificates must be installed in the proper Windows certificate stores on the Gateway server.
- Open
certlm.msc
(Local Computer Certificates) - Install the Root CA certificate into:
Trusted Root Certification Authorities
→Certificates
- Install the Intermediate CA certificate into:
Intermediate Certification Authorities
→Certificates
You can import certificates using the GUI or PowerShell:
Import-Certificate -FilePath "C:\path\to\intermediate.crt" -CertStoreLocation "Cert:\LocalMachine\CA" Import-Certificate -FilePath "C:\path\to\root.crt" -CertStoreLocation "Cert:\LocalMachine\Root"
When registering a new CA in Keyfactor Command:
- You must specify the thumbprint of the Intermediate CA certificate.
- This is used to associate issued certificates with the correct issuing chain.
How to Get the Thumbprint:
- In
certlm.msc
, open the certificate under Intermediate Certification Authorities. - Go to Details tab → Scroll to Thumbprint.
- Copy the hex string (ignore spaces).
⚠️ All certificate chains must be trusted by the Gateway OS. If the intermediate is missing or untrusted, issuance will fail or returned certificates may not chain properly. -
CA Connection
Populate using the configuration fields collected in the requirements section.
- DirectoryUrl - ACME directory URL (e.g. Let's Encrypt, ZeroSSL, etc.)
- Email - Email for ACME account registration.
- EabKid - External Account Binding Key ID (optional)
- EabHmacKey - External Account Binding HMAC key (optional)
- SignerEncryptionPhrase - Used to encrypt singer information when account is saved to disk (optional)
- DnsProvider - DNS Provider to use for ACME DNS-01 challenges (options Google, Cloudflare, AwsRoute53, Azure, Ns1)
- Google_ServiceAccountKeyPath - Google Cloud DNS: Path to service account JSON key file only if using Google DNS (Optional)
- Google_ProjectId - Google Cloud DNS: Project ID only if using Google DNS (Optional)
- Cloudflare_ApiToken - Cloudflare DNS: API Token only if using Cloudflare DNS (Optional)
- Azure_ClientId - Azure DNS: ClientId only if using Azure DNS and Not Managed Itentity in Azure (Optional)
- Azure_ClientSecret - Azure DNS: ClientSecret only if using Azure DNS and Not Managed Itentity in Azure (Optional)
- Azure_SubscriptionId - Azure DNS: SubscriptionId only if using Azure DNS and Not Managed Itentity in Azure (Optional)
- Azure_TenantId - Azure DNS: TenantId only if using Azure DNS and Not Managed Itentity in Azure (Optional)
- AwsRoute53_AccessKey - Aws DNS: Access Key only if not using AWS DNS and default AWS Chain Creds on AWS (Optional)
- AwsRoute53_SecretKey - Aws DNS: Secret Key only if using AWS DNS and not using default AWS Chain Creds on AWS (Optional)
- Ns1_ApiKey - Ns1 DNS: Api Key only if Using Ns1 DNS (Optional)
-
-
Define Certificate Profiles and Certificate Templates for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The Acme plugin supports the following product IDs:
- default
-
Follow the official Keyfactor documentation to add each defined Certificate Authority to Keyfactor Command and import the newly defined Certificate Templates.
The Acme AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 24.2 and later.
Apache License 2.0, see LICENSE.
See all Keyfactor Any CA Gateways (REST).