Ongoing service disruptions
For the most recent update on ongoing service disruptions affecting the AWS Middle East (UAE) Region (ME-CENTRAL-1), refer to the AWS Health Dashboard. For information on AWS Service migration, see How do I migrate my services to another region?
Secrets Manager の Lambda ローテーションが失敗した原因を教えてください。
引き受けたロールを使用して 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 関数コードをダウンロードする
次の手順を実行します。
- Lambda コンソールを開きます。
- ナビゲーションペインで、[関数] を選択します。
- [関数名] で、シークレットをローテーションする Lambda 関数を選択します。
- [ダウンロード] で、次のオプションのいずれかを選択します。
関数コードの .zip
AWS SAM ファイル
両方 - [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 関数コードを更新した後、コードをアップロードしてシークレットをローテーションします。
関連情報
- 言語
- 日本語
