DevSecOps: Securing Pipelines with AWS KMS and Secrets Manager
In modern cloud-native software delivery, the continuous integration and continuous delivery (CI/CD) pipeline is the crown jewel of an organization's infrastructure. It has direct access to source code, production environments, database schemas, and third-party APIs. Consequently, securing this pipeline is one of the most critical challenges in DevSecOps. Misconfigured pipeline credentials, hardcoded secrets, or over-privileged access keys can lead to catastrophic data breaches and system compromises.
This comprehensive guide dives deep into securing your enterprise CI/CD pipelines using AWS Key Management Service (KMS) and AWS Secrets Manager. We will design and implement a production-grade, zero-trust DevSecOps architecture that ensures secrets are encrypted at rest, in transit, and only decrypted in-memory during runtime execution. We will also cover infrastructure-as-code (IaC) implementation, secret rotation, multi-account security boundaries, and auditing.
What You Will Learn
- The core principles of Envelope Encryption using AWS KMS.
- How to architect a zero-trust credential injection flow for AWS CodePipeline and CodeBuild.
- How to write secure, least-privilege IAM and KMS key policies.
- How to dynamically retrieve secrets in-memory during pipeline runs without leaking them to build logs.
- How to implement automatic secret rotation using AWS Lambda.
- How to configure VPC Endpoints for KMS and Secrets Manager to prevent traffic from traversing the public internet.
- Enterprise troubleshooting, debugging, and audit compliance workflows.
Prerequisites
To get the most out of this masterclass lesson, you should be familiar with:
- Basic AWS identity management (IAM policies, roles, and trust relationships).
- Core CI/CD concepts (pipelines, build stages, and artifacts).
- Basic Terraform or AWS CloudFormation syntax for provisioning resources.
- Shell scripting (Bash) and command-line interfaces (AWS CLI).
What is DevSecOps Pipeline Security?
DevSecOps Pipeline Security is the practice of integrating automated security controls, identity boundaries, and cryptographic protection directly into the CI/CD workflow. Instead of treating security as a post-build phase, it shifts security left by using tools like AWS KMS and AWS Secrets Manager to dynamically inject encrypted credentials, sign software artifacts, and audit access patterns in real-time, eliminating hardcoded credentials from source control.
Enterprise DevSecOps Architecture
In a secured enterprise AWS environment, the CI/CD pipeline must never store static credentials (such as database passwords, API keys, or SSH keys) in source repositories or environment variables. Instead, the pipeline relies on dynamic IAM role assumption and cryptographic decryption at runtime.
The diagram below illustrates the secure interaction flow between AWS CodePipeline, AWS CodeBuild, AWS Secrets Manager, AWS KMS, and an isolated target resource (such as an Amazon RDS database) within a secure VPC boundary.
+--------------------------------------------------------------------------------------------------+ | AWS VPC BOUNDARY | | | | +--------------------+ (1) Trigger Build +---------------------------+ | | | AWS CodePipeline | ----------------------------------------> | AWS CodeBuild Container | | | +--------------------+ +---------------------------+ | | | | | | (2) Get Secret | | v | | +--------------------+ (4) Decrypt Secret +---------------------------+ | | | AWS KMS (CMK) | <---------------------------------------- | AWS Secrets Manager | | | +--------------------+ +---------------------------+ | | ^ | | | | (5) Decrypted DEK | (3) Request | | v | Encrypted | | +--------------------+ | Payload | | | Envelope | | | | | Decryption | <-------------------------------------------------------+ | | +--------------------+ | | | | | | (6) In-Memory Decrypted Secret | | v | | +--------------------+ | | | Amazon RDS DB | | | +--------------------+ | +--------------------------------------------------------------------------------------------------+
Architectural Flow Steps:
- Trigger Build: CodePipeline triggers a CodeBuild execution. CodeBuild assumes a highly restricted, temporary IAM execution role assigned specifically to that build project.
- Request Secret: During the build phase, the CodeBuild container requests a specific secret from AWS Secrets Manager using its unique Amazon Resource Name (ARN).
- Evaluate Permissions: Secrets Manager checks if the CodeBuild IAM role has permissions to read the secret. If authorized, Secrets Manager retrieves the encrypted secret payload from its storage layer.
- Envelope Decryption: Secrets Manager makes a call to AWS KMS to decrypt the data encryption key (DEK) associated with the secret, passing the ciphertext payload. KMS verifies the key policy to ensure the calling entity is authorized to use the Customer Managed Key (CMK).
- Return Plaintext Secret: KMS decrypts the DEK and returns it to Secrets Manager, which then decrypts the secret value and returns the plaintext secret to the CodeBuild container over an encrypted TLS connection.
- In-Memory Consumption: CodeBuild processes the secret inside volatile memory (RAM) to authenticate against the target resource (e.g., RDS) and immediately flushes the variable. The secret is never written to disk or logged to Amazon CloudWatch.
Deep Dive: AWS Key Management Service (KMS)
AWS Key Management Service (KMS) is a managed service that makes it easy to create and control the cryptographic keys used to encrypt your data. To secure pipelines effectively, we must understand the difference between key types, key policies, and the mechanics of envelope encryption.
1. Envelope Encryption Mechanics
Directly encrypting large datasets or files with a master key in KMS can be slow and inefficient over a network. To solve this, AWS uses Envelope Encryption. Here is how it works:
- The Customer Master Key (CMK) (now referred to as the KMS Key) remains securely inside the HSM (Hardware Security Module) boundary of AWS KMS. It never leaves KMS in plaintext.
- When you want to encrypt data, KMS generates a unique Data Encryption Key (DEK).
- KMS encrypts your data using this DEK, and then encrypts the DEK using your KMS Key (CMK).
- The encrypted data and the encrypted DEK are stored together as an "envelope".
- To decrypt, KMS uses the CMK to decrypt the DEK, and then the decrypted DEK is used to decrypt your actual data.
2. AWS Managed Keys vs. Customer Managed Keys (CMKs)
By default, AWS services use AWS Managed Keys (e.g., aws/secretsmanager). However, for enterprise-grade DevSecOps pipelines, you should always use Customer Managed Keys (CMKs). The table below outlines the critical differences:
| Feature | AWS Managed Key | Customer Managed Key (CMK) |
|---|---|---|
| Creation & Ownership | Created automatically by AWS on your behalf. | Created, owned, and configured by you. |
| Key Policies | Read-only; cannot be modified to restrict specific roles. | Fully customizable key policies (least privilege). |
| Cross-Account Access | Cannot be used for cross-account decryption. | Supports cross-account access (essential for multi-account CI/CD). |
| Rotation | Rotated automatically every 3 years (non-configurable). | Can be rotated automatically every year (or on-demand). |
| Cost | Free (subject to API usage limits). | $1/month per key + API usage charges. |
3. Creating a Secure KMS Key Policy
A KMS key policy is the primary way to control access to your CMK. Unlike IAM policies, which can be overridden by other policies, a KMS key policy must explicitly grant permissions to root or specific roles; otherwise, the key becomes completely inaccessible.
Below is an enterprise-grade KMS Key Policy designed for pipeline security. It grants administrative rights to the DevOps Admin team, but restricts decryption rights exclusively to the CodeBuild pipeline execution role.
{
"Version": "2012-10-17",
"Id": "pipeline-kms-policy-v1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::112233445566:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow DevOps Administrators to Manage Key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::112233445566:role/DevOpsAdminRole"
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow CodeBuild Service Role to Decrypt Secrets",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::112233445566:role/CodeBuildPipelineExecutionRole"
},
"Action": [
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "secretsmanager.us-east-1.amazonaws.com"
}
}
}
]
}
Deep Dive: AWS Secrets Manager
AWS Secrets Manager helps you protect secrets needed to access your applications, services, and IT resources. The service enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle.
1. Dynamic Secret Generation and Storage
Secrets Manager stores secrets as encrypted JSON payloads. For example, a database credential secret should be structured as follows:
{
"engine": "postgres",
"host": "production-db.c123456789.us-east-1.rds.amazonaws.com",
"username": "db_admin",
"password": "SuperSecureComplexPassword2026!",
"port": 5432
}
2. Dynamic Secret Rotation with AWS Lambda
One of the core compliance requirements of frameworks like PCI-DSS, SOC2, and HIPAA is the regular rotation of credentials. AWS Secrets Manager natively integrates with AWS Lambda to automatically execute rotation functions. The lifecycle of a secret rotation follows a precise 4-step sequence managed by the Lambda service:
+---------------------+ (1) createSecret +------------------------+ | | -------------------------> | Create temporary user | | | | in database | | | +------------------------+ | | | | (2) testSecret +------------------------+ | AWS Lambda | -------------------------> | Test temporary user | | Rotation Function | | connection | | | +------------------------+ | | | | (3) setSecret +------------------------+ | | -------------------------> | Set temporary password | | | | as the active password | | | +------------------------+ | | | | (4) finishSecret +------------------------+ | | -------------------------> | Deprecate old credentials| +---------------------+ +------------------------+
- createSecret: The Lambda function creates a new version of the secret containing a newly generated password. It also creates a corresponding user account with this password inside the target database.
- testSecret: The Lambda function tests the new credentials by attempting to authenticate against the database.
- setSecret: The Lambda updates the database to mark this new credential as the active/current credential set.
- finishSecret: The Lambda marks the new secret version with the
AWSCURRENTstaging label, deprecating the old secret version.
Step-by-Step Implementation Guide
Let's build a fully operational DevSecOps pipeline security architecture. We will write the Infrastructure as Code (IaC) in Terraform, configure the IAM policies, write the secure pipeline build specification, and execute a deployment.
Step 1: Provisioning KMS and Secrets Manager with Terraform
Create a file named main.tf. This configuration provisions a Customer Managed Key, creates an alias for it, and creates a secret in Secrets Manager encrypted with this newly created key.
provider "aws" {
region = "us-east-1"
}
# 1. Create the KMS Customer Managed Key
resource "aws_kms_key" "pipeline_key" {
description = "KMS Key for CI/CD Pipeline Secrets Encryption"
deletion_window_in_days = 7
enable_key_rotation = true
policy = jsonencode({
Version = "2012-10-17"
Id = "pipeline-key-policy"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
}
Action = "kms:*"
Resource = "*"
},
{
Sid = "Allow CodeBuild Decryption"
Effect = "Allow"
Principal = {
AWS = aws_iam_role.codebuild_role.arn
}
Action = [
"kms:Decrypt",
"kms:DescribeKey"
]
Resource = "*"
}
]
})
tags = {
Environment = "Production"
Team = "DevSecOps"
}
}
# 2. Create the KMS Alias
resource "aws_kms_alias" "pipeline_key_alias" {
name = "alias/pipeline-secrets-key"
target_key_id = aws_kms_key.pipeline_key.key_id
}
# 3. Create the Secrets Manager Secret Container
resource "aws_secretsmanager_secret" "db_secret" {
name = "prod/database/credentials"
kms_key_id = aws_kms_key.pipeline_key.arn
recovery_window_in_days = 0 # Force delete for testing purposes
tags = {
Environment = "Production"
}
}
# 4. Store a Secret Value (JSON Payload)
resource "aws_secretsmanager_secret_version" "db_secret_val" {
secret_id = aws_secretsmanager_secret.db_secret.id
secret_string = jsonencode({
username = "db_admin"
password = "SuperSecretComplexPassword2026!"
host = "prod-db.example.com"
port = 5432
})
}
# Data source to fetch current account details
data "aws_caller_identity" "current" {}
Step 2: Defining the IAM Role for AWS CodeBuild
Now, let's provision the IAM role that the CodeBuild execution engine will assume. This role must have explicit permissions to read the specific secret we created, but absolutely nothing else (Zero Trust principle).
# 5. Create IAM Role for CodeBuild
resource "aws_iam_role" "codebuild_role" {
name = "CodeBuildPipelineExecutionRole"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "codebuild.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
# 6. Create IAM Policy to access Secrets Manager
resource "aws_iam_policy" "codebuild_secrets_policy" {
name = "CodeBuildSecretsAccessPolicy"
description = "Allows CodeBuild to pull database secrets from Secrets Manager"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
]
Resource = [
aws_secretsmanager_secret.db_secret.arn
]
}
]
})
}
# 7. Attach Policy to CodeBuild Role
resource "aws_iam_role_policy_attachment" "attach_secrets_policy" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.codebuild_secrets_policy.arn
}
Step 3: Writing a Secure buildspec.yml
One of the most common security vulnerabilities in CI/CD pipelines is secret leakage in logs. If you run echo $DB_PASSWORD or execute a command that fails and dumps environment variables, your credentials will be stored in Amazon CloudWatch logs indefinitely.
To prevent this, AWS CodeBuild provides built-in integration with Secrets Manager that masks secrets automatically. If CodeBuild detects the secret value in standard output (stdout) or standard error (stderr), it replaces it with [REDACTED] or asterisks (***).
Here is a secure buildspec.yml implementing dynamic credential resolution and secure application execution.
version: 0.2
env:
# Method A: Standard secure mapping (Recommended)
# CodeBuild automatically fetches and masks these variables
secrets-manager:
DB_USER: "prod/database/credentials:username"
DB_PASS: "prod/database/credentials:password"
DB_HOST: "prod/database/credentials:host"
phases:
install:
runtime-versions:
nodejs: 18
commands:
- echo "Checking environment security configurations..."
# Ensure debugging/tracing is disabled to prevent echoing variables
- set +x
pre_build:
commands:
- echo "Validating AWS CLI access and role execution..."
- aws sts get-caller-identity
# Method B: Programmatic runtime fetching (Useful for advanced parsing)
# This pulls the entire JSON block and parses it in-memory
- echo "Fetching dynamic secret payload programmatically..."
- SECRET_PAYLOAD=$(aws secretsmanager get-secret-value --secret-id "prod/database/credentials" --query SecretString --output text)
- PARSED_HOST=$(echo $SECRET_PAYLOAD | node -e "const fs = require('fs'); console.log(JSON.parse(process.argv[1] || '{}').host);" "$SECRET_PAYLOAD")
- echo "Target database host resolved successfully to $PARSED_HOST"
build:
commands:
- echo "Executing database migration..."
# Use the masked variables in-memory. DO NOT echo these variables!
- npm install pg
- node -e "
const { Client } = require('pg');
const client = new Client({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: 'app_db',
password: process.env.DB_PASS,
port: 5432,
});
client.connect()
.then(() => {
console.log('Successfully connected to production database securely!');
return client.query('SELECT NOW()');
})
.then(res => {
console.log('Database server time verified:', res.rows[0]);
return client.end();
})
.catch(err => {
console.error('Connection failed safely.', err.message);
process.exit(1);
});
"
post_build:
commands:
- echo "Pipeline build execution completed successfully."
# Safely unset variables just in case
- unset DB_USER DB_PASS DB_HOST SECRET_PAYLOAD
Advanced Enterprise Patterns
1. Cross-Account CI/CD Secret Sharing
In mature enterprise architectures, pipelines reside in a centralized Shared Services / Tooling Account, while the target environments (Staging, Production) reside in dedicated Target Accounts. Sharing secrets across accounts requires a trust policy on both the KMS Key and the Secrets Manager Resource.
+-----------------------------------+ +-----------------------------------+ | TOOLING ACCOUNT (111111111111) | | PRODUCTION ACCOUNT (222222222222)| | | | | | +-----------------------------+ | | +-----------------------------+ | | | CodeBuild Execution Role | | | | KMS Key (CMK) | | | | (Assumed by Tooling) | | | | (Allows Tooling Decrypt) | | | +-----------------------------+ | | +-----------------------------+ | | | | | ^ | | | | | | | | +-----------------+-------------+-----------------+ | | | | | | | | +-----------------------------+ | | | | | Secrets Manager Secret | | | | | | (Allows Tooling Read) | | | | | +-----------------------------+ | +-----------------------------------+ +-----------------------------------+
To enable this, apply a Resource Policy to the secret in the Production Account (222222222222) allowing the CodeBuild Role in the Tooling Account (111111111111) to read it:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountPipelineAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/CodeBuildPipelineExecutionRole"
},
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "*"
}
]
}
Additionally, the KMS Key Policy in the Production Account must grant the same Tooling role kms:Decrypt permissions. Without this, the Tooling account will retrieve the secret payload but will fail to decrypt it.
2. Securing traffic with VPC Endpoints (PrivateLink)
If your CodeBuild containers are configured to run inside a VPC (to access internal databases, cache clusters, or APIs), any calls to Secrets Manager or KMS must navigate through the network. By default, these calls resolve to public endpoints on the internet.
For a highly secure posture, provision Interface VPC Endpoints (AWS PrivateLink) for KMS and Secrets Manager inside your private subnets. This routes all API traffic entirely within the AWS private backbone network, eliminating exposure to the public internet.
# Create VPC Endpoint for Secrets Manager
resource "aws_vpc_endpoint" "secretsmanager" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.us-east-1.secretsmanager"
vpc_endpoint_type = "Interface"
private_dns_enabled = true
subnet_ids = [
aws_subnet.private_1.id,
aws_subnet.private_2.id
]
security_group_ids = [
aws_security_group.vpc_endpoint_sg.id
]
}
# Create VPC Endpoint for KMS
resource "aws_vpc_endpoint" "kms" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.us-east-1.kms"
vpc_endpoint_type = "Interface"
private_dns_enabled = true
subnet_ids = [
aws_subnet.private_1.id,
aws_subnet.private_2.id
]
security_group_ids = [
aws_security_group.vpc_endpoint_sg.id
]
}
Monitoring, Auditing, and Compliance
To comply with security frameworks, every access to a pipeline secret must be fully auditable. AWS provides native integrations between Secrets Manager, KMS, CloudTrail, and EventBridge to monitor secret lifecycles.
1. Audit Logs with AWS CloudTrail
When CodeBuild fetches a secret, CloudTrail logs a GetSecretValue event. When KMS decrypts the payload, it logs a Decrypt event. Below is a sample CloudTrail event demonstrating an authorized decryption call:
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAXXXXXXXXXXXXXXXXX:CodeBuildSession",
"arn": "arn:aws:iam::112233445566:role/CodeBuildPipelineExecutionRole",
"accountId": "112233445566"
},
"eventTime": "2026-03-30T14:22:15Z",
"eventSource": "kms.amazonaws.com",
"eventName": "Decrypt",
"awsRegion": "us-east-1",
"sourceIPAddress": "secretsmanager.amazonaws.com",
"userAgent": "AWS-Secrets-Manager-Agent",
"requestParameters": {
"encryptionContext": {
"aws:secretsmanager:arn": "arn:aws:aws:secretsmanager:us-east-1:112233445566:secret:prod/database/credentials"
}
},
"resources": [
{
"accountId": "112233445566",
"type": "AWS::KMS::Key",
"ARN": "arn:aws:kms:us-east-1:112233445566:key/12345678-1234-1234-1234-123456789012"
}
]
}
2. Real-Time Alerting on Secret Access
Using Amazon EventBridge, you can trigger automated security workflows if secrets are accessed outside of business hours or by unauthorized IAM roles.
For example, you can create an EventBridge Rule with the following event pattern to alert your Security Operations Center (SOC) via SNS whenever a secret is deleted:
{
"source": ["aws.secretsmanager"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["secretsmanager.amazonaws.com"],
"eventName": ["DeleteSecret", "ScheduleKeyDeletion"]
}
}
Common Pitfalls and Troubleshooting
Securing pipelines can lead to integration friction if not configured correctly. Below are the most common errors encountered in production and how to resolve them.
1. Error: "AccessDeniedException: User is not authorized to perform: secretsmanager:GetSecretValue"
- Root Cause: The CodeBuild execution role lacks permission to read the secret, or the Secrets Manager Resource Policy explicitly denies access.
- Solution: Verify that the CodeBuild service role has the policy attached (as shown in Step 2). Check if there is an explicit
Denystatement in the Secrets Manager resource policy that overrides the execution role's permissions.
2. Error: "KMS.AccessDeniedException: The ciphertext refers to a customer master key that does not exist, does not exist in this region, or you are not allowed to access."
- Root Cause: The execution role has permissions to read the secret in Secrets Manager, but does not have permissions to use the KMS Key (CMK) that encrypted the secret.
- Solution: Update the KMS Key Policy to include
kms:Decryptpermissions for your CodeBuild IAM role. Note that modifying the IAM policy of the CodeBuild role is not enough; the KMS Key Policy itself must explicitly authorize the role.
3. Error: "Network Connection Timeout" inside CodeBuild
- Root Cause: CodeBuild is deployed inside a private subnet in your VPC, but has no path to reach the public Secrets Manager or KMS API endpoints.
- Solution: You have two options:
- Configure a NAT Gateway in a public subnet and route the private subnet traffic through it.
- Provision VPC Interface Endpoints (PrivateLink) for both KMS and Secrets Manager directly inside the VPC (highly recommended for security and cost efficiency).
4. Secret Leakage in Build Logs
- Root Cause: A script or compiler command inadvertently outputted environment variables, or a tool dumped diagnostic information containing plaintext secrets.
- Solution: Leverage CodeBuild's native
secrets-managersyntax in thebuildspec.ymlto automatically mask variables. Avoid usingenv | greporprintenvin build phases. Use dynamic, short-lived tokens instead of long-lived static secrets wherever possible.
DevSecOps Interview Questions & Answers
Q1: What is Envelope Encryption, and why is it used in AWS Secrets Manager and KMS?
Answer: Envelope encryption is the practice of encrypting data with a unique Data Encryption Key (DEK), and then encrypting that DEK with a master Key Encryption Key (KEK / KMS CMK). It is used because direct encryption using a master key is inefficient for large payloads and introduces latency. By using envelope encryption, the cryptographic operations on actual data occur locally and fast, while the master key remains securely protected inside the KMS HSM boundary, only managing the small DEK.
Q2: Why should we avoid using AWS Managed Keys (e.g., aws/secretsmanager) for enterprise-grade CI/CD pipelines?
Answer: AWS Managed Keys do not support custom key policies, meaning you cannot implement fine-grained access control (least privilege) at the key level. Additionally, AWS Managed Keys cannot be used for cross-account access, which is a critical limitation for enterprise multi-account CI/CD architectures where pipelines reside in a tooling account and deploy to separate development or production accounts.
Q3: If an IAM policy allows a role to read a secret, but the KMS key policy does not mention that role, can the role access the secret?
Answer: No. For KMS keys, access must be explicitly allowed by the Key Policy. If the KMS Key Policy does not grant permissions to the IAM role (either directly or via delegation to the root account), the decryption request will fail with an AccessDenied exception, even if the IAM policy has full administrator access.
Q4: How does AWS CodeBuild prevent secrets from leaking into CloudWatch build logs?
Answer: CodeBuild integrates natively with AWS Secrets Manager and SSM Parameter Store via the secrets-manager block in the buildspec.yml. When configured this way, CodeBuild retrieves the secret at runtime and registers its plaintext value with a local masking filter. If that exact string appears in stdout or stderr during build execution, CodeBuild replaces it with asterisks or [REDACTED] before sending the logs to CloudWatch.
Q5: How do you rotate a database password secret in Secrets Manager without causing downtime for running applications?
Answer: This is achieved using the multi-step rotation strategy (often called the Alternating Secret Label strategy). Secrets Manager uses a Lambda function to create a new version of the secret containing a new password, provisions that user/password inside the database, tests the connection with the new credentials, and then seamlessly updates the active label (AWSCURRENT) to the new version. Running applications should be designed to catch connection failures, re-fetch the secret from Secrets Manager, and retry the connection, ensuring zero downtime.
Frequently Asked Questions (FAQs)
Can I store binary files (such as certificates or private keys) in AWS Secrets Manager?
Yes. AWS Secrets Manager allows you to store binary data up to 64KB. You can upload a binary file (such as a .pfx or .pem file) using the AWS Console or CLI, and Secrets Manager will encode it using Base64. When your pipeline retrieves the secret, it can decode the Base64 string back into the original binary file in-memory.
What is the maximum size of a secret in AWS Secrets Manager?
The maximum size of a secret value in AWS Secrets Manager is 64 KB (65,536 bytes). This is generally more than enough to store complex configurations, multiple API keys, or certificates.
How much does AWS Secrets Manager cost compared to SSM Parameter Store?
AWS Secrets Manager costs $0.40 per secret per month, plus $0.05 per 10,000 API calls. In contrast, SSM Parameter Store (Standard) is free of charge, but does not natively support automatic secret rotation or cross-account sharing out-of-the-box. For production credentials, Secrets Manager is highly recommended due to its security lifecycle features.
Is it possible to recover a deleted secret?
Yes. When you delete a secret in Secrets Manager, you must specify a recovery window of at least 7 days (up to 30 days). During this period, the secret remains in a "deleted" state but can be restored. However, you can force deletion without a recovery window using the CLI (--force-delete-without-recovery) if you need to immediately recreate a secret with the same name.
Can I use AWS KMS to encrypt secrets stored in Github Actions or GitLab CI?
Absolutely. You can configure GitHub Actions or GitLab CI to assume an AWS IAM Role using OpenID Connect (OIDC). Once authenticated, the third-party runner can call the AWS KMS decryption API directly or fetch secrets from AWS Secrets Manager, ensuring you do not have to store long-lived AWS Access Keys inside third-party platforms.
Does AWS KMS store my actual plaintext passwords?
No. AWS KMS only manages cryptographic keys (CMKs) and performs encryption/decryption operations. It does not store your passwords, database credentials, or application data. AWS Secrets Manager stores the encrypted payloads and uses KMS as its cryptographic provider to decrypt them on-demand.
Summary & Next Steps
Securing your enterprise CI/CD pipeline is not a one-time setup; it is a continuous posture of refining permissions and monitoring access patterns. By implementing AWS KMS Customer Managed Keys and AWS Secrets Manager with least-privilege policies, you have effectively eliminated static, hardcoded credentials from your deployment lifecycle.
To further advance your AWS DevOps masterclass journey, we recommend exploring the following lessons: