NFLabs. エンジニアブログ

セキュリティやソフトウェア開発に関する情報を発信する技術者向けのブログです。

Ansible Vault IDについてまとめてみた

こんにちは。事業推進部の鵜木です。

近年、クラウド環境の急速な普及に伴い、chef*1やAnsible*2など様々な構成管理ツールを目にするようになりました。 構成管理ツールとは、従来であれば手作業で実施していたサーバ構築や設定の投入などの作業をコード化し、作業を自動化できるソフトウェアです。 また、大規模なサーバを管理する場合においても、構成管理ツールを利用することで一元的に管理できるというメリットがあります。

今回は構成管理ツールの一つであるAnsibleのAnsible Vault IDという機能について、私が利用しているちょっとした設定も含めて紹介したいと思います。

Ansible

先ほど少し触れたように、Ansibleとは構成管理ツールの一つであり、OSSで開発が行われています。 他の構成管理ツールに比べ、エージェントレスで動作するため導入コストが低いという利点があります。
ppaを設定する必要がありますが、Ubuntuだとapt install ansibleで導入できます。
しかし、ppaを設定して導入できるバージョン*3は限られるため、Ansibleの最新のバージョンを入れたいという場合は、pipを利用して導入することをお勧めします。

Ansible Vault

Ansibleの機能の一つであり、Playbookやrole、varsなどに含まれる機微なデータを暗号データに変更できます。 Ansible Vaultの暗号化アルゴリズムとしては、AES256が採用されており、サーバのクレデンシャルなどの機微なデータをレポジトリ管理したい場合に有用な機能です。
また、実際の現場ではユーザレベルに応じて暗号鍵*4を使い分けることで、Ansible Vaultを用いたNeed-to-Knowを実現しています。
Ansibleでは、ファイルや変数を暗号化するために様々な手法が提供されていますが、今回はAnsible Vault IDに注目して紹介していこうと思います。

Ansible Vault ID

Ansible Vault IDに関する詳細な説明はAnsibleの公式ドキュメント*5に記載がありますが、やや複雑で実際に利用するまで少し時間が必要でした。
Vault IDを用いた暗号化手法では、機微なデータを暗号化するためにVault IDと呼ばれるものを利用します。
Vault IDをイメージしやすいように言えば、パスワードを識別するためのラベルとファイルのパスがセットとなったものであり、ここで指定したパスのファイルに記載されている文字列が暗号鍵となります。
ここで、Ansibleでは他にどのような暗号化方式が用意してあるか簡単にまとめた上で、Vault IDに対する説明を補足します。

# 1
ansible-vault encrypt password.txt --ask-vault-pass
標準入力で暗号鍵を設定します。  
# 2
ansible-vault encrypt password.txt --vault-password-file .vault_pass
自身の開発環境に暗号鍵が記載されたファイル(.vault_pass)を用意し暗号鍵を設定します。  
# 3
ansible-vault encrypt password.txt --vault-id label@.vault_pass
自身の開発環境にVault IDを用意しラベル付きで暗号鍵を設定します。  

3番目に提示しているコマンドがVault IDを用いた暗号化手法なのですが、ここでは機微なデータであるpassword.txtを暗号データに変換しようとしています。
labelについては、用途によって使い分けのしやすい名前を設定することをオススメします。.vault_passについては自身の開発環境に予め用意した暗号鍵が書かれたファイルを指定します。このようにすることで、password.txtのデータを.vault_passに記載された文字列を暗号鍵として暗号データに変換することができます。
また、.vault_passの箇所をpromptとすることで、ファイルからではなく、標準入力から暗号鍵を与えることも可能です。

ちなみに、先ほどのコマンドを実行して変換された後のpassword.txtについて見てみると次のような出力になります。
(※一部、省略しています。)

# 1
ubuntu@ubuntu:~$ cat password.txt 
$ANSIBLE_VAULT;1.1;AES256
<snip>
# 2
ubuntu@ubuntu:~$ cat password.txt
$ANSIBLE_VAULT;1.1;AES256
<snip>
# 3
ubuntu@ubuntu:~$ cat password.txt 
$ANSIBLE_VAULT;1.2;AES256;label
<snip>

Vault IDを用いて暗号化したファイルについては、labelが暗号データに付与されていることが一目でわかります。
暗号鍵を複数利用している方には、どの暗号鍵を用いたかがパッと分かるため、とても助かる機能だと思います。

Vault IDを用いた暗号化手順

ここからは、Vault IDを利用するために必要な開発環境での手順を紹介していきます。 Vault IDを用いた暗号化の手順自体は、非常に簡単ですが、ここでは3つのパターンを見てみましょう。

暗号鍵にファイルを指定する場合
  1. 暗号鍵が書かれたファイルを自身の開発環境に用意します。
    • vi .vault_passなど、好きなように用意してください。
  2. そして、コマンドを叩くだけです。
    • ansible-vault encrypt password.txt --vault-id label@.vault_pass
暗号鍵をプロンプト経由で指定する場合

次のコマンドを叩くだけです。

  • ansible-vault encrypt password.txt --vault-id label@prompt
YAMLのバリューのみを暗号化する場合

今までは、ファイル全体を暗号化する例のみを紹介していましたが、後述するように特定の文字列のみを暗号化したいという場合においてもVault IDを利用することができます。 次のコマンドを叩くことで、キーの情報のみを平文で保存し任意の文字列のみを暗号化することができます。

  • ansible-vault encrypt_string --vault-id label@.vault_pass 'thisispassword' --name 'passowrd'

