Ansibleでgroup_varsをシークレットと非シークレットの2つに分割する例

はじめに

以下のような group_vars を使ってAnsibleを使用している

# inventory/group_vars/all.yml
hoge: fuga
# inventory/group_vars/production.yml
env: production
xyz: getwild
# inventory/group_vars/staging.yml
env: staging
xyz: andtough

この中で、xyz という変数がシークレット情報であるため、group_vars/production.yml と group_vars/staging.yml は ansible-vault で暗号化している という状態

変数ファイルを暗号化すると、

  • もちろんパスワードを知っている人しかファイルの中身は見ることができない
  • gitなどで差分を見ることが難しい

しかし、group_vars/production.yml、group_vars/staging.yml といったファイルごと暗号化されるため、xyz 以外の隠す必要のない変数まで隠れてしまうという問題がある

シークレットを含む変数ファイルの状態から、正しくシークレット情報のみを暗号化し、それ以外は平文で管理したい を実現する、安直な思いつきを書く

  1. ansible-playbook コマンド実行時に追加の変数ファイルを指定する
  2. inventory ファイルをそれっぽく加工する

1. ansible-playbook コマンド実行時に追加の変数ファイルを指定する

# inventory/group_vars/all.yml
hoge: fuga
# inventory/group_vars/production.yml
env: production
# inventory/group_vars/production_encrypted.yml
xyz: getwild
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   ├── production.yml
│   │   ├── production_encrypted.yml
│   │   └── staging.yml
│   │   ├── staging_encrypted.yml
│   ├── production
│   ├── staging
├── site.yml
└── vault_password

group_vars をこう分ける production.yml は自動で読み込まれるが、production_encrypted.yml は読み込まれないため、コマンド実行時に指定する

ansible-playbook \ 
  -i inventory/production \
  -e inventory/group_vars/production_encrypted.yml \
  --vault-password-file vault-password-file \
  site.yml

2. inventory ファイルをそれっぽく加工する

inventoryファイルがこういう形だとする

# inventory/production
[server]
192.168.0.1
192.168.0.2

[production:children]
server
# inventory/staging
[server]
192.168.1.1
192.168.1.2

[staging:children]
server

こうする

# inventory/production
[server]
192.168.0.1
192.168.0.2

[production:children]
server

[production_encrypted:children]
production
# inventory/staging
[server]
192.168.1.1
192.168.1.2

[staging:children]
server

[staging_encrypted:children]
staging

ファイル構成は 1. と同じく↓のような感じ

# inventory/group_vars/all.yml
hoge: fuga
# inventory/group_vars/production.yml
env: production
# inventory/group_vars/production_encrypted.yml
xyz: getwild
├── inventory
│   ├── group_vars
│   │   ├── all.yml
│   │   ├── production.yml
│   │   ├── production_encrypted.yml
│   │   └── staging.yml
│   │   ├── staging_encrypted.yml
│   ├── production
│   ├── staging
├── site.yml
└── vault_password
ansible-playbook \
  -i inventory/production \
  --vault-password-file vault-password-file \
  site.yml

これだと 1. のように実行時引数で指定しなくてもいい

余談

Alternative Directory Layout ってやつを知って、これでいい感じにできたりしないかなと考えたけどいい感じに思いつかなかった