異なるリージョンでサービスを連携させようとしてAccessDeniedExceptionを発生させた話

今回は、公式サイトのチュートリアルに記載されていた簡単なWebアプリケーションを作成しようとした際にサービス間の連携がうまくできずエラーになってしまったので原因と解決方法をこちらに備忘メモとして記載したいと思います。

[こちら](https://aws.amazon.com/jp/getting-started/hands-on/build-web-app-s3-lambda-api-gateway-dynamodb/)のチュートリアルに則って作成しました。
手順は以下のモジュール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実行時スクショ
![モジュール1_失敗ver_編集後.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/e7ada412-c991-85b1-4c2d-9cf41f53dc72.jpeg)
モジュール2実行時スクショ
![モジュール2_失敗２_編集後.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/b473a7b1-7e55-ecb7-5e35-f56fea5fb69a.jpeg)
モジュール3実行時スクショ
![モジュール3_失敗_API作成_オレゴン4編集後.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/85650f6d-6812-1926-ab0d-e8f9ba8a8652.jpeg)


ここまでは順調だったのですが、
モジュール4内最後の手順、「変更をテストする」の箇所でテストを実行するとエラーが発生してしまいました。

モジュール4実行時スクショ
![モジュール4_失敗4編集後.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/b1d28f83-2512-2a3b-eaf2-ac488a75e236.jpeg)

エラー内容を確認すると、AccessDeniedExceptionが発生しており、
DBのarnの認証がうまくいっていない旨のメッセージが表示されています。

```(AccessDeniedException) when calling the PutItem operation: User: arn:aws:sts::（IAMに設定しているロールのARN） is not authorized to perform```


## なぜ認証が通っていないのか？
原因として考えられること
・各サービスの設定がうまくいっていない
→各設定の見直し、再度作り直しを行ったが変化無しでした。
・リージョンが異なっている
→dynamoDBを確認してみるとリージョンが「バージニア北部」になっていました。

そこで「オレゴン」のDynamodbを確認してみると以下のように表示されました。
![モジュール4_失敗5編集後.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/9c64a03e-c304-1168-a3e7-cb49472ca802.jpeg)

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 "
    }
    ]
}
```

すると
無事起動できました！
![API実行成功.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/c82fd52d-c07c-fc44-e30d-73eb8e64d111.jpeg)


## 今回の原因
別のリージョンにあっても、同じリージョン内のDynamoDBには何もなかったので連携対象が無いとしてエラーが発生してしまっていました。

[こちら](https://codezine.jp/article/detail/9787)のサイトを見ることでリージョンについて理解できました（公式の方にも説明があったかもしれないですが・・・）。
```各「リージョン」ではAWSのサービスがそれぞれ独立して提供されており、言い方を変えると「リージョン」はお互いに完全に分離されるよう設計されたAWSのネットワークとサービスの「集合」となります。```

つまり、今回作成したアプリの構成が
![構成図1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/7c1d86a5-634b-624a-7019-2504f529d6f4.jpeg)

上記ではなく、以下のようになってしまっていました。
![構成図2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423172/d923c1f8-38a8-abe1-cc52-f772d4b3b9b7.jpeg)



クラウドを日常的に業務で使用している方やクラウドの概念をしっかり理解している方は躓かないところだと思うのですが、リージョンに対して「地理的に離れた領域」であるという認識だけで各「リージョン」ではAWSのサービスがそれぞれ独立して提供されているということを知らないと、複数のサービスを連携させる際に各設定は間違っていないはずなのにうまく動かないという事態が発生してしまうかもしれません（そんなことをするのは私くらいかもしれないですが…）。
今後注意したいと思います。