たそ@ITインフラ初心者

taso@初心者エンジニア

新卒2年目 エンジニアが適当に語るブログてす

HashiCorp Vault×Ansible Automation Platform×AWS

はじめに

お疲れ様です。 こんにちは たそ(@taso_int)です。
Ansibleのアドベントカレンダーに参加しています。
今回は18日目の記事になります。

qiita.com

今回はHashiCorp Vaultの動的シークレットエンジンを利用して、
AWSアクセスキーを発行します。
それをAnsible Automation Platformに登録して、 AWSモジュールを使いたいと思います。

やりたいこと

AnsibleでAWSのモジュールを利用する際AWSアクセスキーが必要になります。
権限によってはいろんな操作が可能です。
アクセスキーの流出で、不正利用されるなどの事例もあったかと思います。

これをHashicorp Vaultの動的シークレットエンジンを利用して、
VaultからAWSアクセスキーを発行し、それをAnsible Automation Platformに登録します。
Vaultから作成されたAWSアクセスキーは、期限を付けたり、
破棄が可能なため流出したとしても利用されるリスクが少なくなります。
それにより安全に利用することが可能です。

参考情報

Vaultドキュメント

developer.hashicorp.com

sampleリポジトリ

github.com

環境

AWS EC2

Ansible Automation Platform v2.3

HashiCorp Vault v1.12.2

今回はお互い違うサーバーを用意していますが、
検証目的であれば同じサーバーで構築しても問題ないと思います。
またAWSシークレットキーが必要になります。

構築方法に関しては以下参考にしてください

Ansible

qiita.com

Vault

taso-int.hatenablog.com

Vaultの設定

VaultではAWSシークレットエンジンの設定以下の設定を行います。
本来だと追加でapproleの設定を行い、トークンを発行しておくことをお勧めします。 時間の都合上rootトークンを使います。
ポリシーはread,list,createの設定を入れた方がいいかもしれません。

AWSシークレットエンジンの設定

Vaultが提供する機能の1部に動的シークレットというものがあります。
これは、必要な時に必要な期限を設けてシークレットを生成する機能であります。
今回はAWSですが、その他クラウドにも対応をしております。
従来だとシークレットをファイルに書いて管理しますが、
ファイルが不要になり、また期限を設けることで流出後のリスクも抑えられます。
IAMやSTSなどの発行が出来ますが、今回はIAMを作成します。

参考情報

https://developer.hashicorp.com/vault/docs/secrets/aws

今回はCLIで設定していきます。

# AWSシークレットキーの有効化
vault secrets enable aws

# root用のアクセスキーの登録
vault write aws/config/root \
   access_key=アクセスキー \
   secret_key=シークレットキー \
   region=リージョン

# root用のアクセスキーののローテート
vault write -f aws/config/rotate-root

# 発行後の失効期限を15分に設定(更新操作があっても15分)
vault write aws/config/lease lease=15m lease_max=15m

# IAMを作成するVaultロールの作成
vault write aws/roles/my-role \
        credential_type=iam_user \
        policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1426528957000",
      "Effect": "Allow",
      "Action": [
        "ec2:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
EOF

これにてVault側の設定は終わりになります。
vault read aws/creds/my-roleを実行すると発行されます。
期限切れてますが、ぼかしてます。

$ vault read aws/creds/my-role
Key                Value
---                -----
lease_id           aws/creds/my-role/wYG6EegJWviT8rl7Ea0BYBpY
lease_duration     15m
lease_renewable    true
access_key         AKI***********
secret_key         geGnVnUxW**********
security_token     <nil>

これは15分以上経過するもしくはvault lease revoke aws/creds/my-role/<lease_id>を実行することで失効します。

Ansible Automation Platformの設定

手動で設定するのも悪くないのですが、
いちいち発行して、登録するのが面倒くさいのでPlaybookを書いていきます。
uriモジュールを利用して、vault read aws/creds/my-roleに相当するAPIを叩きます。
そこからawx.awx collectionを利用して、機密情報を上記の結果から登録します。
たぶん他にもやり方はあると思います。

APIを叩く

uriモジュールを使います。 ANSIBLE_HASHI_VAULT_ADDRはvaultのURL、
ANSIBLE_HASHI_VAULT_TOKENはrootのトークンが入ります。 今回は変数として置いています。

参考情報

docs.ansible.com

sample

- name: make credential
  ansible.builtin.uri:
    url: "{{ ANSIBLE_HASHI_VAULT_ADDR }}/v1/aws/creds/my-role"
    method: GET
    body_format: json
    headers:
      X-Vault-Token: "{{ ANSIBLE_HASHI_VAULT_TOKEN }}"
  register: res_newCredential

Ansible Automation Platformの登録

awx.awx.credentialモジュールを利用して登録を行います。
モジュールを利用するのが初めてで、ちゃんと書く方法があると思います。
controller_usernameとかを書かない方法が知りたいです。
知ってる方がいれば教えてください。
urlはAnsible Automation PlatformのURL
userはユーザー、passwordはログインパスワードになります。

参考情報

docs.ansible.com

sample

- name: update AWS credential
  awx.awx.credential:
    name: AWS
    organization: Default
    credential_type: Amazon Web Services
    inputs:
      username: "{{ res_newCredential['json']['data']['access_key'] }}"
      password: "{{ res_newCredential['json']['data']['secret_key'] }}"
    controller_username: "{{ user }}"
    controller_password: "{{ password }}"
    controller_host: "{{ url }}"
    validate_certs: false

実行したいと思いますが、awx.awx collectionはデフォルトEEにはないので、
リポジトリを作成して、requirements.ymlに記載しました。

実行してみる

Playbookは問題なく動いて、登録されました。

AWSを動かしてみる

試しにセキュリティグループを作成したいと思います。
すぐ実行するとエラーになったのでpauseで少し待ちます。
おそらくここはIAMではなくSTSの発行で改善できます。

tasks:
  - name: pause 3 minutes
    ansible.builtin.pause:
      minutes: 3

  - name: example using security group rule descriptions
    amazon.aws.ec2_security_group:
      name: test_vault_sg
      description: sg with rule descriptions
      vpc_id: "{{ vpc_id }}"
      region: ap-northeast-1
      rules:
        - proto: tcp
          ports:
          - 80
          cidr_ip: 0.0.0.0/0
          rule_desc: allow all on port 80

Playbookは無事動き、AWS側でも確認できました。

また期限が切れると認証エラーになります。

以上でこの記事は終わりになりますが、改善箇所が多いので、
次週またやりたいと思います。

箇所としては以下です。

  • revokeの実装
  • approleの実装
  • STSの発行
  • Playbookの修正

以上になります。少しVaultの機能をAnsibleでも生かせることが出来て良かったと思います。
ここまで読んでいただきありがとうございました。