J'ai configuré une fonction de rotation AWS Lambda pour utiliser un rôle endossé afin d’alterner mon secret AWS Secrets Manager ou d’effectuer une rotation entre les comptes AWS. Cependant, la fonction n'a pas changé le secret.
Brève description
En décembre 2024, Secrets Manager a modifié la façon dont il valide les entités qui appellent l'action d'API PutSecretValue dans le cadre du processus de rotation. Ce changement affecte à la fois la rotation des rôles entre comptes et endossés.
La fonction doit transmettre un jeton de rotation afin que Secrets Manager puisse valider l'identité de l'entité. Les fonctions de rotation Lambda peuvent ensuite appeler PutSecretValue.
Si vous n'avez pas mis à jour le code de votre fonction de rotation avant décembre 2024, il est recommandé de le mettre à jour. Vérifiez AWS CloudTrail pour détecter un événement RotationFailed avec le message suivant : « Pending secret version VERSION_ID for Secret SECRET_ARN wasn't created by Lambda LAMBDA_ARN. Remove the AWSPENDING staging label and restart rotation ». Si vous trouvez l'événement RotationFailed, mettez à jour votre fonction Lambda pour utiliser le paramètre RotationToken.
Remarque : Si vous n'utilisez pas de rotation entre comptes ou si vous n'utilisez pas de rôle endossé, aucune modification n'est requise.
Résolution
Télécharger le code de fonction Lambda
Procédez comme suit :
- Ouvrez la console Lambda.
- Dans le volet de navigation, sélectionnez Fonctions.
- Dans Nom de la fonction, sélectionnez votre fonction Lambda qui alterne le secret.
- Dans Téléchargement, choisissez l'une des options suivantes :
Code de fonction .zip
Fichier AWS SAM
Les deux
- Choisissez OK pour enregistrer la fonction sur votre ordinateur local.
Modifier le code de fonction Lambda
Ouvrez votre éditeur de code et modifiez le code de votre fonction Lambda. Les exemples suivants sont des modifications de code que vous pourriez avoir besoin d'apporter.
Modifier le code lambda_handler
Incluez le paramètre rotation_token à l’étape create_secret pour la rotation entre comptes :
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']
# Add the rotation token
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))
# Use rotation_token
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")
Modifier le code create_secret
Mettez à jour la fonction create_secret pour accepter et utiliser le paramètre rotation_token :
# Add rotation_token to the function
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, using rotation_token
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))
Charger le code de fonction Lambda mis à jour
Après avoir mis à jour le code de votre fonction Lambda, chargez-le pour alterner votre secret.
Informations connexes
Rotation par fonction Lambda
Ma fonction de rotation Lambda a appelé une deuxième fonction pour alterner un secret de Secrets Manager, mais elle a échoué. Pourquoi la deuxième fonction Lambda a-t-elle échoué ?