使用 AWS re:Post 即表示您同意 AWS re:Post 使用條款

如何在 Amazon Cognito 使用者集區中使用自訂電子郵件寄件者 Lambda 觸發機制?

4 分的閱讀內容
0

我要調用 Amazon Cognito 自訂電子郵件寄件者 AWS Lambda 觸發機制來處理和傳遞電子郵件訊息。

解決方法

使用 Amazon Cognito 自訂電子郵件寄件者觸發機制,允許第三方供應商從 Lambda 函數程式碼傳送電子郵件通知給您的使用者。Amazon Cognito 會將電子郵件訊息請求傳送至 Lambda 函數。然後,Lambda 函數會處理並傳遞電子郵件訊息。

建立 Lambda 函數,作為您的自訂電子郵件寄件者觸發機制

  1. 建立名稱為 index.js 的檔案、將下列程式碼新增至檔案,然後儲存變更。

    const AWS = require('aws-sdk');const b64 = require('base64-js');
    const encryptionSdk = require('@aws-crypto/client-node');
    
    // Configure the encryption SDK client with the KMS key from the environment variables.
    
    const { encrypt, decrypt } = encryptionSdk.buildClient(encryptionSdk.CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT);
    const generatorKeyId = process.env.KEY_ALIAS;
    const keyIds = [ process.env.KEY_ARN ];
    const keyring = new encryptionSdk.KmsKeyringNode({ generatorKeyId, keyIds })
    exports.handler = async (event) => {
    
    // Decrypt the secret code using encryption SDK.
    let plainTextCode;
    if(event.request.code){
    const { plaintext, messageHeader } = await decrypt(keyring, b64.toByteArray(event.request.code));
    plainTextCode = plaintext
    }
    
    // PlainTextCode now has the decrypted secret.
    
    if(event.triggerSource == 'CustomEmailSender_SignUp'){
    
    // Send email to end-user using custom or 3rd party provider.
    // Include temporary password in the email.
    
    console.log("CustomEmailSender_SignUp: " + plainTextCode);
    
    }else if(event.triggerSource == 'CustomEmailSender_ResendCode'){
    console.log("CustomEmailSender_ResendCode: " + plainTextCode);
    
    }else if(event.triggerSource == 'CustomEmailSender_ForgotPassword'){
    console.log("CustomEmailSender_ForgotPassword: " + plainTextCode);
    
    }else if(event.triggerSource == 'CustomEmailSender_UpdateUserAttribute'){
    console.log("CustomEmailSender_UpdateUserAttribute: " + plainTextCode);
    
    }else if(event.triggerSource == 'CustomEmailSender_VerifyUserAttribute'){
    console.log("CustomEmailSender_VerifyUserAttribute: " + plainTextCode);
    
    }else if(event.triggerSource == 'CustomEmailSender_AdminCreateUser'){
    console.log("CustomEmailSender_AdminCreateUser: " + plainTextCode);
    
    }else if(event.triggerSource == 'CustomEmailSender_AccountTakeOverNotification'){
    console.log("CustomEmailSender_AccountTakeOverNotification: " + plainTextCode);
    }
    
    return;
    };

    **警告:**此程式碼會透過指令碼來解密已加密的保密內容。保密內容是由 Amazon Cognito 傳送的臨時密碼和授權碼。此指令碼也會在日誌中列印純文字程式碼,以供示範之用。但是,以純文字記錄保密內容是一項安全問題。當您的應用程式處於正式作業環境時,請勿在日誌中列印已解密的保密內容。
    在 index.js 檔案中新增相關程式碼,以進行從您的自訂電子郵件提供者傳送電子郵件訊息給使用者。

  2. 建立 .zip 封存檔,亦稱為壓縮的 index.js 檔案:

    $ zip function.zip index.js
  3. 開啟 Lambda 主控台

  4. 使用 Node.js 執行時期建立 Lambda 函數
    下列是使用 Node.js 14.x 執行時期建立 Lambda 函數的 AWS Command Line Interface (AWS CLI) 命令範例。
    **注意:**如果您在執行 AWS CLI 命令時收到錯誤訊息,請確定您使用的是最新版本的 AWS CLI

    $ aws lambda create-function --function-name CustomEmailSender --runtime nodejs14.x --handler index.handler --zip-file fileb://function.zip --role ExecutionRoleARN --region REGION

    **注意:**將 ExecutionRoleARN 取代為您要與 Lambda 函數相關聯的 AWS Identity and Access Management (IAM) 角色 Amazon Resource Name (ARN)。如需詳細資訊,請參閱 Lambda 執行角色。您可以將 CustomEmailSender 取代為您選擇的函數名稱。將 REGION 取代為 AWS 區域代碼。

  5. 安裝 @aws-crypto/client-node 和 base64-js 模組以使用 AWS Encryption SDK。
    如果您沒有安裝 @aws-crypto/client-node 模組,請執行以下動作。請確保在與 Lambda 相容的本機開發環境中執行安裝命令:
    建立工作目錄:

    $ mkdir -p aws-crypto-layer/nodejs

    變更工作目錄:

    $ cd aws-crypto-layer/nodejs

    使用 npm 軟體封裝管理工具,安裝最新版本的 aws-crypto 模組:

    $ npm install @aws-crypto/client-node
    
    $ npm install base64-js

    **注意:**最佳實務是在開發 Lambda 資源時,使用 Amazon Linux 2 環境。當您在 Windows 或 macOS 作業系統進行開發時,請使用 Docker 來安裝 aws-crypto 模組:

    $ docker run --entrypoint "" -v "$PWD":/var/task "public.ecr.aws/lambda/nodejs:14" /bin/sh -c "npm install @aws-crypto/client-node; exit"

    建立要上傳至 Lambda 層的 .zip 檔案:

    $ zip -r ../package.zip ../

    建立包含最新版本 @aws-crypto/client-node 模組的 Lambda 層:

    $ aws lambda publish-layer-version --layer-name node_crypto --description "My layer" --license-info "MIT" --compatible-runtimes nodejs14.x --zip-file fileb://../package.zip --region REGION

    將 Lambda 層添加到您的函數中:

    $ aws lambda update-function-configuration --function-name CustomEmailSender --layers arn:aws:lambda:us-east-2:123456789012:layer:node_crypto:1 --region REGION

    注意:用您的函數名稱替換「CustomEmailSender」。將 arn:aws:lambda:us-east-2:123456789012:layer:node_crypto:1 取代為 publish-layer-version 命令輸出中的 LayerVersionArn 值。將 REGION 取代為 AWS 區域代碼。

