TheArchitect

Secrets Rotation & Compliance Audit

AWS architecture template · Zero hardcoded credentials: EC2 fetches DB credentials from Secrets Manager with automatic 30-day rotation. CloudTrail captures every API call to an immutable S3 audit bucket.

Secrets Rotation & Compliance Audit is a free AWS architecture template built with CloudTrail, CloudWatch, EC2, IAM, KMS, Lambda, RDS, S3 and Secrets Manager. Open it in TheArchitect to edit the diagram, estimate monthly cost, and export the CloudFormation or Terraform that deploys it.

App ServerCustomer DBDB CredentialsRotation Funct…Data CMKCompliance Tra…Audit BucketRotation Failu…Rotation Role
Secrets Rotation & Compliance Audit architecture diagram

AWS services in this template

  • CloudTrail
  • CloudWatch
  • EC2
  • IAM
  • KMS
  • Lambda
  • RDS
  • S3
  • Secrets Manager

Deployment notes

Needs input

  • Set RDS endpoint in Secrets Manager rotation Lambda environment variable.
  • Grant Secrets Manager permission to invoke the rotation Lambda.
  • Create S3 bucket policy granting CloudTrail delivery access.

Generated CloudFormation — 9 resources

Logical IDResource type
AppServerec2AWS::EC2::Instance
CustomerDBrdsAWS::RDS::DBInstance
DBCredentialssecretsmanagerAWS::SecretsManager::Secret
RotationFunctionlambdaAWS::Lambda::Function
DataCMKkmsAWS::KMS::Key
ComplianceTrailcloudtrailAWS::CloudTrail::Trail
AuditBuckets3AWS::S3::Bucket
RotationFailureAlarmcloudwatchAWS::CloudWatch::Alarm
RotationRoleiamAWS::IAM::Role
View the full CloudFormation template
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Generated by TheArchitect — https://www.thecloudarchitect.dev",
  "Metadata": {
    "TheArchitect": {
      "Edges": [
        {
          "From": "AppServerec2",
          "To": "CustomerDBrds",
          "Label": "SQL over TLS"
        },
        {
          "From": "RotationFunctionlambda",
          "To": "CustomerDBrds",
          "Label": "ALTER USER"
        },
        {
          "From": "DataCMKkms",
          "To": "DBCredentialssecretsmanager",
          "Label": "encrypts secret"
        },
        {
          "From": "DataCMKkms",
          "To": "CustomerDBrds",
          "Label": "encrypts storage"
        },
        {
          "From": "ComplianceTrailcloudtrail",
          "To": "AuditBuckets3",
          "Label": "log delivery"
        },
        {
          "From": "RotationFunctionlambda",
          "To": "RotationFailureAlarmcloudwatch",
          "Label": "error metric"
        },
        {
          "From": "RotationRoleiam",
          "To": "RotationFunctionlambda",
          "Label": "execution role"
        }
      ]
    }
  },
  "Resources": {
    "AppServerec2": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "ImageId": "ami-0abcdef1234567890",
        "InstanceType": "t3.small",
        "DisableApiTermination": false
      }
    },
    "CustomerDBrds": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "DBInstanceIdentifier": "compliance-db",
        "Engine": "postgres",
        "EngineVersion": "15.4",
        "DBInstanceClass": "db.t3.medium",
        "MultiAZ": false,
        "AllocatedStorage": "20",
        "StorageType": "gp3",
        "StorageEncrypted": true,
        "DeletionProtection": true,
        "BackupRetentionPeriod": 7
      }
    },
    "DBCredentialssecretsmanager": {
      "Type": "AWS::SecretsManager::Secret",
      "Properties": {
        "Name": "compliance/db-credentials",
        "Description": "RDS PostgreSQL credentials rotated every 30 days by rotation Lambda",
        "GenerateSecretString": {
          "PasswordLength": 32,
          "ExcludeCharacters": "\"@/\\"
        }
      }
    },
    "RotationFunctionlambda": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": [
        "RotationRoleiam"
      ],
      "Properties": {
        "FunctionName": "db-credentials-rotation",
        "Runtime": "python3.12",
        "Handler": "rotation.handler",
        "MemorySize": 256,
        "Timeout": 120,
        "Description": "Secrets Manager rotation function. Implements the four-step rotation: createSecret, setSecret (ALTER USER in RDS), testSecret, finishSecret.",
        "Role": {
          "Fn::GetAtt": [
            "RotationRoleiam",
            "Arn"
          ]
        }
      }
    },
    "DataCMKkms": {
      "Type": "AWS::KMS::Key",
      "Properties": {
        "Description": "Data CMK — encrypts RDS storage and Secrets Manager secret value",
        "EnableKeyRotation": true,
        "Enabled": true,
        "PendingWindowInDays": 30
      }
    },
    "ComplianceTrailcloudtrail": {
      "Type": "AWS::CloudTrail::Trail",
      "Properties": {
        "TrailName": "compliance-audit-trail",
        "S3BucketName": "compliance-audit-logs",
        "IsLogging": true,
        "IsMultiRegionTrail": true,
        "EnableLogFileValidation": true,
        "IncludeGlobalServiceEvents": true
      }
    },
    "AuditBuckets3": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "BucketName": "compliance-audit-logs",
        "VersioningConfiguration": {
          "Status": "Enabled"
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "ObjectLockEnabled": true,
        "ObjectLockConfiguration": {
          "ObjectLockEnabled": "Enabled"
        }
      }
    },
    "RotationFailureAlarmcloudwatch": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmName": "secrets-rotation-failure",
        "AlarmDescription": "Rotation Lambda error — DB credentials may be stale. Investigate immediately.",
        "Namespace": "AWS/Lambda",
        "MetricName": "Errors",
        "Statistic": "Sum",
        "Period": 300,
        "EvaluationPeriods": 1,
        "Threshold": 1,
        "ComparisonOperator": "GreaterThanOrEqualToThreshold",
        "TreatMissingData": "notBreaching"
      }
    },
    "RotationRoleiam": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "RoleName": "secrets-rotation-role",
        "Description": "Lambda execution role for rotation function — SecretsManager + RDS describe + KMS",
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
        ]
      }
    }
  }
}

Generated by TheArchitect from the diagram above. Review values such as names, CIDR ranges and instance sizes before deploying to your account.

Related templates