Amplify、Cognitoを使ったサーバレスウェブアプリ構築ハンズオンをやってみた

Serverless Web Applicationについて手軽に学べるハンズオンを紹介します。

こんにちは。AWS事業本部トクヤマシュンです。

フルスタックエンジニアが持て囃される昨今、皆さんフルスタックしていますか?
残念ながら、私はできていません。
インフラ中心に業務を経験してきたので、どうもアプリ周りには疎くて、、、

このままじゃいけない!
思い立ったが吉日、まずは手始めにサーバレスウェブアプリケーションを構築するAWSのハンズオンをやってみました。
ハンズオンはこちら

想定読者

  • Amplify/Cognitoを手軽に試したい
  • サーバレスウェブアプリ構築をやってみたい

ハンズオンの構成

serverless-hands-on-architecture

  1. AWS Amplify
    • 静的ウェブホスティングを担当
  2. Amazon Cognito
    • ユーザ管理基盤を担当
  3. Amazon API Gateway, AWS Lambda, Amazon DynamoDB
    • RESTful API、サーバレスバックエンド処理を担当

では、順に設定します。

1. 静的ウェブホスティングの構築

AWS Amplify Consoleを利用すると、シンプルなCI/CDワークフローを用いて
簡単に静的ウェブサイトをホスティングできます。

Gitリポジトリの構築

まずはCI/CDワークフローを構築するためのGitリポジトリを準備します。
リポジトリサービスとしてはGitHub/Bitbucket/GitLab/AWS CodeCommitが利用可能です。
今回はハンズオン手順にしたがってAWS CodeCommitで進めてみます。

コンソールから「test-site」リポジトリを作成し、ソースをアップロードします。

ウェブアプリのソースは、ハンズオンで提供されるAmazon S3バケットから取得し、
「test-site」リポジトリにpushしています。

AWS Amplify Consoleでウェブホスティングの有効化

AWS Amplify ConsoleによってCI/CDワークフローを構築し、
ウェブホスティングを行っていきます。

コンソールから「ウェブアプリケーションをホスト」を選択し、
リポジトリサービスとしてAWS Code Commitを指定します。

先ほど作成した「test-site」リポジトリを指定し、次に進みます。

ビルド用設定はソースに応じて自動設定されます。
今回は変更不要で、次に進みます。

すべてデフォルト設定で進めると、プロビジョン→ビルド→デプロイ→検証とワークフローが進んでいき、ホスティングが完了します。

URLにアクセスすると画面が表示され、ホスティング成功が確認できます。

静的サイトの実体としてはAmazon CloudFrontやAmazon S3を使っているはずですが、
それらはAWS管理のリソースとなり、自分のアカウントからは確認できません。
そのため細かなチューニングはできません。

ただ、数クリックで静的ウェブホスティングのCI/CDワークフローが構築できました。
この手軽さは本当に素晴らしい!!

2. ユーザ管理基盤の構築

次に、Amazon Cognitoを使ったユーザ管理基盤を構築します。

Amazon Cognitoユーザープール作成

まずは、Amazon Cognitoユーザープールをコンソール画面から作成します。
プール名のみ「test-site」を指定し、他はデフォルトのままで進めていきます。

ユーザープールが作成できました。
プールIDは後で必要となるので、覚えておきます。

Amazon Cognitoアプリクライアント作成

次に、アプリクライアントからユーザープールにアクセスするための設定をします。
アプリクライアント名に「test-site-app」を指定し、「クライアントシークレットを生成」のチェックを外し、他はデフォルトで作成します。

アプリクライアントが作成できました。
アプリクライアントIDは後で必要となるので、覚えておきます。

アプリのAmazon Cognito設定更新

アプリの「js/config.js」ファイルのcognitoセクションを更新します。

js/config.js

window._config = {
    cognito: {
        userPoolId: '', // プールIDを記載。e.g. us-east-2_uXboG5pAb
        userPoolClientId: '', // アプリクライアントIDを記載。e.g. 25ddkmj4v6hfsfvruhpfi7n4hv
        region: '' // デプロイするリージョンを記載。e.g. ap-northeast-1
    },
    api: {
        invokeUrl: '' // 今は記載不要。e.g. https://rc7nyt4tql.execute-api.us-west-2.amazonaws.com/prod',
    }
};

これにより、ウェブアプリからAmazon Cognitoユーザープールに連携できます。

更新したファイルをAWS CodeCommitにpushするとCI/CDワークフローが動作し、
自動でホスティングの更新まで行ってくれます。

サイトにアクセスし、登録フォームからユーザ作成を行います。
今回はID:「test@example.com」で作成しました。

コンソールを確認すると、ユーザプールにID登録ができています。
ステータスは「UNCONFIRMED」で未確認状態のため、上のユーザーの確認をクリックします。

ユーザ確認ができました。
この状態であれば、ユーザからログインが可能となります。

なお、ユーザ確認は今回のようにコンソール画面からも行えますし、
メールアドレスに届くコードを使ってユーザ自身の確認も可能です。

3. サーバレスバックエンドの構築

次に、静的ウェブアプリから実行される、サーバレスバックエンドを構築します。

Amazon DynamoDBテーブルの作成

コンソールからAmazon DynamoDBテーブルを作成します。
テーブル名は「Rides」、パーティションキーは「RideId」でキータイプは「文字列」、他はデフォルト設定で作成まで進みます。

作成できたら、あとで使うためARNを覚えておきます。

AWS Lambda関数のIAMロールを作成

