Como uso o gatilho personalizado do remetente de e-mail do Lambda nos grupos de usuários do Amazon Cognito?

8 minuto de leitura
0

Preciso invocar o gatilho do AWS Lambda do remetente de e-mail personalizado do Amazon Cognito para processar e entregar mensagens de e-mail.

Resolução

Use um gatilho de remetente de e-mail personalizado do Amazon Cognito para permitir que provedores terceirizados enviem notificações por e-mail para seus usuários a partir do código de função do Lambda. O Amazon Cognito envia solicitações de mensagens de e-mail para uma função do Lambda. Em seguida, a função do Lambda processa e entrega as mensagens de e-mail.

Criar uma função do Lambda para ser seu gatilho personalizado de remetente de e-mail

1.    Crie um arquivo com o nome index.js, adicione o código a seguir ao arquivo e salve suas alterações.

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;
};

Aviso: Esse código é programado para decifrar segredos criptografados. Os segredos são senhas temporárias e códigos de autorização enviados pelo Amazon Cognito. O script também imprime o código de texto simples em logs para fins de demonstração. No entanto, o registro em log de segredos em texto simples é um problema de segurança. Quando sua aplicação estiver em produção, NUNCA imprima segredos decifrados em logs.

Adicione o código relevante no arquivo index.js para enviar mensagens de e-mail a usuários do seu provedor de e-mail personalizado.

2.    Crie um arquivamento .zip, também conhecido como arquivo index.js compactado:

$ zip function.zip index.js

3.    Abra o console do Lambda.

4.    Crie uma função do Lambda com um runtime Node.js.

Veja a seguir um exemplo de comando da AWS Command Line Interface (AWS CLI) para criar uma função do Lambda com o runtime Node.js 14.x.

Observação: Se você receber erros ao executar os comandos da AWS CLI, utilize a versão mais recente da AWS CLI.

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

Observação: Substitua <ExecutionRoleARN> pelo nome do recurso da Amazon (ARN) do perfil do AWS Identity and Access Management (IAM) que você deseja associar à função do Lambda. Para obter mais detalhes, consulte Função de execução do Lambda. Você pode substituir CustomEmailSender pelo nome da função de sua escolha. Substitua <specify a region> pelo seu código de região da AWS.

5.    Instale o módulo @aws-crypto/client-node para usar o SDK de criptografia da AWS.

Se você não tiver o módulo @aws-crypto/client-node instalado, deverá concluir as seguintes tarefas de alto nível:

  • Instale o módulo.
  • Empacote a versão mais recente do módulo.
  • Crie uma camada do Lambda que contenha a dependência que você pode usar com a função do Lambda.

Observação: Execute os comandos de instalação em um ambiente de desenvolvimento local compatível com o Lambda.

Crie um diretório de trabalho:

$ mkdir -p aws-crypto-layer/nodejs

Altere o diretório de trabalho:

$ cd aws-crypto-layer/nodejs

Instale a versão mais recente do módulo aws-crypto com o gerenciador de pacotes npm:

$ npm install @aws-crypto/client-node

Observação: É uma prática recomendada usar um ambiente do Amazon Linux 2 ao desenvolver recursos do Lambda. Use o Docker para instalar o módulo aws-crypto ao desenvolver com um sistema operacional Windows ou macOS:

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

Crie um arquivo .zip a ser carregado na sua camada do Lambda:

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

Crie uma camada do Lambda que inclua a versão mais recente do módulo @aws-crypto/client-node:

$ 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 <specify a region>

Adicione a camada do Lambda à sua função:

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

Observação: Substitua CustomEmailSender pelo nome da sua função. Substitua arn:aws:lambda:us-east-2:123456789012:layer:node_crypto:1 pelo valor LayerVersionArn da saída do comando publish-layer-version. Substitua <specify a region> pelo seu código de região.

Criar uma chave de criptografia no AWS KMS

O Amazon Cognito usa uma chave de criptografia simétrica do AWS Key Management Service (AWS KMS) para criptografar senhas temporárias e códigos de autorização gerados pelo Amazon Cognito.

1.    Criar uma chave do AWS KMS:

$ aws kms create-key --description "KMS Key for CustomEmailSender" --region <specify a region>

Observação: Substitua <specify a region> pelo seu código de região.

