Ansible Vaultを使った暗号化

エンジニア

お久しぶりです。少しばたついていて更新が遅れました。今回はAnsibleを使って超絶簡単に暗号化を行なってしまおうの会です。

デプロイに元々Ansibleを使ってる場合はそのまま導入できます。使ってない場合でもコマンドで簡単に暗号化が試せるのでぜひやってみてください!

Ansible Vaultとは

結論、「ソースコードの暗号化・復号ができるもの」それだけです。

そして目的は「秘密情報管理のリスクを減らす」ことです。

皆さんはAWSなどのアクセスキーやAPIキーをどのように管理していますか?それらが記載されているソースコードはGitHubにありませんか?この場合、管理者がうっかりパブリックリポジトリに設定を変更してしまったらどうなるでしょうか。入ったばかりの新卒がソースを流出させてしまったらどうでしょうか(もちろんアクセス権はしっかり設定する必要はありますが)。

ヒューマンエラーは考えたらキリがないですが、立派な秘密情報管理リスクの1つです。

Ansible Vault(以下Vault)の強みはヒューマンエラーを最大限防止できることです。例えば秘密情報のあるソースファイルのみ暗号化しておくとしましょう。そしてパスフレーズを別の場所で管理しておきます。これだけでどちらか一方が流出しても大事に至ることはありません。

そしてパスフレーズを開発用・本番用で分けることでパスフレーズのアクセス権だけ考えれば良くなり、開発者、運用者ともに一つのリポジトリに集約させることができるのです。

さらに元々Ansible運用している現場であれば、復号も自動で行われスムーズなデプロイを可能にします。

簡単に使ってみる

Vaultの使い方は2通りです。

  1. ansible-vaultコマンドを使う。
  2. Ansibleに組み込む。

まずはコマンドでやっていきます。

暗号化(encrypt)

今回はAWSのアクセスキー情報を想定してやっていきます。aws_credentials.iniを用意します。

[dev]
aws_access_key_id = AAAABBBB
aws_secret_access_key = CCCCCCDDDDDD

ansible-vaultコマンドを打ち、パスを聞かれるので適当に入力すると簡単に暗号化できます。

$ ansible-vault encrypt aws_credentials.ini
New Vault password: 
Confirm New Vault password: 
Encryption successful

そして暗号化されたファイルはこんな感じ。

$ANSIBLE_VAULT;1.1;AES256
30646430636331623838656264343238613537636535616135376564356131313430633432386362
3938313663366437313166323432383833363663376236610a663361363334636236313830333463
33383237343864383266633037396138333634343132333631653335626632343063323166356666
3761663039386138330a623565643861636633653131306539626365613430333839346662616264
34653935373063613063363764653665383139636236306537383831643866316239356665326630
66666430383666303539386539316166386561356462363739656434333363373933376533373237
30373365333361643666343733333861323337333334323464376638653365333535623833323938
65313237333032393335

暗号ファイルの確認(view)

暗号化されたファイルを一時的にみたい場合はviewで確認できます。

$ ansible-vault view aws_credentials.ini
Vault password: 
[dev]
aws_access_key_id = AAAABBBB
aws_secret_access_key = CCCCCCDDDDDD

復号(decrypt)

復号はdecryptで簡単にできます。

$ ansible-vault decrypt aws_credentials.ini
Vault password: 
Decryption successful

するとファイルは元に戻ります。

[dev]
aws_access_key_id = AAAABBBB
aws_secret_access_key = CCCCCCDDDDDD

オプション(–vault-password-file)

パスワードを手入力ではなく、ファイルで渡すこともできます。–vault-password-fileオプションでパスファイルを指定します。

$ ansible-vault encrypt --vault-password-file pass.txt aws_credentials.ini
$ ansible-vault decrypt --vault-password-file pass.txt aws_credentials.ini

文字列の暗号化(encrypt_string)

またyamlファイルのように変数の一部を暗号化することもできます。以下のyamlファイルがあったとします。

city: "東京"
age: 24

この”東京”だけを暗号化したい時にencrypt_stringを使ってコマンドを実行します。

$ ansible-vault encrypt_string --vault-password-file pass.txt '東京'
!vault |
          $ANSIBLE_VAULT;1.1;AES256
          35626334376139326231383066376238663338643933393965343633633732346133626463396230
          3831373364656239643837646665646564313934303233300a643861663133376138363432653730
          33646134623437373139356439663238376633313032303132306434613565623938343764303931
          3730663639353635340a306362336661386534376339393932653066643635636562333134333138
          3531
Encryption successful

すると”東京”が暗号化されたものが標準出力されます。これを元のファイルの東京にコピペして置き換えてください。手動になってはしまいますが暗号化できます。

city: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          35626334376139326231383066376238663338643933393965343633633732346133626463396230
          3831373364656239643837646665646564313934303233300a643861663133376138363432653730
          33646134623437373139356439663238376633313032303132306434613565623938343764303931
          3730663639353635340a306362336661386534376339393932653066643635636562333134333138
          3531
age: 24

Ansibleデプロイで利用する

ここからはansibleを知っている方向けになります。

タスクは簡単にクレデンシャルの配置とします。

- name: クレデンシャル配置
  ansible.builtin.template:
    src: ../files/aws_credentials.ini
    dest: /etc/aws_credentials.ini

そしてアクセスキーは変数で表します。

[dev]
aws_access_key_id = {{ access_key }}
aws_secret_access_key = {{ secret_access_key }}

そして肝心の変数ファイルを暗号化しておきます。

$ANSIBLE_VAULT;1.1;AES256
62343432306439656433303939653062643262366638373661306663303838633361393636643136
6631623539393939336432326164363631346432653533660a326330366364646635653364343865
30666431383337616333313937373164623834323663313031303536313363636332313634356261
3734336132363365330a633631373330303639303232323461393462616463636465313330626165
62343830646433396562383538316438363036353163613234343936313461616161303262343064
33386430363434613166396230343466633664313235623932646435303539616638326365313937
653937356165396133643764303365356435

viewで中身を見るとこんな感じ。

access_key: AAAABBBBB
secret_access_key: CCCCDDDD

そしてansibleの設定ファイルにはパスフレーズの書かれたファイルを指定します。

[defaults]
vault_password_file = roles/TEST/files/pass.txt

これだけでansibleの実行オンリーで復号も自動で行われデプロイが完了します。コンテナを立ててそこに実行してみます。

$ ansible-runner run . -p create.yml

PLAY [create docker] ***********************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [docker : コンテナ作成] ***************************************************
changed: [localhost]

PLAY [create env] ***************************************************

TASK [TEST : クレデンシャル配置] ***********************************************
changed: [container]

PLAY RECAP *********************************************************************
container       : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

デプロイされてるかコンテナの中を確認してみると、しっかりされています。

[root@container /]# cat /etc/aws_credentials.ini
[dev]
aws_access_key_id = AAAABBBBB
aws_secret_access_key = CCCCDDDD