GithubActionsでCloudFormationを使ったIAMユーザを管理する

# GithubActionsでCloudFormationを使ったIAMユーザを管理する（商用作業の承認フロー編）

IAMユーザをコード管理してますか？
普段はTerraformユーザなのですが、CloudFormationを使ってユーザ管理の仕組みを作ることがあったので
その時のGithubActionsについてご紹介したいと思います。

## やりたいこと


商用環境などでは、承認者の承認がなければ、開発者とはいえ、環境変更をさせないようにするようガバナンスを効かせたい時がある。
![作業承認の時のIAMユーザ管理.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120055/c55481eb-137c-a5be-2415-3717295925e7.png)

そう言った時、いちいちユーザを選んで、グループの変更をするのも大変だし、承認ボタン一つで終わらせたい。
承認者もGithubがつかえるので、他のCICDと同じくGithubActionsとCloudFormationで管理することにしました。

とりあえずGithubActionsのイメージ図
![GithubActionsのアーキテクチャ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120055/5f934c6a-06ea-fdd4-da5c-691493facbfd.png)


そんなわけで今回は下記三点を目的とした。
* 商用作業時の承認をGitHubで管理したい。
* 流行りのGitHubActionsを使いたい。
* マージボタン＝承認はかっこいい



## 　GitHubActionsのワークフローの設定

GithubActionsは.github/workflows/ の配下にyamlで定義すればよいらしい。
今回は
* AWS上にCloudFormationでデプロイするワークフロー
* せめてもの書式チェックするテスト

の二つ用意した。

### AWS上にCloudFormationでデプロイするワークフロー

```.github/workflows/release.yml
name: iam　user dev-release

on:
  push:
    branches:
      - dev-release

jobs:
  deploy-development:
    environment: development
    runs-on: [self-hosted, development]
    env:
      ProjectName: project-X    #プロジェクト名をパラメータに盛り込んでいるので指定（使ってなければ不要）
    steps:
      - name: Checkout
        uses: actions/checkout@v2.3.2

      - name: Aws credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-1　　
          
      - name: Pip install    #AWSCLIをCloudFormationのデプロイ時につかいたいのでGithubActionsの環境を作る
        run: |
          pip install --upgrade pip
          pip install -r requirements.txt

      - name: Deploy CFn
        env:
          CFnOptions: --capabilities CAPABILITY_NAMED_IAM --no-fail-on-empty-changeset 
        run: |
          aws cloudformation deploy \
          --stack-name iam-user-stack \
          --template iam-user.yml \
          --parameter-overrides ProjectName=${ProjectName} \
          ${CFnOptions}

```

####  補足   
* IAMのCFn実行のときは「--capabilities CAPABILITY_NAMED_IAM」をつけておく必要がある
* 変更がないときにチェンジセットがないとエラーになりがちなので「--no-fail-on-empty-changeset」もつける


### せめてもの書式チェックするテスト

```.github/workflows/ci.yml
name: voice-dx iam ci

on:
  pull_request:
    branches:
      - dev-release
      - master
  push:
    branches:
      - "**"

jobs:
  cnf-lint:
    runs-on: [self-hosted, development]

    steps:
      - uses: actions/checkout@v2

      - name: Pip install
        run: |
          pip install --upgrade pip
          pip install -r requirements.txt
      - name: Execute lint check
        run: |
          cfn-lint *.yml　   #ここはテストしたいCFnテンプレートファイルを置いてあるところを指定してください
 
```

ちなみに上記二つのワークフローで使っているrequirements.txtは一緒にしている（めんどくさいので）


```requirements.txt
awscliv2
cfn-lint
```


### CloudFormationの設定

```iam-user.yml
AWSTemplateFormatVersion: "2010-09-09"

Description: IAM user

Resources:
  TestUser:  #要変更、CFnテンプレートでユニークの必要があります
    Type: AWS::IAM::User
    Properties:
      UserName: testusername  #要変更、アカウントの中でユニークの必要があります
      Groups:
        - !Sub ${Env}-${ProjectName}-operators-group
      LoginProfile:
        Password: "xxxx" #初期パスワード、パスワードポリシーに沿ってないとCFnでエラーになります
        PasswordResetRequired: true #初期パスワード変更必須にするか

```

IAMユーザー管理のベストプラクティスに従い、権限に合わせてグループは事前に用意している。
こちらもCFnのテンプレートファイルを用意しているが今回は省略する。


## 残課題

### IAM管理の時のテンプレートファイルの分け方については最適解を模索している

1. IAMポリシー
2. IAMグループ
3. IAMロール
3. IAMユーザ

でファイルを分離し、順にデプロイしているが、
依存関係を紐付け切れておらず、CFnから消せなくなることがしばしばある。
あまり依存関係をがっつりかくのも大変だし、とりあえず運用できるレベルにはなっているが
たまに消す順番を誤ると、残骸が残ってしまうので、CFnの実行をマネコンから見届けるのが必須の状態が続いている。

### IAMユーザが初期パスワードから変更すると自動で消えない

CFnの辛いところだと思っているのだが、IAMユーザの作成まではスムーズだが、
その後ユーザ自身でパスワード変更やMFAの設定をしていると、
削除する時、該当ユーザのところをCFnテンプレートから消すと綺麗に消えない。IAMユーザのガワだけ残る


## まとめ

CFnテンプレートによるIAMユーザ管理には課題が残るが
GithubActionsの登場で、シンプルにCloudFormationを動かすことができるようになり、
商用環境における権限管理はGithubだけでできるようになったので、ガバナンスも担保し、セキュリティ意識も高く、非常に楽に運用できる。