Como esse comando não especifica uma política de chave, a política de chave padrão é atribuída. Para aplicar uma política de chave personalizada à sua chave do AWS KMS, adicione o parâmetro --policy ao comando com sua política JSON. Certifique-se de conceder a permissão kms:CreateGrant à entidade do IAM que executa a operação UpdateUserPool para adicionar um gatilho de e-mail personalizado.

Você não pode especificar um alias ao executar o comando create-key. Para criar um alias para a nova chave KMS, use o comando create-alias:

$ aws kms create-alias --alias-name alias/custom-email-key --target-key-id <KeyId> --region <specify a region>

Observação: Substitua <KeyId> pelo valor do ID da chave da saída do comando create-key. Substitua <specify a region> pelo seu código de região.

O exemplo de código se baseia nas variáveis de ambiente KEY_ALIAS e KEY_ARN para informações sobre chaves de criptografia. Você deve configurar essas variáveis de ambiente no gatilho do Lambda CustomEmailSender.

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

Observação: Substitua CustomEmailSender pelo nome da sua função do Lambda. Substitua alias/custom-email-key pelo alias de chave da sua chave do AWS KMS. Substitua <key_ARN> pelo valor do ARN da saída do comando create-key. Substitua <specify a region> pelo seu código de região.

Conceda à entidade principal do serviço Amazon Cognito a permissão cognito-idp.amazonaws.com para invocar a função do Lambda

Use o comando a seguir para conceder permissão à entidade principal do serviço Amazon Cognito para invocar a função do Lambda:

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

Observação: Substitua CustomEmailSender pelo nome da sua função do Lambda. Substitua <UserPoolArn> pelo ARN do seu grupo de usuários. Para encontrar o ARN do grupo de usuários, abra a página User pools (Grupos de usuários) do console do Amazon Cognito. Em seguida, selecione o grupo de usuários na lista. Ou execute o comando describe-user-pool. Substitua <specify a region> pelo seu código de região.

Atualize o grupo de usuários do Amazon Cognito para que ele use um gatilho do Lambda personalizado do remetente de e-mail

Atualize o grupo de usuários definindo o parâmetro CustomEmailSender na API UpdateUserPool. UpdateUserPool requer todos os parâmetros existentes do seu grupo de usuários e os parâmetros que você deseja alterar. O Amazon Cognito define os valores de quaisquer parâmetros ausentes de acordo com seus padrões. Para obter mais informações, consulte Atualizar a configuração do grupo de usuários.

No exemplo a seguir, somente o parâmetro --lambda-config é usado com os detalhes da função do Lambda CustomEmailSender. Portanto, o comando adiciona o gatilho personalizado do remetente de e-mail ao seu grupo de usuários e define os parâmetros restantes do grupo de usuários como padrão. Se você configurar seu grupo de usuários com valores não padrão, transmita os valores no comando update-user-pool para evitar defini-los como padrão.

$ aws cognito-idp update-user-pool --lambda-config "CustomEmailSender={LambdaVersion=V1_0,LambdaArn= <LambdaArn>},KMSKeyID=<KMSKeyArn>" --user-pool-id <UserPoolId> --region <specify a region>

Observação: Substitua <LambdaArn> pelo valor do ARN da função na saída do comando create-function. Substitua <KMSKeyArn> pelo valor do ARN fornecido na saída do comando create-key. Substitua <UserPoolId> pelo seu ID de grupo de usuários do Amazon Cognito. Substitua <specify a region> pelo seu código de região.

Testar a funcionalidade

Para testar a integração da função do Lambda, simule uma operação de remetente de e-mail para um usuário do seu grupo de usuários, como verificação de e-mail ou recuperação de senha. O exemplo a seguir mostra um evento ForgotPassword enviado à função do Lambda pelo Amazon Cognito.

{
  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'
    }
  }
}

O exemplo a seguir é uma resposta em código de texto simples:

CustomEmailSender_ForgotPassword: 12345

Você pode ver os logs completos no grupo de logs do Amazon CloudWatch criado para sua função do Lambda. Para obter mais detalhes sobre como ver esses logs, consulte Acesso aos logs do Amazon CloudWatch para AWS Lambda.

AWS OFICIAL
AWS OFICIALAtualizada há um ano