Passer au contenu

Pourquoi ma rotation Lambda dans Secrets Manager a-t-elle échoué ?

Lecture de 5 minute(s)
0

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 :

  1. Ouvrez la console Lambda.
  2. Dans le volet de navigation, sélectionnez Fonctions.
  3. Dans Nom de la fonction, sélectionnez votre fonction Lambda qui alterne le secret.
  4. Dans Téléchargement, choisissez l'une des options suivantes :
    Code de fonction .zip
    Fichier AWS SAM
    Les deux
  5. 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é ?

AWS OFFICIELA mis à jour il y a un an