為什麼我的 Secrets Manager Lambda 輪換失敗?
我設定了一個 AWS Lambda 輪換函數,以使用假設的角色來輪換 AWS Secrets Manager 密碼或在 AWS 帳戶之間進行輪換。但是,該函數並沒有輪換密碼。
簡短說明
2024 年 12 月,Secrets Manager 變更了其在輪換程序中驗證呼叫 PutSecretValue API 動作之實體的方式。此變更會影響跨帳戶和假設角色的輪換。
函數必須傳遞輪換權杖,以便 Secrets Manager 驗證實體的身分識別。然後,Lambda 輪換函數可以呼叫 PutSecretValue。
如果您在 2024 年 12 月之前沒有更新輪換函數程式碼,那麼最好進行更新。檢查 AWS CloudTrail 中是否存在 RotationFailed 事件,其中顯示訊息「密碼SECRET_ARN 的待處理密碼版本 VERSION_ID 不是由 Lambda LAMBDA_ARN 建立的。請移除 AWSPENDING 暫存標籤並重新啟動輪換」。如果您發現 RotationFailed 事件,請更新您的 Lambda 函數以使用 RotationToken 參數。
注意: 如果您不使用跨帳戶輪換或假設角色,則無需進行任何更改。
解決方法
下載 Lambda 函數程式碼
請完成下列步驟:
- 開啟 Lambda 主控台。
- 在導覽窗格中,選擇 Functions (函數)。
- 在 Function name (函數名稱) 中,選擇輪換密碼的 Lambda 函數。
- 在 Download (下載) 中,選擇下列其中一個選項:
函數程式碼.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 函數程式碼後,上傳程式碼以輪換您的密碼。
相關資訊
我的 Lambda 輪換函數呼叫了第二個函數來輪換 Secrets Manager 密碼,但失敗了。為什麼第二個 Lambda 函數會失敗?
- 語言
- 中文 (繁體)

相關內容
- 已提問 2 年前