AWS Lambda と Amazon DynamoDB を使用してバックエンドの処理を実装する

# やりたいこと
前回の記事（https://qiita.com/mkttks/items/5220724fdd10ff51333d ）ではWebサイトにログイン機能を実装しました。今回はAWS LambdaとAmazon DynamoDBを使ってバックエンドの処理を実装します。（Webサイトとバックエンドの処理をつなぐのは次回です。）

内容は引き続き下記の公式チュートリアルに沿ったものです。
https://aws.amazon.com/jp/getting-started/hands-on/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/

# システム構成図
![lambdaとdynamoDBのシステム構成図](https://d1.awsstatic.com/Test%20Images/Kate%20Test%20Images/Serverless_Web_App_LP_assets_04.76030d61413ff43bd6aa75fbd16e02ad23aec67a.png)
公式チュートリアルから引っ張ってきた図だとこんな感じです。

# 手順

## Amazon DynamoDBでテーブルを準備する

まずAmazon DynamoDBでテーブルを準備します。Amazon DynamoDBはAWSでデータベースが使えるサービスです。データベースの中にデータを収める時の単位がテーブルですね。

### DynamoDBにアクセス
1. AWS Console( https://console.aws.amazon.com/ )にサインインして検索欄に「dynamo」と入力
1. 出てきたDynamoDBのアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/94871d52-f554-d925-0806-8e962e7d0965.png)

### テーブルを作成
1. 左のメニューの「テーブル」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/6ef29e3a-9295-88c1-994f-b41ef285019b.png)
1. 「テーブル」->「テーブルの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/0a0b9d29-10db-9b48-41e2-3252a9db6f44.png)
1. 「テーブルの作成」->「テーブルの詳細」->「テーブル名」に任意のテーブル名を入力（ここではRidesとします）
1. 「パーティションキー」に任意のキー名を入力（ここではRideIdとします）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/06b94dff-1acb-655e-9041-f07dd91be45a.png)
1. 他デフォルトのまま「テーブルの作成」をクリック
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/85721ddc-0fd4-cbf1-d047-e69af2fa26f9.png)

Ridesテーブルが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/693e39cd-eb9b-b1a5-3599-d496548a490d.png)

### テーブルのARNをメモ

次の手順で必要となるためテーブルのARNをメモしておきます。
ARNとはAWSで作ったいろんなものに付いているIDみたいなものです。

1. 「テーブル」のテーブル名をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/6ec9b5de-ed50-a391-db0f-40fe1e4cdd4c.png)
1.「概要」タブの「一般的な情報」の中に「追加情報」というドロップダウンがあるのでクリックして開く
1. 「Amazonリソースネーム（ARN）」が表示されるのでコピーしてメモ帳などに張り付けておく
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/fe0b2397-db78-6f11-9d62-4fdfca55f0bc.png)

## Lambda関数を準備する
続いてAWS LambdaでLambda関数を準備します。
LambdaとはAWSで関数作って動かせるよって感じのサービスです。Lambdaで作った関数のことをLambda関数と呼んでいます。

### Lambdaにアクセス

1. AWS Console( https://console.aws.amazon.com/ )にサインインして検索欄に「lambda」と入力
1. 出てきたLambdaのアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/8320dbdd-978a-1501-3963-a9ec372e9bb1.png)
1. 左のメニューの「関数」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/01261cfb-4211-6294-a951-3503f3495e5f.png)

### Lambda関数を作成

1. 「関数」->「関数の作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a2de99fb-4837-cd8d-adf2-1491e9401f1b.png)
1. 「関数の作成」->「一から作成」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/2ecf2999-550d-e210-961f-5810d6113193.png)
1. 「関数名」に任意の名前を入力（ここではRequestUnicornとします）
1. 「ランタイム」をNode.js 16.xにする
*このチュートリアルではNode.jsを使いますが、ランタイムの設定を変えることで他にJava、Python、Rubyなどのプログラミング言語が利用できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/8f740079-6637-c9d5-fee3-fe87b78bd1de.png)
1. 「アクセス権限」->「基本的な Lambda アクセス権限で新しいロールを作成」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/7ac83183-d7e6-ef2c-0b7b-6ab8ad78226b.png)
1. 「関数の作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/e7b36cb4-bbae-690a-c3d0-d59805e89016.png)

