CircleCIでbranchへのpushはテスト環境にデプロイする設定をしてみたがS3とCloudFrontの接続でちょっとミスした話

#目的
前回、GitHubへpushしたリソースをCircleCIを使ってS3へデプロイする構成を作ってみました。
今回はよりリアルな製品開発をイメージしてテスト環境と本番環境が分かれていることを想定し、branchへのコミットをテスト環境、masterへのコミットを本番環境へデプロイするようにs3とCiecleCIの設定を行いました。

その中でS3の設定でミスに気づきましたので、対処方法含め共有します。

#構成図
利用サービスやアーキテクトは前回と同じです。テストと本番の2環境となります。
![Arch5-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/21d71cd7-e158-f9c9-e687-026a7f5cdfa8.png)

![Arch4-test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/35fb59c3-b750-e1f2-5a55-245548b2723d.png)
#環境構築

##CircleCIのyaml設定
前回の設定値に「テスト環境のbucket名」とmasterへpushしなかった場合の処理を記載しました。
本来であればbranchへのpushを明示すべきですが、elseで処理してます。

```CircleCI:config.yml
version: 2
jobs:
  build:
    working_directory: ~/repo
    environment:
      - AWS_S3_BUCKET_NAME: my-bcuket
      - AWS_S3_BUCKET_NAME_TEST: my-bcuket-test
      - AWS_S3_BUCKET_EXCLUDE: .*/*
    docker:
      - image: innovatorjapan/awscli:latest
    steps:
      - checkout
      - run:
          name: Deploy to Master or Branch.
          command: |
            if [ "${CIRCLE_BRANCH}" == "master" ]; then
              aws s3 sync ~/repo s3://${AWS_S3_BUCKET_NAME}/ --exact-timestamps --delete  --exclude "${AWS_S3_BUCKET_EXCLUDE}"
            else
              aws s3 sync ~/repo s3://${AWS_S3_BUCKET_NAME_TEST}/ --exact-timestamps --delete  --exclude "${AWS_S3_BUCKET_EXCLUDE}"
            fi
```



##S3バケット作成
AWS_S3_BUCKET_NAME_TEST: で命名したbucketを作成します。
S3バケットの作成には「既存のバケットから設定をコピー」というオプションがあるので、前回作成した本番用バケットから設定をコピーしましたが、後述の理由で再作成となりました。
![s3_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/8c480a5f-c1a2-70b2-eb7b-0513e2bb93f0.png)

S3のアクセスログは今回は省略しました。
![s3_3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/d07dfa19-62f0-cc33-3590-9ae941933f4c.png)

作成後、バケットポリシーの設定をコピーします。**最終的にはここがエラーの原因だと気づきました。**

```s3:bucket.policy
{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bcuket-test/*"
        },
        {
            "Sid": "forCircleCi",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:user/CircleCI"
            },
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::webpage-my-bcuket-test",
                "arn:aws:s3:::webpage-my-bcuket-test/*"
            ]
        }
    ]
}
```
##CloudFront
前回作成した環境と同様にS3をオリジンとして設定します。
![CFConf4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/0f177aa1-73f1-1848-9c7f-cdb2c07aaa54.png)


##Route53レコードセット追加
レコードセットの作成からテスト環境のドメインを登録します。
![R53conf3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136929/2bf81285-808b-ffe1-bd9a-be4aafbe530d.png)

#接続できない
S3のAccess denyページが表示されてしまいました。
設定ドメインからS3のエラーページが見えたので、Route53とCloudfront間の設定は正しい、S3とCloudfront間の問題と気づきました。

#原因
CloudFront Origin Access Identityの値がなぜかCloudfrontから自動Updateされず、コピー元の設定が残ってしまいました。
おそらくパケットポリシーにCircleCiの許可設定など標準外の値が入っていたためだと推測しております。

```s3:bucket.policy
{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXX" #←これ
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bcuket-test/*"
        },
        {
            "Sid": "forCircleCi",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXXXX:user/CircleCI"
            },
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::webpage-my-bcuket-test",
                "arn:aws:s3:::webpage-my-bcuket-test/*"
            ]
        }
    ]
}
```
#対策
上記原因に気づくのに遅れ、S3バケットの作成をやりなおした結果無事テストページにアクセスできました。
Diffチェックを行えばもう少し早めに気づくことができ、S3の設定をコピーした後のパケットポリシーで、CloudFront Origin Access Identityの値を手動で変更すればアクセスできたと推察しております。

#所感
接続トラブルの際はパラメータは一つ一つ検証する必要があります。