在 AWS KMS 中建立加密金鑰

Amazon Cognito 使用 AWS Key Management Service (AWS KMS) 對稱加密金鑰來加密由 Amazon Cognito 產生的臨時密碼和授權碼。

  1. 使用下列命令來建立 AWS KMS 金鑰:

    $ aws kms create-key --description "KMS Key for CustomEmailSender" --region REGION

    **注意:**將 REGION 取代為區域代碼。
    因為此命令未指定金鑰政策,系統會指派預設金鑰政策。若要將自訂金鑰政策套用至您的 AWS KMS 金鑰,請使用 JSON 政策--policy 參數新增至命令。請確定您已將 kms:CreateGrant 許可授予執行 UpdateUserPool 操作的 IAM 實體,以便新增自訂電子郵件觸發機制。
    當您執行 create-key 命令時,您無法指定別名。若要為新 KMS 金鑰建立別名,請使用 create-alias 命令:

    $ aws kms create-alias --alias-name alias/custom-email-key --target-key-id KeyId --region REGION

    **注意:**將 Keyid 取代為 create-key 命令輸出中的金鑰 ID 值。將 REGION 取代為區域代碼。
    此程式碼範例依賴環境變數 KEY_ALIASKEY_ARN 來取得加密金鑰資訊。您必須在 CustomEmailSender 的Lambda 觸發機制中設定這些環境變數。

    $ aws lambda update-function-configuration --function-name CustomEmailSender --environment 'Variables={KEY_ALIAS=alias/custom-email-key,KEY_ARN=key_ARN}' --region REGION

    **注意:**將 CustomEmailSender 取代為 Lambda 函數名稱。將 alias/custom-email-key 取代為 AWS KMS 金鑰的金鑰別名。將 key_ARN 取代為 create-key 命令輸出中的 ARN 值。將 REGION 取代為區域代碼。

  2. 授予 Amazon Cognito 服務主體可調用 Lambda 函數的 cognito-idp.amazonaws.com 許可。使用下列命令將許可授予調用 Lambda 函數的 Amazon Cognito 服務主體。

    $ aws lambda add-permission --function-name CustomEmailSender --statement-id "CognitoLambdaInvokeAccess" --action lambda:InvokeFunction --principal cognito-idp.amazonaws.com --source-arn UserPoolArn --region REGION

    **注意:**將 CustomEmailSender 取代為 Lambda 函數名稱。將 UserPoolArn 取代為使用者集區 ARN。若要尋找使用者集區 ARN,請開啟 Amazon Cognito 主控台使用者集區頁面。然後從清單中選取使用者集區。或者,執行 describe-user-pool 命令。將 REGION 取代為區域代碼。

  3. 更新 Amazon Cognito 使用者集區,以便它使用自訂電子郵件寄件者 Lambda 觸發機制。設定 UpdateUserPool API 中的 CustomEmailSender 參數。UpdateUserPool 需要使用者集區的所有現有參數以及您要變更的參數。Amazon Cognito 會將任何缺少參數的值設為預設值。如需詳細資訊,請參閱更新使用者集區組態
    在下列範例中,只有 --lambda-config 參數與 CustomEmailSender Lambda 函數詳細資料搭配使用。因此,該命令會將自訂電子郵件寄件者觸發機制新增至您的使用者集區,並將其餘的使用者集區參數設為預設值。如果您使用非預設值設定使用者集區,請傳遞 update-user-pool 命令中的值,避免參數被設為預設值。

    $ aws cognito-idp update-user-pool --lambda-config "CustomEmailSender={LambdaVersion=V1_0,LambdaArn= LambdaARN},KMSKeyID=KMSKeyARN" --user-pool-id UserPoolId --region REGION

    **注意:**將 LambdaARN 取代為 create-function 命令輸出中函數的 ARN 值。將 KMSKeyARN 取代為 create-key 命令輸出中提供的 ARN 值。將 UserPoolId 取代為 Amazon Cognito 使用者集區 ID。將 REGION 取代為區域代碼。

