Serverless Frameworkを使用したCogintoトリガの展開


最近、記事を投稿しましたpre signup triggers for AWS Cognito user pools . この記事はラムダ関数を使用してプリサインアップの検証を設定しました.
この記事では、同じ目標を達成する方法を説明します.しかし、AWSコンソールの代わりにServerless Frameworkを使用して、ランマイダとポリシーを展開して配備します.

セットアップ


まず、次のコマンドを使用してServerlessのフレームワークをインストールします.npm install -g serverless .
Serverlessがインストールされたら、次のコマンドでプロジェクトを作成しますserverless create --template aws-nodejs -n cognito-triggers .
上記のコマンドで、AWSクラウドプラットフォームでホストされることを意図したNodejs Serverlessプロジェクトを作成しています.その後、私たちはcognito-triggers プロジェクトのために.
このプロジェクトで必要な言語を自由に使用してください.あなたの言語のパッケージのインストールに従って、必要に応じてステップを構築してください.

実装


まず、作成しましょう.env 次のコンテンツを含むプロジェクトのルートファイル
COGNITO_USER_POOL_NAME=<user_pool_name>
COGNITO_USER_POOL_ID=<user_pool_id>
COGNITO_USER_POOL_ARN=<user_pool_arn>
REGION=us-west-2

複数の環境(たとえば、テスト、ステージング、生産)に展開している場合は、.env.{stage} . したがって、生産envファイルは.env.production .
このプロジェクトのために、我々は簡単のために1つのenvファイルに固執します.
このプロジェクトに必要ないくつかのパッケージを以下のコマンドでインストールしましょう.npm install @aws-sdk/client-cognito-identity-provider dotenv serverless-dotenv-plugin我々は、必要がありますdotenv and serverless-dotenv-plugin 環境変数を読み込みます.我々はまたserverless-offline パッケージがローカルにラムダ関数を呼び出したい場合にパッケージします.私たちはこの記事の中には入らないでしょうがnpm install -D serverless-offline .
あなたは、あることに気がつきますserveless.yml プロジェクトのルートでファイルします.ファイルを開き、次のコードを追加します
service: cognito-triggers

useDotenv: true

plugins:
  - serverless-dotenv-plugin
  - serverless-offline

frameworkVersion: '3'