コンソールから、AWS Lambda関数実行のためのIAMロール「WildRydesLambda」を作成します。
このロールには2つのポリシーを設定します。

  • AWSLambdaBasicExecutionRole
    • Amazon CloudWatch Logsに書き込みを行うための管理ポリシー
  • WildRydesLambda
    • 先ほど作成したAmazon DynamoDBの「Rides」テーブル操作を行うためのインラインポリシー

まずはIAMロールの作成画面で、信頼されたエンティティタイプは「AWSのサービス」、ユースケースは「Lambda」を選択し、次に進みます。

許可ポリシーに「AWSLambdaBasicExecutionRole」を設定し、次に進みます。

ロール名に「WildRydesLambda」を設定し、ロールを作成します。

次に、作成したIAMロール「WildRydesLambda」にインラインポリシーを追加します。
IAMロールを選択し、「アクセス許可を追加」→「インラインポリシーを作成」をクリックします。

下記を設定し、ポリシーの確認をクリックします。

  • サービス:DynamoDB
  • アクション:PutItem
  • リソース:tableに先ほど作成したDynamoDBテーブルのARN

名前に「DynamoDBWriteAccess」を設定し、ポリシーの作成をクリックします。

以上でIAMポリシーの作成は完了です。

Lambda関数の作成

コンソールから、Amazon DynamoDBの「Rides」テーブルに指定された値を書き込むための
AWS Lambda関数「RequestUnicorn」を作成します。
下記を設定し、ポリシーの確認をクリックします。

  • 関数名:RequestUnicorn
  • ランタイム:Node.js
  • 既存のロール:WildRydesLambda

ハンズオンサイトではNode.jsのバージョンは「6.10」を選択するよう記載がありますが、今回「14.x」でも動作しました。

AWS Lambda関数が作成できたら、関数コード「index.js」をrequestUnicorn.jsの内容に置き換えます。

4. RESTful APIの構築

最後に、Amazon API Gatewayを利用したRESTful APIを構築します。

REST APIの作成

Amazon API Gatewayコンソールから新しいREST APIを作成します。
API名を「WildRydes」、エンドポイントタイプを「エッジ最適化」にしてAPIを作成します。

Amazon Cognitoユーザープールオーソライザーの作成

作成したREST APIとAmazon Cognitoユーザープールを紐づけ、APIコールの認証設定をします。
ナビゲーションバーの左側のオーソライザーから、下のパラメーターを指定して作成します。

  • 名前:WildRydes
  • タイプ:Cognito
  • Cognitoユーザープール:test-site
  • トークンのソース:Authorization

これによって、サインインしている(=IDトークンが発行されている)時にのみ、
APIコールを認可するよう設定ができました。

Amazon API Gatewayのリソースとメソッドの作成

ナビゲーションバーの左側のリソースから、下のパラメーターを指定してリソースを作成します。

  • リソース名:ride
  • リソースパス:/ride
  • API Gateway CORSを有効にする:チェック

次に、rideリソースのPOSTメソッドを作成します。
POSTメソッドのセットアップでは、下のパラメーターを指定してリソースを作成し、保存します。

  • 統合タイプ:Lambda関数
  • Lambdaプロキシ統合の使用:チェック
  • Lambdaリージョン:ap-northeast-1
  • Lambda関数:RequestUnicorn

この時、関数を呼び出すための許可をAmazon API Gatewayに付与するように求められたら、[OK] を選択します。
メソッドリクエストのカードを選択し、認可のプルダウンリストからCognitoユーザープールオーソライザー「WildRydes」を選択し、チェックマークをクリックします。

これにより、POSTリクエストのAuthorizationヘッダーにCognitoユーザープールオーソライザー「WildRydes」で認証された正しいIDトークンが指定されている場合にのみ、Lambda関数の実行が可能となります。

APIのデプロイ

Amazon API Gatewayコンソールのアクションドロップダウンから、APIのデプロイを選択します。 下のパラメーターを指定してデプロイを行います。

  • デプロイされるステージ:[新しいステージ]
  • ステージ名:prod

デプロイ後に表示されるURL(URLの呼び出し)は後で利用するので覚えておきます。

アプリケーションにAPIを呼び出すURLを設定

アプリの「js/config.js」ファイルのapiセクションを更新します。

js/config.js

window._config = {
    cognito: {
        userPoolId: '', // プールIDを記載。e.g. us-east-2_uXboG5pAb
        userPoolClientId: '', // アプリクライアントIDを記載。e.g. 25ddkmj4v6hfsfvruhpfi7n4hv
        region: '' // デプロイするリージョンを記載。e.g. ap-northeast-1
    },
    api: {
        invokeUrl: '' // API Gatewayデプロイ後に表示されるURLを記載。e.g. https://rc7nyt4tql.execute-api.us-west-2.amazonaws.com/prod',
    }
};

これにより、アプリケーションのクリックイベントをトリガーとして、デプロイしたAPIの呼び出しが可能となります。

更新したファイルをAWS CodeCommitにpushすると、サーバレスウェブアプリケーションの構築は完了です。

5. 動作確認

ログイン後、/rideページに表示される地図をクリックします。
Amazon API Gateway → AWS Lambda → Amazon DynamoDBのフローで
イベント情報のAmazon DynamoDBテーブルへの書き込みが確認できました。
左側にAmazon DynamoDB、右側にウェブアプリケーションを配置したデモを載せておきます。

オススメのハンズオンです

今回、サーバレスウェブアプリ構築ハンズオンをやってみました。
アプリの構築だけでなく、コードも読み進めながら行ったところ、所要時間は4時間程度でした。
構築を試すだけであれば、2時間程度で完了できるかと。

結構お腹いっぱいにはなりますが、サーバレスウェブアプリケーションを構築してみたい未経験者にはオススメです!
ハンズオンの後には、作成したリソースの削除をお忘れなく。