Secret Manager Secrets Rotation Enabled
More Info:
Ensure that AWS Secrets Manager service is configured to automatically rotate your service or database secrets (i.e. enable automatic rotation feature for your secrets). Secrets Manager rotation is the automatic process that periodically change your secrets data to make it more difficult for an attacker to access the services and resources secured with these secrets. With Amazon Secrets Manager you don't have to manually change the secret and update it on all of your clients. Instead, the Secrets Manager service uses an AWS Lambda function to perform for you all of the steps required for rotation, on a regular schedule (predefined or custom).
Risk Level
Medium
Address
Security
Compliance Standards
AWSWAF, HITRUST, SOC2, NISTCSF, PCIDSS
Remediation
How to enable secret rotation in secrets manager
Using AWS Console
- Open the AWS Management Console and navigate to the Secrets Manager service.
- Select the secret you want to enable rotation for and click on the "Edit rotation" button. (In the Cloudanix Console, navigate to "Misconfig" page and look for Affected Assets for "Secret Manager Secrets Rotation Enabled" Policy.)
- Select the "Enable automatic rotation" option and choose the rotation frequency.
- Choose the Lambda function that will be used to rotate the secret. You can either choose an existing function or create a new one.
- Provide the necessary permissions to the Lambda function to access the secret and rotate it.
- Configure the rotation settings such as the number of days before the rotation starts and the number of days before the old secret is deleted.
- Review and confirm the rotation settings and click on the "Save" button.
Triage and Remediation
- Remediation
Remediation
Using Console
Below are the minimal console steps to enable rotation for an AWS Secrets Manager secret that’s encrypted with a KMS key.
Note: Secrets rotation is configured per secret. The KMS key only encrypts the secret; enabling rotation is done in Secrets Manager, not on the KMS key itself.
1. Identify the secret
- Sign in to the AWS Management Console.
- Go to Secrets Manager:
Services → Security, Identity, & Compliance → Secrets Manager. - On Secrets, click the secret you want to enable rotation for (it can be encrypted with a customer-managed KMS key).
2. Set up (or select) a rotation Lambda function
-
On the secret’s details page, click Rotate secret (or edit rotation from the Rotation tab/section).
-
Check Enable automatic rotation.
-
Under Rotation schedule, choose the rotation period (e.g., 30 days).
-
Under Rotation function, choose one of:
- Use an existing Lambda function (if you already have a rotation function for this secret’s type).
- Or Create a new Lambda function (recommended if you don’t have one):
- Choose the database/service type (e.g., RDS, DocumentDB, etc.).
- Provide a name for the new Lambda function.
- AWS will create a Lambda from a template and an IAM role with required permissions.
-
Save/confirm the Lambda creation (if you created a new one) and return to the Rotate secret configuration.
3. Configure rotation schedule and save
- Set Rotation schedule:
- Choose Automatic rotation.
- Set the rotation interval (e.g., 30, 60, or 90 days).
- (Optional) Configure a specific start time if needed.
- Click Save or Schedule rotation.
4. (Optional) Test rotation
- On the secret’s page, use Rotate secret immediately (or Test rotation) if available.
- Confirm that:
- The Lambda function completes without errors.
- The target resource (DB, service, etc.) can be accessed using the updated secret value.
- The secret remains encrypted with your intended KMS key (check Secret details → Encryption key).
This remediates the “Secrets Manager secrets rotation disabled” issue for a KMS-encrypted secret via the AWS Console.
Using CLI
To fix this finding using AWS KMS via AWS CLI, you typically need to enable automatic rotation on the KMS keys that encrypt your Secrets Manager secrets.
Below are the step‑by‑step commands.
1. Identify the KMS key used by the secret
If you already know the KMS key ID/ARN, skip to step 2.
Otherwise, get the secret’s details:
aws secretsmanager describe-secret \
--secret-id <your-secret-id>
In the output, note the KmsKeyId field. That is the KMS key you must configure.
2. Check current rotation status of the KMS key
aws kms get-key-rotation-status \
--key-id <kms-key-id-or-arn>
Look at KeyRotationEnabled:
false→ rotation not enabled (this triggers your finding).true→ rotation already enabled.
3. Enable automatic rotation for the KMS key
aws kms enable-key-rotation \
--key-id <kms-key-id-or-arn>
Notes:
- This can only be done for symmetric customer managed keys (CMKs), not AWS‑managed keys.
- Rotation interval is fixed at 1 year for KMS automatic rotation.
4. Re‑verify rotation status
aws kms get-key-rotation-status \
--key-id <kms-key-id-or-arn>
Confirm KeyRotationEnabled is now true.
If you also need Secrets Manager secret rotation (rotating the secret value itself, e.g., database password), I can give you the separate CLI steps for setting up a rotation Lambda and enabling rotate-secret.
Using Python
Below is a practical, minimal set of steps and Python snippets to enable automatic rotation for AWS Secrets Manager secrets that use KMS.
1. Prerequisites
- A secret already exists in AWS Secrets Manager (e.g.
my-db-secret). - The secret is encrypted with a KMS key (default or customer-managed).
- You have:
awsclior AWS Console accessboto3installed for Python- IAM permissions for:
secretsmanager:*lambda:*iam:PassRole
2. Create an IAM Role for the Rotation Lambda
Create a role (e.g. SecretsRotationRole) with:
- Trust policy (principal is Lambda):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
- Permissions policy for Secrets Manager, KMS, logging, and your target resource (e.g. DB, API, etc.):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:PutSecretValue",
"secretsmanager:UpdateSecretVersionStage"
],
"Resource": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:my-db-secret-*"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:Encrypt",
"kms:GenerateDataKey"
],
"Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/YOUR_KMS_KEY_ID"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
// Add DB permissions if you are rotating DB credentials
]
}
Attach this policy to the role.
3. Write the Rotation Lambda in Python
A rotation Lambda must implement these steps:
createSecret, setSecret, testSecret, finishSecret.
Below is a minimal template (you must customize the actual secret-change logic, e.g., DB password rotation):
import boto3
import json
import logging
import os
logger = logging.getLogger()
logger.setLevel(logging.INFO)
secrets_client = boto3.client('secretsmanager')
def lambda_handler(event, context):
arn = event['SecretId']
token = event['ClientRequestToken']
step = event['Step']
metadata = secrets_client.describe_secret(SecretId=arn)
if not metadata['RotationEnabled']:
raise ValueError("Secret rotation not enabled for secret {}".format(arn))
versions = metadata['VersionIdsToStages']
if token not in versions or 'AWSPENDING' not in versions[token]:
raise ValueError("Secret version not set as AWSPENDING for rotation")
if step == "createSecret":
create_secret(arn, token)
elif step == "setSecret":
set_secret(arn, token)
elif step == "testSecret":
test_secret(arn, token)
elif step == "finishSecret":
finish_secret(arn, token)
else:
raise ValueError("Invalid step parameter")
def create_secret(arn, token):
# If a pending secret already exists, don’t recreate
try:
secrets_client.get_secret_value(SecretId=arn, VersionId=token, VersionStage="AWSPENDING")
logger.info("createSecret: AWSPENDING already exists for %s", arn)
return
except secrets_client.exceptions.ResourceNotFoundException:
pass
# Get the current secret (to use as base)
current = secrets_client.get_secret_value(SecretId=arn, VersionStage="AWSCURRENT")
current_dict = json.loads(current['SecretString'])
# TODO: Implement logic to generate new secret value, e.g. new password
new_secret_dict = current_dict.copy()
new_secret_dict["password"] = "NEW_GENERATED_PASSWORD" # replace with real generation
secrets_client.put_secret_value(
SecretId=arn,
ClientRequestToken=token,
SecretString=json.dumps(new_secret_dict),
VersionStages=["AWSPENDING"]
)
logger.info("createSecret: Created new pending secret for %s", arn)
def set_secret(arn, token):
# TODO: Apply the new secret to the target system (e.g., update DB user password)
logger.info("setSecret: Apply pending secret in target system for %s", arn)
# Example stub; implement per your target:
# 1. Get AWSPENDING
# 2. Connect to DB / service
# 3. Update password / key
pass
def test_secret(arn, token):
# TODO: Verify that AWSPENDING secret works against target system
logger.info("testSecret: Testing pending secret for %s", arn)
# Example stub:
# 1. Get AWSPENDING
# 2. Attempt to connect/login
# 3. Raise on failure
pass
def finish_secret(arn, token):
metadata = secrets_client.describe_secret(SecretId=arn)
current_version = None
for version, stages in metadata['VersionIdsToStages'].items():
if "AWSCURRENT" in stages:
current_version = version
break
# Mark the new version as current
secrets_client.update_secret_version_stage(
SecretId=arn,
VersionStage="AWSCURRENT",
MoveToVersionId=token,
RemoveFromVersionId=current_version
)
logger.info("finishSecret: Set AWSCURRENT to version %s for %s", token, arn)
Package this as a ZIP and deploy as a Lambda (via console or CLI).
Set:
- Runtime: Python 3.x
- Role:
SecretsRotationRole - Timeout: long enough for rotation (e.g. 15–30 seconds; more if needed).
4. Enable Rotation on the Secret Using Python (boto3)
Use rotate_secret or enable_rotation from boto3:
import boto3
secrets_client = boto3.client("secretsmanager", region_name="YOUR_REGION")
secret_arn = "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:my-db-secret-XXXX"
lambda_arn = "arn:aws:lambda:REGION:ACCOUNT_ID:function:your-rotation-lambda"
response = secrets_client.rotate_secret(
SecretId=secret_arn,
RotationLambdaARN=lambda_arn,
RotationRules={
"AutomaticallyAfterDays": 30 # e.g. every 30 days
}
)
print(response)
If the Lambda is already associated and you just want to turn rotation on/update schedule:
secrets_client.enable_rotation(
SecretId=secret_arn,
RotationLambdaARN=lambda_arn,
RotationRules={
"AutomaticallyAfterDays": 30
}
)
5. Verify Rotation Status
resp = secrets_client.describe_secret(SecretId=secret_arn)
print("RotationEnabled:", resp["RotationEnabled"])
print("RotationRules:", resp.get("RotationRules"))
print("RotationLambdaARN:", resp.get("RotationLambdaARN"))
This remediates the misconfiguration by programmatically enabling secret rotation for a KMS-encrypted secret in AWS using Python; you only need to fill in the target-specific rotation logic in the Lambda (setSecret and testSecret).
Using Terraform
resource "aws_kms_key" "EXAMPLE_KEY" {
description = "KMS key for XYZ purpose"
deletion_window_in_days = 30
key_usage = "ENCRYPT_DECRYPT"
customer_master_key_spec = "SYMMETRIC_DEFAULT"
# Enable annual automatic rotation for this KMS key
enable_key_rotation = true
}
Replace EXAMPLE_KEY with your key name and adjust description/usage/spec as needed.
This change does not force replacement of the KMS key; Terraform will update it in place.
To verify, terraform plan should show an in-place update with enable_key_rotation changing from false (or null) to true.