上のコードでは、サービス名を設定しますuseDotenv: true 環境変数の読み込みを許可します.
プラグインのセクションには2つのプラグインがあります.
  • serverless-dotenv-plugin 環境変数を読み込みます.
  • serverless-offline ローカルマシン上でプロジェクトを実行する場合(ローカル関数を呼び出したい場合).
  • では、プロバイダを定義しましょう.
    provider:
      name: aws
      runtime: nodejs14.x
      stage: ${opt:stage, 'dev'}
      region: ${env:REGION}
      profile: default
      iam:
        role:
          statements:
            - Effect: 'Allow'
              Action: 'cognito-idp:ListUsers'
              Resource: '${env:COGNITO_USER_POOL_ARN}'
    
    package:
      patterns:
        - '!.gitignore'
    
    
    プロバイダ名をaws なぜなら、AWSプラットフォームを使っているからです.我々の選択の実行はNODEJS 14です.X .配備しているプラットフォームで利用できるランタイムを使用してください.
    ステージを設定するとき、我々は提供するのを好む--stage コマンドオプションで.指定しなかった場合はdev . これは、サービスをオフラインで実行したり展開したりするときに使用する環境ファイルを指示します.例えばsls offline --stage staging を使用してローカルマシンでサービスを実行します.env.stagingsls deploy --stage production サービスを.env.production ファイル.
    興味深い部分については、実際のラムダ関数!のトップレベルでserverless.yml プロバイダーセクションの右側にあるファイルを次のコードで機能セクションを作成します.
    functions:
      pre_signup:
        handler: ./src/pre_signup.handler
        events:
          - cognitoUserPool:
              pool: ${env:COGNITO_USER_POOL_NAME}
              trigger: PreSignUp
              existing: true
    
    
    The functions セクションは、我々が我々のサービスのラムダ関数を宣言するところです.ここではpre_signup 関数.
    The handler 関数のプロパティは、JSファイルによってエクスポートされたハンドラ関数を指します.パスがファイルの場所に一致することを確認します.ここではファイルをsrc プロジェクトのルートにあるフォルダ.
    The events プロパティは、このラムダ関数をトリガーするイベントの種類を決定します.これは、APIゲートウェイを通してのHTTPリクエストであるかもしれません、あるいは、我々のケースでは、ユーザープールへの認知サインアップ.
    既に既存のユーザープールを持っている場合は、existing プロパティtrue のためにcognitoUserPool ユーザープールの名前をpool プロパティ.
    すべてのプリサインアップロジックを処理するJS関数を作成しましょう.
    クリエイトアsrc プロジェクトのルートでフォルダを作成しpre_signup.js そのフォルダ内で.ファイルには次の内容があります.
    'use strict';
    require("dotenv").config({});
    
    const { COGNITO_USER_POOL_ID } = process.env;
    
    const {
      CognitoIdentityProviderClient,
      ListUsersCommand
    } = require("@aws-sdk/client-cognito-identity-provider");
    
    module.exports.handler = async (event, context, callback) => {
      const client = new CognitoIdentityProviderClient();
    
      const listUsersCommand = new ListUsersCommand({
        UserPoolId: COGNITO_USER_POOL_ID,
        Filter: `email = "${event.request.userAttributes.email}"`
      });
    
      const result = await client.send(listUsersCommand);
    
      if (result.Users.length > 0) return callback(new Error("Email is already in use."), event);
    
      callback(null, event);
    };
    
    
    このコードは、あなたが私の前の記事を読んだら、非常によく知られていますPre Signup Validation on AWS Cognito . 基本的に、我々は、このサインアップ試みで提供されたものと同じメールアドレスを持っている我々のユーザープールのユーザーをリストしています.0以上の場合、メールアドレスが既に使用中であることを示すエラーをスローします.
    注意してください、私たちはhandler 関数.この関数は、serverless.yml ファイル.
    ここにいる間、ユーザーのメールアドレスに送られるメッセージを編集する別の機能を作成しましょう.認知ユーザーのプールにはCustom message それが送られて、その内容を編集する前に、我々がメッセージを迎撃するのを許すトリガー.
    functions セクションserverless.yml , 関数を作成するcustom_message 次のプロパティー
      custom_message:
        handler: ./src/custom_message.handler
        events:
          - cognitoUserPool:
              pool: ${env:COGNITO_USER_POOL_NAME}
              trigger: CustomMessage
              existing: true
    
    
    別のハンドラーを参照して、Custommessageトリガーにフックすることを除いて、それはPreRise signup機能と同じです.
    src フォルダクリエイトcustom_message.js 以下の内容を持つファイル
    'use strict';
    require("dotenv").config({});
    
    module.exports.handler = async (event, context, callback) => {
      switch(event.triggerSource) {
        case "CustomMessage_SignUp":
          event.response.smsMessage = `Hi ${event.userName}, your signup code is ${event.request.codeParameter}`;
          event.response.emailSubject = `Your registration code`;
          event.response.emailMessage = `Hi ${event.userName}, your signup code is ${event.request.codeParameter}`;
          break;
        case "CustomMessage_ForgotPassword":
          event.response.smsMessage = `Hi ${event.userName}, your password reset code is ${event.request.codeParameter}. If you did not request this code, ignore this message. Please DO NOT share this code with anyone.`;
          event.response.emailSubject = `Your password reset code`;
          event.response.emailMessage = `Hi ${event.userName}, your password reset code is ${event.request.codeParameter}. If you did not request this code, ignore this email. Please DO NOT share this code with anyone.`;
          break;
        case "CustomMessage_ResendCode":
          event.response.smsMessage = `Hi ${event.userName}, your requested code is ${event.request.codeParameter}`;
          event.response.emailSubject = `Your requested code`;
          event.response.emailMessage = `Hi ${event.userName}, your requested verification code is ${event.request.codeParameter}`;
          break;
        default:
          event.response.smsMessage = `Hi ${event.userName}, your requested code is ${event.request.codeParameter}`;
          event.response.emailSubject = `Your requested code`;
          event.response.emailMessage = `Hi ${event.userName}, your requested code is ${event.request.codeParameter}`;
      }
      callback(null, event);
    }
    
    
    ハンドラはメッセージイベントに応じて異なるメッセージイベントをキャプチャし、関連するメッセージを表示します.CustomMessage_SignUp トリガーのソースは、サインアップ検証メールがトリガされます.CustomMessage_ForgotPassword パスワードリセットメールCustomMessage_ResendCode 手動のコード要求が引き起こされるとき(例えば未確認のとき、ログインを試みて).
    別のトリガーソースについての詳細情報を見つけることができますhere .
    このトリガのイベントオブジェクトは次のようになります.
    {
      version: '1',
      region: 'us-west-2',
      userPoolId: '<user_pool_id>',
      userName: '<username>',
      callerContext: {
        awsSdkVersion: 'aws-sdk-js-3.58.0',
        clientId: '<client_id>'
      },
      triggerSource: 'CustomMessage_SignUp',
      request: {
        userAttributes: {
          sub: 'd98dad2a-c2f3-4f97-bc49-a3ed3c81f27a',
          email_verified: 'false',
          'cognito:user_status': 'UNCONFIRMED',
          email: '<user_email_address>'
        },
        codeParameter: '{####}',
        linkParameter: '{##Click Here##}',
        usernameParameter: null
      },
      response: { smsMessage: null, emailMessage: null, emailSubject: null }
    }
    
    
    を含めることを確認しますcodeParameter あなたのカスタムメッセージで.

    展開


    アプリケーションを配備するには、次の手順に従います.sls deploy . 特定の環境に展開している場合は、--stage オプション(例:sls deploy --stage staging or sls deploy --stage production ).
    展開したサービスを削除したい場合はsls remove or sls remove --stage <stage> そして、このサービスで作成したかもしれないどんなリソースも一緒にサービスを破壊するでしょう.