Why did my Secrets Manager Lambda rotation function fail for my secret in another account?
I configured an AWS Lambda function to rotate my AWS Secrets Manager secret in another AWS account, but the function didn't rotate the secret.
Short description
In December 2024, Secrets Manager will change to how entities that call the PutSecretValue API action are validated. Entities that call the PutSecretValue API from a Lambda function in another account for cross-account rotation must pass a rotation token. Secrets Manager uses the rotation token to validate the identity of the entity. Lambda rotation functions then call the PutSecretValue API as part of the rotation for the secret.
If your Lambda rotation function is in the same account as the secret that it rotates, then no changes are required.
If your Lambda rotation function is in another account than the secret that it rotates, then you must update your function to pass a rotation token.
Important: It's a best practice to update your rotation function before December 2024.
Resolution
To resolve this issue, update the code in your existing rotation function to include the RotationToken parameter.
Download the Lambda function code
Complete the following steps:
- Open the Lambda console.
- In the navigation pane, choose Functions.
- For Function name, select your Lambda function that rotates the secret.
- For Download, choose one of the following options:
Function code .zip
AWS SAM file
Both - Choose OK to save the function on your local machine.
Edit the Lambda function code
Open your code editor tool, and edit the code that you downloaded. The following are example code edits that you can make.
Code example 1: Lambda_handler
The following code shows the lambda_handler function in a Secrets Manager Lambda rotation function. Secrets Manager invokes this function multiple times during a rotation. For cross-account rotation, include the rotation_token parameter in the create_secret step.
def lambda_handler(event, context): """Secrets Manager Rotation Template This is a template for creating an AWS Secrets Manager rotation lambda Args: event (dict): Lambda dictionary of event parameters. These keys must include the following: - SecretId: The secret ARN or identifier - ClientRequestToken: The ClientRequestToken of the secret version - Step: The rotation step (one of createSecret, setSecret, testSecret, or finishSecret) - RotationToken: the rotation token to put as parameter for PutSecretValue call context (LambdaContext): The Lambda runtime information Raises: ResourceNotFoundException: If the secret with the specified arn and stage does not exist ValueError: If the secret is not properly configured for rotation KeyError: If the event parameters do not contain the expected keys """ arn = event['SecretId'] token = event['ClientRequestToken'] step = event['Step'] rotation_token = event['RotationToken'] # Setup the client service_client = boto3.client('secretsmanager', endpoint_url=os.environ['SECRETS_MANAGER_ENDPOINT']) # Make sure the version is staged correctly metadata = service_client.describe_secret(SecretId=arn) if not metadata['RotationEnabled']: logger.error("Secret %s is not enabled for rotation" % arn) raise ValueError("Secret %s is not enabled for rotation" % arn) versions = metadata['VersionIdsToStages'] if token not in versions: logger.error("Secret version %s has no stage for rotation of secret %s." % (token, arn)) raise ValueError("Secret version %s has no stage for rotation of secret %s." % (token, arn)) if "AWSCURRENT" in versions[token]: logger.info("Secret version %s already set as AWSCURRENT for secret %s." % (token, arn)) return elif "AWSPENDING" not in versions[token]: logger.error("Secret version %s not set as AWSPENDING for rotation of secret %s." % (token, arn)) raise ValueError("Secret version %s not set as AWSPENDING for rotation of secret %s." % (token, arn)) if step == "createSecret": create_secret(service_client, arn, token, rotation_token) elif step == "setSecret": set_secret(service_client, arn, token) elif step == "testSecret": test_secret(service_client, arn, token) elif step == "finishSecret": finish_secret(service_client, arn, token) else: raise ValueError("Invalid step parameter")
Code example 2: create_secret
The following code example shows how to revise the create_secret function in a Secrets Manager Lambda rotation function. To allow cross-account rotation, accept the rotation_token parameter, and pass the rotation token to put_secret_value.
def create_secret(service_client, arn, token, rotation_token): """Create the secret This method first checks for the existence of a secret for the passed in token. If one does not exist, it will generate a new secret and put it with the passed in token. Args: service_client (client): The secrets manager service client arn (string): The secret ARN or other identifier token (string): The ClientRequestToken associated with the secret version rotation_token (string): the rotation token to put as parameter for PutSecretValue call Raises: ResourceNotFoundException: If the secret with the specified arn and stage does not exist """ # Make sure the current secret exists service_client.get_secret_value(SecretId=arn, VersionStage="AWSCURRENT") # Now try to get the secret version, if that fails, put a new secret try: service_client.get_secret_value(SecretId=arn, VersionId=token, VersionStage="AWSPENDING") logger.info("createSecret: Successfully retrieved secret for %s." % arn) except service_client.exceptions.ResourceNotFoundException: # Get exclude characters from environment variable exclude_characters = os.environ['EXCLUDE_CHARACTERS'] if 'EXCLUDE_CHARACTERS' in os.environ else '/@"\'\\' # Generate a random password passwd = service_client.get_random_password(ExcludeCharacters=exclude_characters) # Put the secret service_client.put_secret_value(SecretId=arn, ClientRequestToken=token, SecretString=passwd['RandomPassword'], VersionStages=['AWSPENDING'], RotationToken=rotation_token) logger.info("createSecret: Successfully put secret for ARN %s and version %s." % (arn, token))
Upload the updated Lambda function code
To rotate your secret, upload the updated Lambda function rotation code.
Related information
Relevant content
- Accepted Answerasked 2 years agolg...
- asked 5 years agolg...
- asked 6 months agolg...
- asked 2 years agolg...
- asked 3 years agolg...
- AWS OFFICIALUpdated 3 years ago
- AWS OFFICIALUpdated 2 years ago