IAMポリシーをAnsibleで管理する


#はじめに
以前、[AnsibleでIAMユーザおよびグループを管理するPlaybook](http://qiita.com/tomohiko_isobe/items/5ae6f15f52a2d20e2635)をご紹介しましたが、今回はAnsibleでIAMポリシーを管理してみたいと思います。

#やること
- グループにインラインポリシーアタッチ
- グループに管理ポリシーアタッチ

##ポイント
- Ansibleのモジュールは管理ポリシーの操作に対応していないので、AWS CLIにて実装
	
#注意
ポリシーのデタッチには対応していません。
ユーザへのアタッチ、ロールについては今回はフォローしていません。

#前提
- AWS関連のモジュール実行にはbotoが必要です。
- AWS CLIが必要です。
- credential情報は環境変数か`aws configure`でセットしてある必要があります。

#sample

以下のグループにインラインポリシーとAWS管理ポリシーをアタッチします。
ポリシー内容はサンプルなので適当です。

- ansible
	- インラインポリシー
		- SourceIpを制限したAdminポリシー
	- AWS管理ポリシー
		- CloudWatchReadOnlyAccess
		- AmazonEC2ReadOnlyAccess


##ディレクトリ構成

```bash:ディレクトリ構成
site.yml
roles/
|--iam/
|  |--tasks/
|  |  |--main.yml
|  |--templates/
|  |  |--admin_policy.json.j2
group_vars/
|--group.yml
```

##vars

こんな感じに変数を定義します。

```yaml:group_vars/group.yml
---
my_vars:
  aws:
    iam:
      inline_policies:
        - group_name: ansible
          policy:
            - name: admin_ip_restricted
              template: admin_policy.json.j2
              params:
                condition: '{"IpAddress": {"aws:SourceIp": ["XX.XX.XX.XX/32"]}}'
      managed_policies:
        - group_name: ansible
          policy:
            - arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess
            - arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess
```

##Role

インラインポリシーは、jsonのテンプレートを読み込んで定義します。

管理ポリシーのアタッチについては、shellモジュールでAWS CLIを実行しています。
重複実行してもエラーとはなりませんが、毎回ステータスがchangedになってしまうので、アタッチ済みポリシーと突き合わせます。

`aws iam list-attached-group-policies`によりターゲットグループにアタッチされている管理ポリシーのARNを取得し、結果のjsonを`from_json`フィルタを通してset_factモジュールに渡すと、そのままグループごとに`<<グループ名>>_policies`というARNのリストが生成されます。

whenにより、上記リストに追加したい管理ポリシーARNがあるかどうかを判定しています。

```yaml:roles/iam/tasks/main.yml
---
- name: IAM Inline-Policy作成
  iam_policy:
    profile: "{{ lookup('env', 'AWS_DEFAULT_PROFILE') }}"
    iam_type: group
    iam_name: "{{ item.0.group_name }}"
    policy_name: "{{ item.1.name }}"
    state: present
    policy_json: "{{ lookup( 'template', item.1.template ) }}"
  with_subelements:
    - "{{ my_vars.aws.iam.inline_policies }}"
    - policy

- name: Get managed-policy list
  shell: >-
    aws iam list-attached-group-policies \
     --group-name {{ item.group_name }} \
     --query 'AttachedPolicies[].PolicyArn'
  changed_when: no
  with_items: "{{ my_vars.aws.iam.managed_policies }}"
  register: iam_managed_policies

- name: Create managed-policy list
  set_fact:
    "{{ item.item.group_name }}_policies": "{{ item.stdout | from_json }}"
  with_items: "{{ iam_managed_policies.results }}"
  when: not ansible_check_mode

- name: Attach managed-policy
  shell: >-
    aws iam attach-group-policy \
     --group-name {{ item.0.group_name }} \
     --policy-arn {{ item.1 }}
  with_subelements:
    - "{{ my_vars.aws.iam.managed_policies }}"
    - policy
  when: "'{{ item.1 }}' not in {{ item.0.group_name }}_policies"
```

##templates
```yaml:roles/iam/templates/admin_policy.json.j2
{% set params = item.1.params %}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
{% if params.condition is defined %}
      "Resource": "*",
      "Condition": {{ params.condition }}
{% else %}
      "Resource": "*"
{% endif %}
    }
  ]
}
```

#まとめ
これでマネコンからだと分かりづらいポリシーを管理しやすくなるかと思います。
[こちらのRole](http://qiita.com/tomohiko_isobe/items/5ae6f15f52a2d20e2635)の後ろに連結して一つのRoleとしても使えますのでお試しください。

#参考
##AnsibleでAWSリソースを管理するシリーズ
- [VPCをAnsibleで作成する](http://qiita.com/tomohiko_isobe/items/c245bedfa6966305eb10)
- [IAMユーザをAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/5ae6f15f52a2d20e2635)
- [AWSのセキュリティグループをAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/7342b8ba874d997c5c6c)
- [EC2をAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/163b23d5a0e566aaa159)
- [ec2_group_factsモジュールをAnsible2.2で使えるようにする](http://qiita.com/tomohiko_isobe/items/8684b4dc8f99793e5cf8)
- [RDSをAnsibleで管理する](http://qiita.com/tomohiko_isobe/items/7ce42217e177f0c6b7ec)
- [AnsibleでRoute53を管理する](http://qiita.com/tomohiko_isobe/items/85c5513314a64f2392ba)
- [Ansibleの実行対象AWSアカウントを事前にチェックして事故防止](http://qiita.com/tomohiko_isobe/items/f24fbd86eb64a0e9bd4a)
- [ACMを利用した独自取得SSL証明書更新をAnsibleでやってみる](http://qiita.com/tomohiko_isobe/items/893e9448b7fd0dacc11e)
- [AnsibleでRoute53のレコード情報をいい感じにエクスポートする(全件対応版)](http://qiita.com/tomohiko_isobe/items/cac24af47c85975bb38b)