今回は、公式サイトのチュートリアルに記載されていた簡単なWebアプリケーションを作成しようとした際にサービス間の連携がうまくできずエラーになってしまったので原因と解決方法をこちらに備忘メモとして記載したいと思います。
こちらのチュートリアルに則って作成しました。
手順は以下のモジュール1~5の流れとなります。
モジュール 1: ウェブアプリケーションを作成する
・Amplify コンソールでウェブアプリを作成
・ウェブアプリをテストする
モジュール 2: サーバーレス関数を構築する
・PythonでAWS コンソールを使用して Lambda 関数を一から作成する
・AWS コンソールで (JSON) イベントを作成して関数をテストする
モジュール 3: サーバーレス関数をウェブアプリケーションにリンクする
・API Gateway を使用して新しい API を作成する
・API で HTTP (ハイパーテキスト転送プロトコル) メソッドを定義する
・API から Lambda 関数をトリガーする
・API で CORS を有効にして、ウェブサイトから使用できるようにする
・AWS マネジメントコンソールから API Gateway で作成された API をテストする
モジュール 4: データテーブルを作成する
・AWS マネジメントコンソールで DynamoDB テーブルを作成する
・IAM でロールを作成し、アクセス許可を管理する
・AWS SDK (Python、JavaScript、または Java) を使用して DynamoDB テーブルに書き込む
モジュール 5: ウェブアプリケーションに対話性を追加する
・HTML ページから API Gateway API を呼び出す
・Amplify コンソールにウェブアプリケーションの新しいバージョンをアップロードする
各モジュール実行結果
モジュール1実行時スクショ
モジュール2実行時スクショ
モジュール3実行時スクショ
ここまでは順調だったのですが、
モジュール4内最後の手順、「変更をテストする」の箇所でテストを実行するとエラーが発生してしまいました。
エラー内容を確認すると、AccessDeniedExceptionが発生しており、
DBのarnの認証がうまくいっていない旨のメッセージが表示されています。
(AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::(IAMに設定しているロールのARN) is not authorized to perform
なぜ認証が通っていないのか?
原因として考えられること
・各サービスの設定がうまくいっていない
→各設定の見直し、再度作り直しを行ったが変化無しでした。
・リージョンが異なっている
→dynamoDBを確認してみるとリージョンが「バージニア北部」になっていました。
そこで「オレゴン」のDynamodbを確認してみると以下のように表示されました。
Lambdaで呼び出しているテーブルが見つからない旨のエラーが出ていました(CloudWatchなどではこのような内容のログが無かったので気づきませんでした)。
そこでオレゴンリージョンのDynamoDBにHelloWorldDatabaseテーブルを作成し、モジュール4でIAMポリシーに追加していたインラインポリシーを修正することに...
修正前
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem"
],
"Resource": "バージニア北部のリージョンで作成したテーブルの ARN "
}
]
}
修正後
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query",
"dynamodb:UpdateItem"
],
"Resource": "オレゴンのリージョンで作成し直したテーブルの ARN "
}
]
}
今回の原因
別のリージョンにあっても、同じリージョン内のDynamoDBには何もなかったので連携対象が無いとしてエラーが発生してしまっていました。
こちらのサイトを見ることでリージョンについて理解できました(公式の方にも説明があったかもしれないですが・・・)。
各「リージョン」ではAWSのサービスがそれぞれ独立して提供されており、言い方を変えると「リージョン」はお互いに完全に分離されるよう設計されたAWSのネットワークとサービスの「集合」となります。
クラウドを日常的に業務で使用している方やクラウドの概念をしっかり理解している方は躓かないところだと思うのですが、リージョンに対して「地理的に離れた領域」であるという認識だけで各「リージョン」ではAWSのサービスがそれぞれ独立して提供されているということを知らないと、複数のサービスを連携させる際に各設定は間違っていないはずなのにうまく動かないという事態が発生してしまうかもしれません(そんなことをするのは私くらいかもしれないですが…)。
今後注意したいと思います。