Lambda関数ができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a29ef4c9-fd1f-bf9a-81bf-55e2e6c07cba.png)

### Lambda関数のコードを変更

Lambda関数のコードを書き換えます。今回は公式が用意しているサンプルコード（requestUnicorn.js）をそのまま使います。

1. 以下のURLにアクセス
https://gist.github.com/connor11528/0c787fd42e6f4e17f348771ee5ae8f13
*公式チュートリアルのリンクがなぜか辿れなくなっていたので有志の方があげた別のリンクです
1. requestUnicorn.jsの中身をコピーする
1. 「Lambda」->「関数」->「（関数名）」の「コード」タブ->「コードソース」を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/96e8749a-c8f2-3b39-d6c2-5e2007d2786e.png)
1. index.jsの中身を削除し、コピーしたrequestUnicorn.jsの中身にすべて置き換える
（requestUnicorn.jsの中身はランダムなアイテムを生成してDynamoDBのRidesテーブルに書き込みにいくものです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/bf0d7cb2-976f-b47f-dfd4-2d00d7c9aa3d.png)
1. 「Deploy」ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/519b643b-16e2-a15d-aa65-f0b26382727b.png)

関数が正常に更新されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/b6cc2d1b-6f42-0f8c-54e8-fc545352e6c5.png)

### テスト実行
まだ手順は終わっていませんが、一度作ったLambda関数をテストしてみましょう。

1. 「コードソース」->「Test」ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a11c740c-c155-10c0-6b85-f811b78a44e5.png)
1. 「テストイベントを設定」->「新しいイベントを作成」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/7e0096b2-16a4-6cff-4da9-c996c75be7c9.png)
1. 「イベント名」に任意の名前を入力（ここではTestRequestEventとします）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/0eedab4c-32e5-df34-f343-79052c6b6f11.png)
1. 下記のテストイベントをコピーしてエディタに張り付ける
（この段落の一番下に置いてます。もしくはこちらからどうぞ https://aws.amazon.com/jp/getting-started/hands-on/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito/module-3/）
1. 「保存」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/d159e811-3259-a07a-10c0-f43aadab6d45.png)
1. 「Test」ボタンのドロップダウンでTestRequestEventを選択
1. 「Test」ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/983cb114-348e-9c6d-8aa9-ec6900c5445d.png)

↓テストイベント
```json
{
    "path": "/ride",
    "httpMethod": "POST",
    "headers": {
        "Accept": "*/*",
        "Authorization": "eyJraWQiOiJLTzRVMWZs",
        "content-type": "application/json; charset=UTF-8"
    },
    "queryStringParameters": null,
    "pathParameters": null,
    "requestContext": {
        "authorizer": {
            "claims": {
                "cognito:username": "the_username"
            }
        }
    },
    "body": "{\"PickupLocation\":{\"Latitude\":47.6174755835663,\"Longitude\":-122.28837066650185}}"
}
```

結果が返ってきました。ここでは500エラーが返ってきてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/a203db11-c8c4-3e6f-72d2-f3241263ddd7.png)
↓エラーメッセージ抜粋
`RequestUnicorn is not authorized to perform: dynamodb`

この関数はDynamoDBの実行権限がないと言われていますね。
初期状態のLambda関数は他のAWSのサービスで作ったものに読み書きする権限が与えられていません。次の手順で権限を付与していきます。

## Lambda関数にDynamoDBの権限を付与する

