Ir para o conteúdo

Por que minha alternância do Secrets Manager Lambda falhou?

5 minuto de leitura
0

Configurei uma função de alternância do AWS Lambda para usar uma função assumida para alternar meu segredo do AWS Secrets Manager ou alternar entre contas da AWS. No entanto, a função não alterou o segredo.

Breve descrição

Em dezembro de 2024, o Secrets Manager mudou a forma como valida entidades que chamam a ação da API PutSecretValue como parte do processo de alternância. Essa alteração afeta tanto a alternância entre contas como a de funções assumidas.

A função deve passar um token de alternância para que o Secrets Manager possa validar a identidade da entidade. As funções de alternância do Lambda podem então chamar PutSecretValue.

Se o código da sua função de alternância não foi atualizado antes de dezembro de 2024, a prática recomendada é fazer a atualização. Verifique o AWS CloudTrail para um evento RotationFailed com a mensagem, “A versão secreta pendente VERSION_ID para Secret SECRET_ARN não foi criada pelo Lambda LAMBDA_ARN. Remova o rótulo de teste AWSPENDING e reinicie a alternância”. Se você encontrar o evento RotationFailed, atualize sua função do Lambda para usar o parâmetro RotationToken.

Observação: se você não usar a alternância entre contas ou uma função assumida, nenhuma alteração será necessária.

Resolução

Baixe o código da função do Lambda

Conclua as etapas a seguir:

  1. Abra o console do Lambda.
  2. No painel de navegação, escolha Funções.
  3. Em Nome da função, selecione sua função do Lambda que alterna o segredo.
  4. Em Baixar, escolha uma das seguintes opções:
    Código de função .zip
    Arquivo AWS SAM
    Ambos
  5. Escolha OK para salvar a função em sua máquina local.

Edite o código da função do Lambda

Abra seu editor de código e edite seu código de função do Lambda. Os exemplos a seguir são edições de código que talvez você precise fazer.

Edite o código lambda_handler

Inclua o parâmetro rotation_token na etapa create_secret para alternância entre contas:

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

Edite o código create_secret

Atualize a função create_secret para aceitar e usar o 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))

Faça o upload do código da função do Lambda atualizado

Depois de atualizar seu código de função do Lambda, faça o upload do código para alternar seu segredo.

Informações relacionadas

Alternância pela função do Lambda

Minha função de alternância do Lambda chamou uma segunda função para alternar um segredo do Secrets Manager, mas falhou. Por que a segunda função do Lambda falhou?

AWS OFICIALAtualizada há um ano