Automated TLS certificate lifecycle management for Cisco Unified Communications and Expressway platforms.
Issues free, trusted certificates from Let's Encrypt and deploys them to CUCM, IM&P, Unity Connection, Emergency Responder, and Expressway — fully unattended.
TLS certificate lifetimes are getting shorter. The CA/Browser Forum has voted to reduce maximum certificate lifetimes to 47 days by 2029. Let's Encrypt already issues 90-day certificates. Managing these manually across a Cisco UC environment — where each product cluster (CUCM, IM&P, Unity Connection, CER) requires its own certificate with device-generated CSRs, and Expressway needs SSH-based deployment — becomes an unsustainable operational burden.
CiscoCertificates eliminates this problem entirely. Configure it once, schedule it as a Windows Task, and certificates are renewed and deployed automatically before they expire.
This project contains two tools:
The core automation engine that handles the complete certificate lifecycle:
- Issues trusted certificates from Let's Encrypt via ACME DNS-01 validation
- Deploys to Cisco UC servers (CUCM, IM&P, Unity Connection, CER) using the platformcom REST API
- Deploys to Cisco Expressway via SSH/SFTP
- Installs the Let's Encrypt CA trust chain on UC devices
- Restarts affected services (e.g., Cisco Tomcat) automatically via SSH
- Verifies deployment by reading certificates back from each node and via TLS probing
- Tracks state so failed deployments are retried without re-issuing certificates
- Notifies via email on success or failure
A Windows desktop application (WPF) for editing the automation configuration file (appsettings.json) without touching JSON directly. Features a modern Fluent UI with dedicated pages for each configuration section: ACME settings, DNS provider, UC nodes, Expressway nodes, certificate jobs, notifications, and general automation settings.
| Product | Minimum Version | Deployment Method |
|---|---|---|
| Cisco Unified Communications Manager (CUCM) | 14.0 | REST API (device CSR) |
| Cisco IM&P (CUPS) | 14.0 | REST API (device CSR) |
| Cisco Unity Connection (CUC) | 14.0 | REST API (device CSR) |
| Cisco Emergency Responder (CER) | 14.0 | REST API (device CSR) |
| Cisco Expressway (E/C) | X14 | SSH/SFTP |
ACME DNS-01 validation requires creating temporary DNS TXT records. The following providers are supported natively:
- Cloudflare — Native API integration
- Amazon Route 53 — AWS SDK integration
- Azure DNS — Azure SDK integration
- Google Cloud DNS — Google API integration
- DigitalOcean — API integration
- Custom Script — PowerShell script interface for any other DNS provider
- Windows 10/11 or Windows Server 2016+ (x64)
- .NET 8.0 Desktop Runtime (Windows x64)
- Outbound HTTPS access to Let's Encrypt and your DNS provider API
- HTTPS (port 443) and SSH (port 22) access to each Cisco device
- Cisco UC version 14.0 or newer (required for the platformcom REST API)
- An API token for your DNS provider (or custom PowerShell scripts)
-
Download CiscoCertificates-v1.0-Release.zip and extract to a folder (e.g.,
C:\CiscoCertAutomation) -
Configure — Open
appsettings.jsonin the Config Editor or a text editor:- Set your ACME contact email and DNS provider credentials
- Define all UC and Expressway node hostnames and admin credentials
- Create certificate jobs (one per product cluster)
- Configure notification settings (optional)
-
Validate access — Run the API preflight check:
CiscoCertificates.Automation.exe --api-preflight -
Check current state — Run a status report:
CiscoCertificates.Automation.exe --status-report -
Deploy certificates — Run production mode:
CiscoCertificates.Automation.exe --production -
Schedule — Create a daily Windows Scheduled Task pointing to the executable with
--production
See the Administration Guide for a detailed first-run walkthrough including testing steps using Let's Encrypt's staging server.
The Config Editor provides a visual interface for managing appsettings.json. Launch CiscoCertificates.ConfigEditor.exe and use File > Open to load your configuration, or File > New to start fresh.
The editor has seven pages accessible from the sidebar:
| Page | Purpose |
|---|---|
| ACME Settings | Let's Encrypt account email, ACME provider selection (Production, Staging, ZeroSSL, Custom), account key path, and polling/timing settings |
| DNS Provider | Select and configure your DNS provider (Cloudflare, Route 53, Azure, DigitalOcean, Google Cloud, or Custom Script) |
| UC Nodes | Define all Cisco UC servers — hostname, product type, cluster role (publisher/subscriber), cluster group, and credentials |
| Expressway | Define Expressway nodes — hostname, SSH/TLS ports, credentials, and SSH command templates |
| Jobs | Certificate jobs — common name, SANs, key algorithm, device CSR settings, deployment targets, trust chain options, and EKU requirements |
| Notifications | SMTP server settings, recipients, authentication, and success/failure notification preferences |
| General | Renewal window, parallelism, state tracking, HTTP timeouts, replication verification, and service restart settings |
Changes are tracked with an unsaved-changes indicator. Save with Ctrl+S.
CiscoCertificates.Automation.exe [mode] [options]
Exactly one mode is required (mutually exclusive):
| Mode | Aliases | Description | Makes Changes? |
|---|---|---|---|
--production |
--prod |
Checks each certificate and renews/deploys when within the renewal window. | Yes |
--status-report |
--status, --report, --report-only |
Reports current certificate status on all targets. Sends a summary email. | No |
--issue-only |
--issue, --acme-only |
Forces ACME issuance without deploying to devices. Saves certs locally. | Partial (DNS only) |
--api-preflight |
--preflight, --validate-api |
Tests API/SSH connectivity and authentication to all configured targets. | No |
--cleanup-dns |
--cleanup |
Removes stale _acme-challenge TXT records from the DNS provider. |
Partial (DNS only) |
You can also specify a mode using --mode <value> or --mode=<value> syntax (e.g., --mode production).
These can be combined with any mode:
| Option | Aliases | Description |
|---|---|---|
--dry-run |
--dryrun |
Issues from ACME and validates the certificate and trust stores, but skips deployment to devices. Can also be used standalone without a mode. |
--restart |
--allow-restart |
Allows automatic UC service restarts (e.g., Cisco Tomcat) after certificate deployment. Without this flag, certificates are deployed but services are not restarted. |
--name <job> |
--job <job> |
Runs only the specified job by name (e.g., --name cucm-tomcat). Without this, all configured jobs are processed. |
--help |
-h, /? |
Displays help text and exits. |
Any argument in the format --Section:Key=Value is passed to the .NET configuration system:
CiscoCertificates.Automation.exe --production --Logging:LogLevel:Default=Debug
CiscoCertificates.Automation.exe --production --Acme:DnsPropagationWaitSeconds=120
| Code | Meaning |
|---|---|
| 0 | All jobs completed successfully |
| 1 | Invalid command-line arguments |
| 2 | One or more jobs failed |
| 3 | Another instance is already running (mutex) |
| 4 | Jobs succeeded but notification email failed |
For standalone Cisco devices (no cluster), configure one UC node entry with ClusterRole: "publisher" and one certificate job targeting that node. No replication verification is needed.
For Cisco UC clusters, the automation follows the publisher-first model:
- The publisher generates a CSR that includes all cluster node hostnames (when
CsrDistribution: "multi-server") - The certificate is issued and uploaded to the publisher only
- Cisco's internal database replication distributes the certificate to all subscribers
- The automation polls each subscriber to verify replication completed
- Services are restarted on the publisher first, then each subscriber
You must define all nodes in the cluster (publisher and subscribers) as UC nodes, but the certificate job targets only the publisher. Subscribers are automatically discovered by matching ClusterGroup.
Important: IM&P (CUPS) certificates typically require additional Subject Alternative Names beyond the CUPS server hostnames. The CUPS Tomcat certificate usually needs to include the CUCM publisher and subscriber FQDNs as well, because IM&P services reference CUCM for user lookups and presence routing.
Example CUPS job SANs:
"SubjectAlternativeNames": [
"cups-pub.example.com",
"cups-sub1.example.com",
"cucm-pub.example.com",
"cucm-sub1.example.com"
]If you omit the CUCM FQDNs from the CUPS certificate, you may see certificate trust warnings in Jabber clients or IM&P service logs related to CUCM connectivity. Check your existing CUPS certificate's SAN list before configuring the job to ensure you include all required hostnames.
Expressway uses a different model — it accepts externally-generated private keys:
- The automation generates a key pair and CSR locally
- Let's Encrypt signs the CSR
- The certificate and private key are uploaded via SFTP
- An SSH command installs the certificate
- Temporary files are cleaned up and a TLS probe verifies the new certificate is active
Set UseDeviceCsr: false for all Expressway jobs.
As of February 11, 2026, Let's Encrypt stopped including the Client Authentication Extended Key Usage (EKU) by default. Some Cisco UC scenarios depend on mutual TLS and may require the clientAuth EKU.
Each certificate job supports RequiredEnhancedKeyUsages and FailIfRequiredEkuMissing settings to validate EKU compliance before deployment.
See: Let's Encrypt announcement | Cisco Field Notice FN74362
| Package | Contents |
|---|---|
| CiscoCertificates-v1.0-Release.zip | Production-ready binaries (Automation CLI + Config Editor GUI) |
CiscoCertificates.Automation.exe — Automation engine (CLI)
CiscoCertificates.ConfigEditor.exe — Configuration editor (GUI)
appsettings.json — Configuration template (edit for your environment)
scripts/
dns-present.ps1 — DNS TXT record creation (for custom DNS providers)
dns-cleanup.ps1 — DNS TXT record cleanup (for custom DNS providers)
Help.html — Complete administration guide
Requires the .NET 8.0 SDK (Windows x64).
# Build both projects
dotnet build CiscoCertificates.slnx
# Publish release builds
dotnet publish src/CiscoCertificates.Automation/CiscoCertificates.Automation.csproj -c Release -o .\out
dotnet publish src/CiscoCertificates.ConfigEditor/CiscoCertificates.ConfigEditor.csproj -c Release -o .\outThe complete Administration Guide covers:
- Detailed first-run walkthrough (7-step validation process)
- Using the Configuration Editor GUI
- Full configuration reference for every setting
- Task Scheduler setup for automated renewal
- State management and recovery procedures
- Troubleshooting guide
Create a daily Windows Scheduled Task:
| Field | Value |
|---|---|
| Program | C:\CiscoCertAutomation\CiscoCertificates.Automation.exe |
| Arguments | --production |
| Start in | C:\CiscoCertAutomation |
| Trigger | Daily at 2:00 AM |
| Run as | Service account with network access to Cisco devices |
| Run whether user is logged on or not | Yes |
Let's Encrypt certificates last 90 days. With RenewBeforeDays: 30, the app starts renewing at day 60, giving you 30 days of automatic retries if something goes wrong.
Optionally, create a second task for a weekly status report using --status-report to get a summary email of all certificate statuses.
