After years operating internal PKI for financial systems, the question that cost me the most was never "was the certificate issued?", it was "what exactly did my CA sign, for whom, and what did it refuse?". Until last week CloudTrail answered only the first one: the IssueCertificate management event returned an ARN and nothing else. An issuance blocked by name constraints left no record at all. The IssueCertificateDetails event, announced on October 5, 2026, answers the other two. These are my notes on what I would do with it starting tomorrow.
The situation: the gap we used to patch by hand
What existed before: three partial sources. The IssueCertificate management event proved the API call went through and handed back the certificate ARN. The SignCertificate event recorded the signing operation. And the audit report, generated at most every 30 minutes into an S3 bucket, listed serial, subject, validity and revocation. None of the three carried SANs, X.509 extensions or the signing algorithm. To know which DNS names actually went into a certificate, the path was GetCertificate by ARN plus openssl x509 -text, under a default ceiling of 75 calls per second and one hard condition: the CA must still exist. Delete the CA and the certificate is unrecoverable.
Where that breaks: short-lived certificate mode. A CA in that mode costs US$ 50 per month and issues certificates valid for up to 7 days at US$ 0.058 each; it is the right mode for workload-to-workload mTLS. With 20,000 workloads renewing every 3 or 4 days, that is 5,000 to 6,000 issuances a day. Rebuilding the inventory retroactively through GetCertificate becomes a multi-hour job racing against the certificates' own validity. The audit report documentation now says, in plain words, to capture the detail at issuance time on high-volume CAs.
What nobody could see: failure before signing. Wrong template, name constraints violation, malformed CSR: the call failed, the client got an exception and the auditor had no line to look at. Under BACEN or PCI-DSS, a missing record of a denied attempt is an audit finding, not a detail.
Anatomy of the event: what to read and what not to assume
IssueCertificateDetails is a service event (eventType: AwsServiceEvent, managementEvent: true) with eventSource: acm-pca.amazonaws.com. It arrives on its own, no opt-in, in every Region where Private CA exists, and only costs standard CloudTrail pricing. The useful content lives in serviceEventDetails:
-
tbsCertificate: the base64 DER of the to-be-signed certificate, with every field and extension, minus the signature. -
issuerName,issuerSerialNumber,issuerAuthorityKeyIdentifier: which CA signed, useful when you run a hierarchy with several intermediates. -
subject,serialNumber,notBefore,notAfter,issuedAt,templateArn,signingAlgorithm: the convenience fields that will become columns. -
status(ISSUEDorFAILED) andstatusReason, for exampleName Constraints violation: DNS name not found in a permitted subtree. -
requesterAccountIdandrequesterArnfor direct calls, orrequesterServicePrincipal(such asacm.amazonaws.com) when a service or connector asked on your behalf.
Three traps the guide documents and I confirmed: first, the envelope's userIdentity is invokedBy: acm-pca.amazonaws.com, not the caller; filtering by principal in CloudTrail finds nothing, the requester sits inside serviceEventDetails. Second, none of the three requester fields is guaranteed: issuances attributed to an internal AWS process carry none of them. Third, status is never PENDING: the event only fires once issuance reaches a terminal state, and on a failure before the TBS was generated the fields derived from it (tbsCertificate, subject, serialNumber) simply are not there. On a shared CA, the announcement says the event goes to the CA owner account; the user guide says it goes to both owner and requester. When the owner account is the security account, the auditor looks in one place.
From issuance attempt to auditor: where the event travels
Every attempt, accepted or refused, becomes one event that CloudTrail delivers on two paths: near real time through EventBridge, and batch through S3/Athena or CloudTrail Lake.
👤 Solicitantes: quem pede o certificado
- Workload com IAM role sourceIdentity + session tags (user)
- ACM / conectores AD, SCEP, Kubernetes (external)
🟧 AWS: Private CA (conta dona da CA)
- Validação template + name constraints (security)
- Geração do TBS e assinatura (security)
- IssueCertificateDetails status ISSUED | FAILED (messaging)
🟧 AWS: Trilha de auditoria
- CloudTrail (trilha da org) management event, 1ª cópia grátis (data)
- S3 da trilha SSE-KMS + lifecycle (storage)
- CloudTrail Lake US$ 0,75/GB ingerido (storage)
🔐 Consumo: segurança e compliance
- EventBridge regra status = FAILED (messaging)
- Security Hub / SNS alerta de recusa (security)
- Lambda decodificador TBS → SAN, key usage (compute)
- Athena inventário + migração de algoritmo (data)
Flows
- workload -> validate: IssueCertificate
- acm -> validate: issuance on your behalf
- validate -> sign: accepted
- validate -> event: refused: statusReason
- sign -> event: issued: TBS + serial
- event -> trail: automatic delivery
- trail -> s3: log files
- trail -> lake: optional ingestion
- trail -> eb: AWS Service Event via CloudTrail
- eb -> alert: FAILED within minutes
- s3 -> decoder: new object
- decoder -> athena: SAN/algorithm columns
- s3 -> athena: partition projection
Playbook: what to switch on in the first five days
Confirm the organization trail covers the CA account and Region: The event is a management event, so it rides the free first copy of any trail that records management events. Check the trail is multi-Region and that the CA owner account (ideally the security account) is in scope. Without a trail the event only shows in the console's 90-day history, which is useless to an auditor.
Create the EventBridge rule for
status = FAILED: Pattern withsource: aws.acm-pca,detail-type: AWS Service Event via CloudTrail,detail.eventName: IssueCertificateDetailsanddetail.serviceEventDetails.status: FAILED. Targets: the PKI team's SNS topic and a Security Hub finding. A name constraints refusal means either a misconfigured workload or someone probing the CA's limits; both deserve a response in minutes, not in the monthly report.Build the Athena table with partition projection: Use Athena's standard CloudTrail DDL with partition projection by account, Region and date, and filter
eventname = 'IssueCertificateDetails'. The convenience columns (subject,signingalgorithm,templatearn,notafter,requesterarn) come straight out ofserviceeventdetailsas a JSON string. If the organization already runs CloudTrail Lake, the same query runs there at US$ 0.005 per GB scanned.Write the TBS decoder for SAN and key usage: Athena does not parse ASN.1. A Lambda triggered by new objects in the trail bucket decodes
tbsCertificate, pulls outsubjectAltName,keyUsage,extendedKeyUsageand key size, and writes Parquet to an inventory prefix. That is what answers "which certificates carry*.payments.internalin the SAN" without touching the CA API.Propagate the original identity with
sourceIdentityand session tags: When an intermediate service callsIssueCertificatefor a workload,requesterArnis the intermediate's. Make the intermediate assume its role withSetSourceIdentityand session tags carrying the workload identifier;sourceIdentityis immutable across the role chain and shows up in the event. With IAM Roles Anywhere, the client certificate's SAN already becomes a principal tag, such asaws:PrincipalTag/x509SAN/URI.Close retention and encryption on the bucket before the first auditor: The trail bucket now holds the DN and SAN of every certificate, including user certificates issued through the Active Directory connector. SSE-KMS with a customer key, a bucket policy denying reads outside the security account, a lifecycle aligned to the retention your regulation demands. Do it before the event accumulates months of personal data.
A live inventory and algorithm migration without touching the CA
The use case I actually care about: algorithm migration. Every financial PKI I have touched had a mix of SHA256WITHRSA on old certificates and ECDSAWITHSHA256 on new ones, and the only way to measure progress was sampling. The signingAlgorithm field on every event turns that into a query: share of issuances per algorithm per week, per template, per requesting account. When post-quantum cryptography's turn comes, it is the same query with a different value. A CloudWatch alarm on a metric filter counting SHA256WITHRSA issuances after the cutover date is the cheapest control there is for "nobody went back to the old template".
Inventory: the audit report remains the official snapshot (serial, revocation, validity) and remains necessary, because the new event does not cover revocation; RevokeCertificate is a separate management event. But the operational inventory, the one answering "how many certificates expire in the next 72 hours and whose are they", becomes notAfter and requesterArn in a table, refreshed within minutes, with no GetCertificate and no dependency on the CA still existing. Since March 31, 2026 Private CA also publishes to CloudWatch the count of certificates issued per CA and of CAs per Region; use the metric to watch the quota (100 million per CA, or 1 million when the CA uses complete CRLs) and the event to know what makes up that number.
What the event does not solve: certificates issued before October 5, 2026 get no retroactive event. Backfilling those still goes the old way, report plus GetCertificate, and it is the last time you need to run it.
Test the trail with a deliberate refusal: Before declaring the control done, request a certificate with a DNS name outside the intermediate CA's name constraints and confirm three things: the event arrived with
status: FAILEDand a readablestatusReason, the EventBridge rule fired the alert, and the row showed up in the Athena query under that day's partition. A compliance control that has never seen a real failure is a control that will fail on the first one.
Cost, volume and personal data: the math the announcement skips
Trail cost: the first copy of management events is free; additional copies cost US$ 2.00 per 100,000 events. The default IssueCertificate quota is 25 per second per account and Region, adjustable, which caps issuance at roughly 2.16 million a day. In the theoretical worst case a second dedicated trail would cost US$ 43 a day; in practice, at 6,000 daily issuances, it is US$ 0.12. What weighs is what you stack on top: Insights at US$ 0.35 per 100,000 events analyzed and Lake at US$ 0.75 per GB ingested. Assuming about 3 KB per event (the base64 TBS is most of it), 6,000 events a day is 18 MB a day, half a GB a month, cents. It is the badly written query with no partition filter that blows the budget, not the event.
Maintenance cost, which is the one that matters: the TBS decoder is your code. It will break when a new template introduces an extension the parser does not know, and it will break silently unless you count incoming events against output rows. Put that delta on an alarm from day one.
Privacy law and segregation: user certificates issued through the Active Directory connector carry a name and an email in the subject and SAN. The trail bucket becomes, without anyone deciding it, a long-retention repository of personal data. That changes who may read the bucket, requires a dedicated KMS key whose policy denies kms:Decrypt outside the security account, and belongs in the record of processing activities under LGPD. It is not a Private CA problem; it is the consequence of finally having the full content in the log.
Anti-patterns I have watched appear in under a week
-
Filtering CloudTrail by
userIdentity.arnto find the requester: the envelope saysinvokedBy: acm-pca.amazonaws.comon every event; the requester is inserviceEventDetails.requesterArn, and not always there. - Using the event as the trigger for automatic revocation: delivery through CloudTrail and EventBridge is best effort and takes minutes; a control loop that needs guaranteed delivery cannot live on top of it.
- Retiring the audit report: the event covers neither revocation nor the inventory issued before October 5, 2026; the report remains the official snapshot for the auditor.
- Treating the TBS as if it were the issued certificate: it has no signature; it serves inventory and content auditing, not chain validation or distribution to clients.
- Leaving the trail bucket on default encryption after this: user certificate DNs and SANs are personal data; a dedicated KMS key and a restricted read policy stop being optional.
Questions I got this week
Do I need to enable anything on the CA?
No. It is a management event and fires automatically in every Region with Private CA. What you need is a trail recording management events in the CA owner account, which nearly every regulated organization already has.
Does the event replace SignCertificate?
It complements it. SignCertificate still records the signing operation; IssueCertificateDetails adds the TBS content, the convenience metadata and the pre-signing failures, which SignCertificate never saw.
On a CA shared through RAM, who receives the event?
The announcement says the CA owner account; the user guide says owner and requester. Design for the owner: put the CA in the security account and the organization trail covers the rest. If the requester account also receives it, that is a copy, not the source.
How do I extract the SAN if Athena cannot read ASN.1?
Decode tbsCertificate outside Athena: a Python Lambda with cryptography or batch openssl asn1parse, writing SAN, key usage and key size as Parquet columns. Count incoming events against output rows; the parser will break one day and you want to know that same day.
Curator's note: I would switch on the
FAILEDrule tomorrow morning and leave the TBS decoder for week two: the name constraints refusal is the cheapest security signal Private CA has ever offered, and the rich inventory can wait for the backfill of the old estate. The hard-won lesson behind this: in financial PKI the cost was never issuing the certificate, it was proving six months later what was issued and what was denied, and until now that proof was a script of mine runningGetCertificateagainst a 75-per-second quota. Whoever runs a shared CA should make the security account the owner before scaling, because that is where the event lands. And treat the trail bucket as what it has become: a repository of personal data with regulatory retention.
Verdict
Adopt it without hesitation if you run Private CA under BACEN, PCI-DSS or LGPD, use short-lived mode, or have more than one account requesting certificates from the same CA: the EventBridge rule for FAILED, the Athena table and the TBS decoder cost cents per month and return an audit proof that used to require a script and patience. Keep the audit report for revocation and for the estate issued before October 5, 2026. Do not use the event as a trigger for critical action: delivery is best effort and takes minutes. And before any query, settle the KMS key, read policy and retention of the trail bucket, because from now on it holds the full content of every certificate your CA signed.
Rating: Recomendado com condições
References
- AWS What's New: AWS Private CA now provides detailed certificate issuance logs (05/10/2026)
- AWS Private CA User Guide: Logging API calls using CloudTrail (IssueCertificateDetails event reference)
- AWS Private CA User Guide: Use audit reports with your private CA
- AWS General Reference: AWS Private CA endpoints and quotas
- AWS Private CA pricing
- AWS CloudTrail pricing
- Amazon EventBridge: AWS Private Certificate Authority events
- Amazon Athena: Query AWS CloudTrail logs
Originally published at fernando.moretes.com. By Fernando F. Azevedo: Senior Solutions Architect.
Top comments (0)