← All work

PKI · Active Directory · Discovery

Consolidating certificate authorities and domain controllers

The work was scoped as moving a certificate authority onto an AWS-hosted domain controller. A read-only discovery script showed the AWS host was already running the production CA, which turned the job into retiring a redundant one. Alongside it, four domain controllers came down to two, under a rule that no new servers could be added.

Role
Sole hands-on engineer across three workstreams
Team
Four
Duration
About 3.5 months of active execution
Status
Executed
2 → 1
Enterprise root CAs, consolidated onto the de facto production issuer
measured
4 → 2
Domain controllers, with only the two AWS-hosted controllers surviving
measured
2 on 1
The retiring CA’s whole live dependency: two certificates on one host
measured
4
Consumers found for a certificate the standard listing showed as unbound
measured
4096-bit
Replacement certificate, enrolled with certreq from an INF template with a proper SAN
measured
Not measured
Dollars saved. Four servers retired, but no cost baseline existed at kickoff
not measured

Constraint

Only the two AWS domain controllers could survive, and every role displaced by a decommission had to land on a host that already existed. Where the constraint created risk, the risk was named explicitly instead of designed around.

Discovery

I wrote a read-only PowerShell discovery script covering forest and controller inventory, per-CA configuration snapshots, full issued-certificate dumps, an audit of the directory’s PKI objects, and an autoenrollment scan, then ran it once.

The AWS survivor was already running a production CA and had been issuing domain controller certificates for years. There was nothing to migrate. The plan changed from migrating the source CA to retiring it and consolidating onto the de facto production issuer, which took an entire backup-and-restore CA migration off the critical path.

Blast radius

Instead of assuming a long certificate tail, I dumped every certificate the retiring CA had ever issued and filtered to what was still valid. The whole production dependency came to two certificates on one host: a remote desktop gateway and connection broker.

Certificate still in use

The standard HTTP SSL binding listing showed one legacy certificate as bound to nothing, which looked like clearance to delete it. RDP doesn’t go through the HTTP stack, so its listener binding never appears in that listing. A WMI query against the terminal services settings class showed the certificate actively serving TLS on an administrative access path, with three more consumers behind it.

Deleting on the first reading would have broken remote access to the gateway.

The replacement was a 4096-bit certificate enrolled with certreq from an INF template, with a proper SAN, repointed to all four consumers: the RDP listener binding (set through WMI), the RD Redirector and RD Publishing role certificates, and a domain-root GPO pinning trusted .rdp publisher thumbprints. The GPO carried the old and new thumbprints side by side through the transition so no client lost trust mid-flight. Old certificates were exported to a rollback location before deletion, not after.

Key decision

Keep the CA where it was, or split the roles across both survivors?

  • ChosenLeave the CA on the primary survivor
    Concentrates certificate issuance and every FSMO role on one instance.
  • Restore the CA onto the secondary
    Spreads the roles, but puts a full CA migration, with its own key-handling and trust-chain risk, on the critical path.

Why

Consolidating onto the surviving issuer concentrated PKI and directory roles. Splitting them would have put a full CA migration on the critical path, introducing more near-term risk than it removed.

Condition attached

Recoverability had to be proven before the concentration became real, so I sequenced the CA backup-and-restore runbook ahead of the gate that creates the single point of failure.

The print queues moved off two decommissioning servers with their drivers intact. Every queue was staged on the new host alongside the existing mappings, and an acceptance wave tested it before anything was removed.

  • Item-level targeting survives a GPO copy. Adding a UAT group to security filtering doesn’t override targeting set inside each preference item, so UAT users would have received nothing and the migration would have looked broken for the wrong reason.
  • “Set as default” has to come off the copy. Otherwise two policies fight over the default printer and it flaps on every refresh.
  • Before UAT, I enumerated every mapping mechanism: preference items, logon scripts, and live SMB sessions. Clean scripts and zero active sessions showed the mapping surface was entirely policy-driven.
  • A line-of-business application stored default printers by full UNC path, so exact queue-name parity became a gating check before removal.

What broke

  • Template command that replaced the published list

    Passing a bare template name to the CA’s template-set operation replaces the whole published list instead of appending to it.

    FixAlways use the append prefix, and list published templates before and after.

  • Expected encryption-test failure on a signing key

    A certificate dump reports the encryption test as failed for a CA signing key. That is expected for a signature-only key, and easy to misread as a broken backup.

    FixDocumented in the recovery runbook, so nobody loses an hour chasing it.

  • Static addressing on EC2

    An address set statically inside the OS survives only until the next instance change.

    FixThe network interface is the source of truth for addressing on EC2.

  • Cmdlet parameters that vary by build

    The thumbprint parameter for setting RDS role certificates didn’t exist on this build.

    FixExport to PFX and import by path, and verify against the actual host instead of the docs.

Process lessons

  • Use group-based targeting from the start, not per-user exception lists.
  • Agree on the counting axis before status reporting. Counting by server and counting by user role were both accurate, and they never matched.
  • Name the rollback boundary before execution, not during it.
  • Written retention and legal-hold confirmation is its own gate before any destruction step.
  • Capture the operational baseline at kickoff. Ten minutes on day one would have turned four retired servers into a provable number.

Stack

  • AD DS
  • AD CS (enterprise root)
  • certutil
  • certreq
  • Backup-CARoleService
  • FSMO, Global Catalog, Sites and Services
  • Group Policy and Preferences
  • RD Gateway and Connection Broker
  • PrintBRM
  • EC2
  • Amazon Time Sync
  • PowerShell 5.1

Organizations, people, dates, and identifying environment details are omitted or generalized. Each figure carries a tag for the kind of evidence behind it.