測試功能

若要測試 Lambda 函數的整合,請從使用者集區模擬使用者的電子郵件傳送者作業,例如電子郵件驗證或密碼復原。下列範例顯示由 Amazon Cognito 傳送至 Lambda 函數的 ForgotPassword 事件。

{  version: '1',
  triggerSource: 'CustomEmailSender_ForgotPassword',
  region: 'us-east-1',
  userPoolId: 'us-east-1_xxxxxxxx',
  userName: 'example_user',
  callerContext: {
    awsSdkVersion: 'aws-sdk-unknown-unknown',
    clientId: '12a3b4example-clientid'
  },
  request: {
    type: 'customEmailSenderRequestV1',
    code: 'XXXXeBlI7XP3RQmipedVF+7OGa4AgQACABVhdXXXXXXXvLXB1YmxpYy1rZXkAREF6Zk9NR2lBR0FUeDRITStmRHl4RDJyNlpqa2wvWktBbG45ckRmTEpMZ1A3THp4ME9RaVVjVHl3MVFOSEZjS3piZz09AAt1c2VycG9vbC1pZAATdXMtZWFzdC0xX29DOUhnUHVKWgABAAdhd3Mta21zAEthcm46XXdzOmttczp1cy1lYXN0LTE6XXX3XXc0NDA5OXXzOmtleS8yNmQ0ZjVmMy00YmZhLTQ0OXXtODUxZS01ZTM2ZWIwYjhmYjMAuAECAQB42Am0o+Rx0MgG+wLLyKtm1/vTm03JK3jQBZxqABAkreYBMOoAUtm3mLS7+kb2VL0SHgAAAH4wfAYJKoZIhvcNAQcGoG8wbQIBADBoBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDHjPPHlSWPt+UKrQOQIBEIA7oFUeGe2NPX2cuEVi+Qxwp8/IH1bgyYQut+QbbkElc1rXXXXXbeEVMjMkFQmQufmJyag9v1f+PUalvXwXAAAAAAwAABAAAAAAAAAAAAAAAAAAscZHg8dY/cKTskGQc065mv////8AAAABAAAAAAAAAAAAAAABAAAABpofXaVnP4pmf+yMoCElrOGy7Gn8pIUAZzBlAjEAn/7tuTNko8/HCwXXXXlCOJDeU0SSyB7o9y0TXHM7GptdvmB1JL9OzLxmUg6zChIhAjAFFbH4NrSblvwh/m0inDc11BpeOSKghtg8Pg5Nkf8eY6vmXX6GxjaCuyhBSO7IDcM=',
    clientMetadata: null,
    userAttributes: {
      sub: '1a2b3cde-33cd-402f-5g67-examplesub',
      'cognito:user_status': 'CONFIRMED',
      email_verified: 'true',
      email: 'user@example.com'
    }
  }
}

下列範例是純文字程式碼的回應:

CustomEmailSender_ForgotPassword: 12345

您可以在為 Lambda 函數建立的 Amazon CloudWatch 日誌群組中查看完整的日誌。如需如何查看這些日誌的詳細資料,請參閱將 Amazon CloudWatch Logs 與 AWS Lambda 搭配使用
安裝 @aws-crypto/client-node 和 base64-js 模組以使用 AWS Encryption SDK。

AWS 官方
AWS 官方已更新 1 年前