スキップしてコンテンツを表示

Secrets Manager の Lambda ローテーションが失敗した原因を教えてください。

所要時間4分
0

引き受けたロールを使用して AWS Secrets Manager のシークレットをローテーションしたり、複数 AWS アカウントにわたりローテーションしたりするように AWS Lambda ローテーション関数を設定しましたが、この関数ではシークレットをローテーションできませんでした。

簡単な説明

2024 年 12 月に、Secrets Manager は、ローテーションプロセスの一環として PutSecretValue API アクションを呼び出すエンティティの検証方法を変更しました。この変更は、クロスアカウントローテーションおよび、引き受けたロールのローテーションに影響します。

Secrets Manager がエンティティの ID を検証するために、関数はローテーショントークンを渡す必要があります。そうすることで、Lambda ローテーション関数が PutSecretValue を呼び出すことができます。

2024 年 12 月までにローテーション関数コードを更新していない場合は、更新することをおすすめします。AWS CloudTrail で、次のメッセージを含む RotationFailed イベントがないかどうかを確認します。「シークレットバージョン VERSION_ID の保留中。Lambda LAMBDA_ARN により、シークレット SECRET_ARN は作成されていません。ステージングラベル AWPSENDING を削除してから、ローテーションを再開してください」RotationFailed イベントが見つかった場合は、RotationToken パラメータを使用するように Lambda 関数を更新します。

注: クロスアカウントローテーションや引き受けたロールを使用しない場合、変更は必要ありません。

解決策

Lambda 関数コードをダウンロードする

次の手順を実行します。

  1. Lambda コンソールを開きます。
  2. ナビゲーションペインで、[関数] を選択します。
  3. [関数名] で、シークレットをローテーションする Lambda 関数を選択します。
  4. [ダウンロード] で、次のオプションのいずれかを選択します。
    関数コードの .zip
    AWS SAM ファイル
    両方
  5. [OK] を選択してローカルマシンに関数を保存します。

Lambda 関数コードを編集する

コードエディタを開き、Lambda 関数コードを編集します。必要なコード編集の例を次に示します。

lambda_handler のコードを編集する

クロスアカウントローテーションで、create_secret ステップに rotation_token パラメータを含めます。

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

create_secret のコードを編集する

create_secret 関数が 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))

更新した Lambda 関数コードをアップロードする

Lambda 関数コードを更新した後、コードをアップロードしてシークレットをローテーションします。

関連情報

Lambda 関数によるローテーション

Lambda のローテーション関数が 2 番目の関数を呼び出して Secrets Manager のシークレットをローテーションを試みましたが、失敗しました。2 番目の Lambda 関数が失敗した原因を教えてください

AWS公式更新しました 1年前
コメントはありません

関連するコンテンツ