Saltar al contenido

¿Por qué ha fallado mi rotación de Lambda de Secrets Manager?

5 minutos de lectura
0

He configurado una función de rotación de AWS Lambda para usar un rol asumido para rotar mi secreto de AWS Secrets Manager o para rotar entre cuentas de AWS. Sin embargo, la función no ha alterado el secreto.

Descripción corta

En diciembre de 2024, Secrets Manager cambió la forma en que valida las entidades que llaman a la acción de la API PutSecretValue como parte del proceso de rotación. Este cambio afecta tanto a la rotación entre cuentas como a la rotación de roles asumidos.

La función debe pasar un token de rotación para que Secrets Manager pueda validar la identidad de la entidad. Las funciones de rotación de Lambda pueden entonces llamar a PutSecretValue.

Si no actualizó el código de la función de rotación antes de diciembre de 2024, se recomienda actualizarlo. Consulte AWS CloudTrail para ver si hay un evento RotationFailed con el mensaje: «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 encuentra el evento RotationFailed, actualice la función de Lambda para usar el parámetro RotationToken.

Nota: Si no utiliza la rotación entre cuentas o un rol asumido, no es necesario hacer ningún cambio.

Resolución

Descarga del código de la función de Lambda

Siga estos pasos:

  1. Abra la consola de Lambda.
  2. En el panel de navegación, seleccione Funciones.
  3. En Nombre de función, seleccione la función de Lambda que rota el secreto.
  4. En Descargar, elija una de las siguientes opciones:
    Código de función .zip
    Archivo SAM de AWS
    Ambos
  5. Seleccione Aceptar para guardar la función en su equipo local.

Edición del código de la función de Lambda

Abra el editor de código y edite el código de la función de Lambda. Los siguientes ejemplos son ediciones de código que puede que necesite realizar.

Editar el código lambda_handler

Incluya el parámetro rotation_token en el paso create_secret para la rotación entre cuentas:

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")

Editar el código create_secret

Actualice la función create_secret para aceptar y usar el parámetro 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))

Carga del código de la función de Lambda actualizado

Después de actualizar el código de la función de Lambda, cárguelo para rotar el secreto.

Información relacionada

Rotación por función de Lambda

Mi función de rotación de Lambda llamó a una segunda función para rotar un secreto de Secrets Manager, pero se produjo un error. ¿Por qué se produjo un error en la segunda función de Lambda?

OFICIAL DE AWSActualizada hace un año