実行結果は次のようになります。
passwordというキーはそのまま平文で保存され、thisispasswordの文字列のみが暗号化されていることが分かります。
f:id:unotch:20220322142237p:plain この手法では、ファイル全体を暗号化しないため、変数を定義した箇所が管理しやすくなるという非常に大きなメリットがあると私は感じています。

Vault IDを用いた復号手順

Vault IDを用いた復号手法についてもいくつかありますが、私は自身の開発環境で環境変数を利用して復号を行う手法を利用しています。
環境変数の設定を入れておくことで、暗号化されていることを意識することなくPlaybookを流すことができます。

DEFAULT_VAULT_IDENTITY_LIST*6

f:id:unotch:20220309182856p:plain この環境変数では、デフォルトで復号に利用するVault IDを設定することができます。 LISTという名前からも分かるように、Vault IDを複数設定することができ、Vault IDが持つ暗号鍵で暗号化されているデータを自動的に復号してくれます。
また、Vault IDを複数設定したい場合はカンマ区切りで設定することができます。 実際に、この環境変数を設定した状態で、Vault IDを利用すると次のような挙動となります。
f:id:unotch:20220309163042p:plain
コマンド上で明示的に復号に必要なVault IDを指定していないにも関わらず、復号できていることが分かります。 複数のVault IDを運用している場合など、環境変数さえ設定しておけば自動的に合致するファイルを復号してくれるので非常に便利です。

DEFAULT_VAULT_ID_MATCH*7

f:id:unotch:20220309182848p:plain これもVault IDを用いて運用していく上で、私が利用している環境変数となります。 この環境変数をイメージしやすいように説明すると、暗号データに変換する際に用いたラベル名と暗号鍵のペアが、復号時にも一致した場合にだけ復号させることを許可するオプションとなります。

実際に、この環境変数を設定しないと、ラベル名に関係なく、暗号鍵が正しければ復号できてしまうという状態になります。
言葉だと、少しこの環境変数の意味が掴めないかもしれないので実際にコマンドと共に見ていきましょう。

例えば、password.txtに対して次のようなラベルとファイルを用いて暗号化したとします。

  • Vault IDはtanaka@.vault_passとします。
    f:id:unotch:20220309173043p:plain

次に、ラベル名だけ変更したVault IDを準備して、先ほどのファイルを復号してみます。
復号した結果がこちらです。ラベル名が一致していないにも関わらず、正しく復号できてしまっていることがわかります。
f:id:unotch:20220309170058p:plain ここで、先ほどの環境変数を設定します。上部にあるこの変数のドキュメントを見てみるとTrue/Falseで有効か無効かを設定できそうな気がしますが、実は違います。
実際にどのような出力になるか見てみましょう。

  • Trueを指定した場合 f:id:unotch:20220309170622p:plain

  • Falseを指定した場合 f:id:unotch:20220309170555p:plain

この環境変数を利用する場合は、変数を定義するだけでオプションが有効となることが分かりました。
そのため、オプションを無効化する場合は環境変数から削除する必要があります。
注意が必要ですね。

暗号鍵はcrackされてしまう!?

Ansible Vaultを利用する上で、利用する暗号鍵については細心の注意を払う必要があります。
それは、Ansible Vaultで利用された暗号鍵が、パスワードクラックツールの一つであるHashcat*8で容易にクラックできるためです。
そのため、暗号鍵として利用するパスワードには、短いパスワードや漏えいしていることが知られているパスワードを利用しないように注意が必要です。
実際に、どのようにクラックできるか簡単に見てみましょう。

暗号鍵のクラックを検証してみた

次のような手順を踏むことによって、暗号鍵をクラックすることができます。

  1. まず、パスワードが記載されたファイルを暗号化して用意します。 f:id:unotch:20220322103545p:plain
  2. 次に、ansible2johnを用いて暗号化したファイルのハッシュ値を抽出します。 f:id:unotch:20220322103846p:plain
  3. Hashcatにて、ansibleのアルゴリズムを指定し、rockyou.txtを用いて解析を行ないます。 f:id:unotch:20220322104551p:plain
  4. 出力結果から、ハッシュ値がninjawarriorと一致することが分かりました。実際に、取得した暗号鍵を用いて、ファイルの中身を見ることができるか確認してみましょう。
    f:id:unotch:20220322111532p:plain

上記のように、あっさりと暗号鍵として利用したパスワードを取得することができ、ファイルの中身まで確認することができました。
また、手元の環境では、Vault IDの利用の有無に関わらず暗号鍵をクラックできることが分かりました。
暗号鍵に利用するパスワードとして、簡単なパスワード、漏えいしたことが知られているパスワードを利用することの危険性が改めて認識できたのではないでしょうか。

まとめ

本記事では、Ansibleの機能の一つであるAnsible Vault、関連する環境変数について紹介しました。また、Hashcatによる暗号鍵のクラックにも触れ、機密情報の漏えいに繋がる危険性についても紹介させて頂きました。Vault IDの機能についてはやや複雑に見えるかもしれませんが、複数の暗号鍵を使い分けて運用しているようなチームやプロジェクトでは、有用ではないでしょうか。

Ansible Vaultの導入を考えているが、公式ドキュメントだと理解・イメージしづらいというような方の助けになれば幸いです。