CircleCI 用 IAM ユーザー作って初めての CI/CD

初めての CI / CD です。CircleCI を使ってみます。
CircleCI  用に権限を制限した IAM ユーザーで、go アプリを 自動テストして ECR、ECS に自動デプロイします。
管理者権限を持つ IAMユーザーで CircleCI を実行しようと思っていたのですが、アクセスキーやシークレットキーを預けておくのはなんとなく不安なので CircleCI 用の IAM ユーザーを試行錯誤しながら作ってみました。

## config.yml の作成
circleci の公式サイトにあるECR/ECS へのデプロイを参考に書きました。
goで作ったアプリをテストしてECR にプッシュして ECS にって感じです。

```.circleci/config.yml
version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@6.12.2
  aws-ecs: circleci/aws-ecs@1.3.0
jobs:
  Test:
    machine:
      image: circleci/classic:edge
    steps:
      - checkout
      - run:
          name: docker-compose build
          command: docker-compose build
      - run:
          name: docker-compose up
          command: docker-compose up -d
      - run:
          name: go test
          command: docker-compose run wecircles go test ./...
      - run:
          name: docker-compose down
          command: docker-compose down
workflows:
  build_and_push_image:
    jobs:
      - Test
      - aws-ecr/build-and-push-image:
          name: ECR
          requires:
            - Test
          filters:
            branches:
              only:
                - deploy
          account-url: AWS_ECR_ACCOUNT_URL
          repo: "${AWS_RESOURCE_NAME_PREFIX}"
          region: AWS_DEFAULT_REGION
          tag: "${CIRCLE_SHA1}"
      - aws-ecs/deploy-service-update:
          name: ECS
          requires:
            - ECR
          aws-region: AWS_DEFAULT_REGION
          family: "${AWS_RESOURCE_NAME_PREFIX}"
          cluster-name: "${AWS_RESOURCE_NAME_PREFIX}"
          container-image-name-updates: "container=${AWS_RESOURCE_NAME_PREFIX},tag=${CIRCLE_SHA1}"

```
細かいチェック以外なら、CircleCI CLI を使ってターミナルで

```terminal
circleci config validate
```
と打ち込んでチェックできて便利でした。（インストール方法はこちら ▶︎ https://circleci.com/docs/2.0/local-cli/）

あと、Circle CI の環境変数にちょっとハマりました。例えば、ECR job の region に ${AWS_DEFAULT_REGION}と 書いて CircleCI CLI でチェックすると、

```terminal
Error: Error calling workflow: 'build_and_push_image'
Error calling job: 'aws-ecr/build-and-push-image'
Type error for argument region: expected type: env_var_name, actual value: "${AWS_DEFAULT_REGION}" (type string)
```

とエラーが出て失敗します。あとで理由は調べてみようと思います。



## CircleCI 用 IAM ユーザーポリシーの作成
CircleCI 用 IAM ユーザーにアタッチするポリシーはこんな感じになりました。
なんの権限を与えればいいのか分からなかったので、合計20回くらいデプロイしてエラーを確認して権限を一個づつ増やしていきました。
Resource と ECR に * を使っている時点でこれが最小権限でないことは自明ですが、自分が可能な限り権限を小さくし、管理者権限に比べたら万一のアクセスキー流出時のリスクが遥かに下がりました。

```iam_policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:RegisterTaskDefinition",
                "ecr:*",
                "ecs:UpdateServicePrimaryTaskSet",
                "ecs:DescribeTaskDefinition",
                "ecs:CreateTaskSet",
                "ecs:UpdateService"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:aws:iam::<アカウントID>:role/ecsTaskExecutionRole"
        }
    ]
}
```

- ECRへのフルアクセス
- ECSへのいくつかのアクセス
- ECSのタスク実行ロールへのアクセス

これらの権限を与えています。

## 参考
- https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements_principal.html
- https://circleci.com/docs/ja/2.0/ecs-ecr/
- https://circleci.com/docs/2.0/local-cli/