作ったLambda関数にDynamoDBのRidesテーブルへの書き込み権限を付与します。
AWSにおいて権限の管理はIAMロールというもので行います。実は前の手順でLambda関数を作ったときに「アクセス権限」->「基本的な Lambda アクセス権限で新しいロールを作成」で新しいIAMロールを作っていましたので、その設定を弄っていきます。

### IAMロールを編集する
1. 「Lambda」->「関数」->「（作った関数名）」を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/17dbfa1b-668f-e5be-450b-aa7c158f41c4.png)
1. 「設定」タブを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/128dc447-b13f-0e31-d026-5c1e769d3533.png)
1. 左のメニューの「アクセス権限」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/04a04e34-7f94-9d75-bd69-5b1c58154ef8.png)
1. 「実行ロール」->「ロール名」をクリック
（このRequestUnicorn-role--xxxxxxxが前の手順で自動的に作ったIAMロールです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/d31b423c-55cb-837c-737b-f308ff53913a.png)
1. 「許可」タブの「許可ポリシー」->「許可を追加」->「インラインポリシーを作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/ec0c65fd-3e9f-d2a3-0880-b1ff54348fb8.png)
1. 「アクセス許可を設定」->「ポリシーエディタ」->「サービスを選択」で検索欄にdynamodbと入力
1. 出てきたDynamoDBをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/e57df7ba-c2c7-b49e-df9e-b433ffaad229.png)
1. 「アクション許可」の検索欄にputitemと入力
1. 出てきた「PutItem」にチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/9d7bd585-67d4-a800-146e-7a6fbe3e9a4e.png)
1. 「リソース」で「特定」にチェックを入れる
1. 「ARNを追加」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/57a93b38-b318-9370-695b-b2ed60b7d631.png)
1. 「ARN」の一番下の欄に「テーブルのARNをメモ」の手順でメモしたARNを張り付ける
1. 「ARNを追加」をクリック
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/0d8d4461-f4da-f776-a108-d44178111235.png)
1. 「次へ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/16a1db7f-a7c8-9a55-09be-700c03021ed8.png)
1. 「確認して作成」->「ポリシーの詳細」->「ポリシー名」で任意の名前を入力（ここではDynamoDBWriteAccessとします）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/e391d146-b0f2-400d-ee8a-86e51700cd1f.png)
1. 「ポリシーの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/71874490-74d2-8583-a067-9ecb870b315a.png)

これでDynamoDBのRideテーブルに書き込みができるようになったはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/07b69ed1-b757-cee8-31ac-a47dce39c2ec.png)

# 動作確認

それでは動作確認してみましょう。

1. AWS Console( https://console.aws.amazon.com/ )にサインインして検索欄に「lambda」と入力
1. 出てきたLambdaのアイコンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/8320dbdd-978a-1501-3963-a9ec372e9bb1.png)
1. 左のメニューの「関数」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/01261cfb-4211-6294-a951-3503f3495e5f.png)
1. 関数名をクリック（ここではRequestUnicorn）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/106c3067-ec07-5b0c-d984-ec2e59f9c030.png)
1. 「コード」->「コードソース」の「Test」ボタンをクリック
（イベントはさっき作ったTestRequestEvent）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/7b195e0e-e174-c713-6051-879387a3c1e3.png)

結果が返ってきました。ステータスコードが200番台なので成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/4ec447a0-a2b3-ba2a-1afb-679fe5e7bddd.png)
DynamoDBに書き込みできているかも確認しましょう。DynamoDBにアクセスして「テーブル」->「（テーブル名）」（ここではRides）で「テーブルアイテムの探索」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/20d91c5d-7e81-d490-a688-ae949985ff6d.png)
「返された項目」で新しいアイテムができていたら書き込み成功です。お疲れさまでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492231/f2702f5d-7fd7-1fc5-2395-724b0762a93f.png)

# まとめ
今回はAWS Lambda と Amazon DynamoDB を使用してバックエンドの処理を実装しました。
次回はAPI GatewayでWebサイトからこの関数を実行できるようにします。次回でWebサイトは完成です！