← Week 2: ACM Private CA — architecture + API

Day 13: Audit Logging — CloudTrail + ACM PCA Audit Reports

Phase 5 · September 7, 2026

← Week 2: ACM Private CA — architecture + API

Agenda (2–3 hours)

  • Read (45 min): ACM PCA User Guide — "Using CloudTrail"; "Creating an audit report"
  • Study (60 min): What events are logged, what fields matter, what's not logged
  • Write (45 min): Audit logging design for your provisioning service
← Week 2: ACM Private CA — architecture + API

Why Audit Logging Matters for a CA

A CA is a trust anchor. Every certificate it issues is a claim:
"I, the CA, attest that this entity holds this key."

If a CA is compromised or misused, you need to answer:

  • Who issued which certificate?
  • When was it issued?
  • What was in the CSR?
  • Was it authorized by the right provisioning service?

Without audit logging, you cannot answer these questions after the fact.

← Week 2: ACM Private CA — architecture + API

CloudTrail: API-Level Logging

AWS CloudTrail records every ACM PCA API call:

Event What it captures
IssueCertificate Caller identity, CA ARN, validity, template ARN, idempotency token
RevokeCertificate Caller identity, CA ARN, serial number, reason
CreateCertificateAuthority CA configuration
GetCertificate CA ARN, cert ARN (not the cert content)
DeleteCertificateAuthority CA ARN, deletion date

What CloudTrail does NOT capture:

  • The CSR contents (PII/business data)
  • The issued certificate itself
  • The private key (obviously)
← Week 2: ACM Private CA — architecture + API

CloudTrail Event: IssueCertificate

Example CloudTrail record:

{
  "eventSource": "acm-pca.amazonaws.com",
  "eventName": "IssueCertificate",
  "userIdentity": {
    "arn": "arn:aws:iam::123456789012:role/provisioning-service-role"
  },
  "requestParameters": {
    "certificateAuthorityArn": "arn:aws:acm-pca:us-east-1:....",
    "templateArn": "arn:aws:acm-pca:::template/EndEntityCertificate/V1",
    "validity": { "value": 90, "type": "DAYS" },
    "idempotencyToken": "device-SN-12345-20260906"
  },
  "responseElements": {
    "certificateArn": "arn:aws:acm-pca:us-east-1:...:certificate/abc123"
  },
  "sourceIPAddress": "10.0.1.45"
}

This tells you: the provisioning Lambda issued a cert for device SN-12345 on Sep 6.

← Week 2: ACM Private CA — architecture + API

ACM PCA Audit Reports

For more detail than CloudTrail, ACM PCA can generate audit reports:

use aws_sdk_acmpca::types::AuditReportResponseFormat;

client
    .create_certificate_authority_audit_report()
    .certificate_authority_arn(ca_arn)
    .s3_bucket_name("my-acmpca-audit-bucket")
    .audit_report_response_format(AuditReportResponseFormat::Json)
    .send()
    .await?;

The audit report is a JSON/CSV file in S3 containing:

  • All certificates ever issued by this CA
  • Serial number, subject, SAN, validity, issued timestamp
  • Whether the cert has been revoked (and reason/timestamp)

This is your certificate inventory — essential for incident response.

← Week 2: ACM Private CA — architecture + API

Audit Report vs. CloudTrail

CloudTrail ACM PCA Audit Report
Granularity Per API call Per issued certificate
Content API params (not cert body) Cert details (serial, subject, SAN)
Timing Real-time On-demand (generate when needed)
Retention Configurable (90 days default) S3 (indefinite)
Cost CloudTrail pricing S3 storage + API call
Use case Who called what API Which certs are active/revoked

For incident response: use CloudTrail to find unauthorized issuance calls,
use Audit Report to find which certs were issued and need revocation.

← Week 2: ACM Private CA — architecture + API

Building an Audit Pipeline

For a production provisioning service, you want:

ACM PCA IssueCertificate call
    │
    ├── CloudTrail → CloudWatch Logs → Alarm on unauthorized issuer
    │
    └── Your provisioning service:
        - Writes (device_id, cert_serial, issued_at, expires_at) to DynamoDB
        - This is your authoritative certificate inventory
        - CloudTrail is the audit trail for compliance

Periodic:
    - Generate ACM PCA Audit Report weekly → diff against DynamoDB inventory
    - Flag any certs in audit report that are NOT in your DynamoDB
      (indicates unauthorized issuance outside your provisioning service)
← Week 2: ACM Private CA — architecture + API

IAM Policies for Audit Access

{
  "Effect": "Allow",
  "Action": [
    "acm-pca:CreateCertificateAuthorityAuditReport",
    "acm-pca:DescribeCertificateAuthorityAuditReport"
  ],
  "Resource": "arn:aws:acm-pca:us-east-1:*:certificate-authority/*"
}

Separate the issuance role (can call IssueCertificate) from the
audit role (can generate audit reports). These should be different IAM roles
so that a compromised provisioning service cannot delete audit evidence.

← Week 2: ACM Private CA — architecture + API

Challenge Assignment

Design the audit logging architecture for acm-pca-design.md §4.2:

### 4.5 Audit Logging

**CloudTrail configuration:**
- What trail? (multi-region? dedicated S3 bucket?)
- What CloudWatch alarm triggers on an unauthorized `IssueCertificate` caller?

**DynamoDB certificate inventory:**
- Table design: partition key, sort key, attributes
- (device_id, cert_serial, issued_at, expires_at, revoked_at, ca_arn)

**Audit report schedule:**
- When generated (weekly? monthly?)
- What automated check compares the audit report to DynamoDB?
- What happens when a discrepancy is found?

**Incident response runbook (sketch):**
- Alert fired: unauthorized IssueCertificate call detected
- Steps: identify caller → generate audit report → revoke unauthorized certs → rotate compromised IAM credentials
← Week 2: ACM Private CA — architecture + API

Resources

  • ACM PCA CloudTrail events: docs.aws.amazon.com/privateca/latest/userguide/PcaCtIntro.html
  • ACM PCA audit reports: docs.aws.amazon.com/privateca/latest/userguide/PcaAuditReport.html
  • CreateCertificateAuthorityAuditReport API: docs.aws.amazon.com/privateca/latest/APIReference/API_CreateCertificateAuthorityAuditReport.html
  • CloudWatch Logs Insights: docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html