GNU/Linux >> Linux の 問題 >  >> Linux

Ansibleプレイブックでの秘密の処理

ついに起こった。あなたはAnsibleにオールインしました。すべての優れた記事を読み、ユースケースを確認し、繰り返し可能なインフラストラクチャの構築と構成のコードとしての管理を開始できることに興奮しています。問題は1つだけです。パスワードやその他のミッションクリティカルな情報を必要とする構成ファイルまたはタスクがあります。パスワードをプレーンテキストファイルに保存するべきではないことを知っているので、パスワードをどこに置くべきかよくわかりません。

恐れることはありません。この記事では、プレイブックの機密情報を処理するためのさまざまなオプションについて説明します。管理者にパスワードの入力を求めるなどの単純なソリューションを探している場合でも、既存のシークレット管理環境との統合などのより複雑なオプションを探している場合でも、Ansibleが対応します。

[次のこともお楽しみいただけます:Linuxシステム管理者向けのAnsibleの謎を解き明かす]

プロンプト

Ansibleの旅を始めたばかりで、すべてのプレイブックを手動で実行している場合は、プレイブックで直接インタラクティブプロンプトを使用するのが簡単な解決策です。 プロンプト Ansibleは、プレイブックが実行されるたびに、ユーザーに必要な変数を要求し、それらを保存します。 APIキーが構成ファイルに存在することを確認する次のプレイブックを検討してください。

---

- hosts: all
  gather_facts: false
  vars_prompt:
    - name: api_key
      prompt: Enter the API key
  tasks:
    - name: Ensure API key is present in config file
      ansible.builtin.lineinfile:
        path: /etc/app/configuration.ini
        line: "API_KEY={{ api_key }}"

このプレイブックを実行すると、Ansibleはプロンプトパラメーターのメッセージを使用してコマンドラインでプロンプトを表示します:

# ansible-playbook -i inventory.ini main.yml
Enter the API key:

コマンドラインで提供された入力は、 api_keyに保存されます 変数。通常の変数と同じようにプレイで使用できます。

変数プロンプトは簡単に実装できますが、完全な構成管理にAnsibleを使用することに投資している場合は、変数プロンプトよりも大きくなります。構成管理が成熟すると、非対話的にプレイブックの実行が開始され、端末の前にパスワードを入力する人がいなくなります。そこでAnsibleVaultが登場します。

Ansible Vault

私の個人的なお気に入りのAnsible機能の1つは、ネイティブコンテンツ暗号化機能を提供するAnsibleVaultです。 Ansible Vaultは、任意の変数とファイルを暗号化および復号化できます。つまり、シークレットを含む変数ファイルを保護したり、機密性の高い構成ファイル全体を暗号化したりすることができます。 Ansible Vaultには多くの高度な機能がありますが、この記事では基本に焦点を当てます。

プレーンテキストシークレットを含む標準のYAMLファイルは、ansible-vault encryptを使用して簡単に暗号化できます コマンド:

# Plaintext YAML file
$ cat secrets_file.enc
api_key: SuperSecretPassword

# Encrypt the file with ansible-vault
$ ansible-vault encrypt secrets_file.enc
New Vault password:
Confirm New Vault password:
Encryption successful

# Confirm that the file now contains encrypted content
$ cat secrets_file.enc
$ANSIBLE_VAULT;1.1;AES256
38396162626134393935663839666463306231653861336630613938303662633538633836656465
3637353766613339663032363538626430316135623665340a653961303730353962386134393162
62343936366265353935346336643865643833353737613962643539373230616239346133653464
6435353361373263640a376632613336366430663761363339333737386637383961363833303830
34336535623736313031313162353831666139343662653665366134633832646661

プレイブックを実行すると、暗号化された変数ファイルを渡し、Ansibleにパスワードの入力を求めるように指示できます。 Ansibleは、通常の変数ファイルを渡した場合と同じように、ファイルを復号化し、定義した変数を使用します。

$ cat main.yml
---

- hosts: all
  gather_facts: false
  tasks:
    - name: Ensure API key is present in config file
      ansible.builtin.lineinfile:
        path: /etc/app/configuration.ini
        line: "API_KEY={{ api_key }}"


$ ansible-playbook -i inventory.ini -e @secrets_file.enc --ask-vault-pass main.yml
Vault password:

PLAY [all] ***********************************************************************************

TASK [Ensure API key is present in config file] **********************************************
changed: [localhost]

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

$ cat /etc/app/configuration.ini
API_KEY=SuperSecretPassword

vars_promptを使用する理由については前に説明しました 手動のユーザー介入が必要なため、自動化された環境では理想的ではありません。では、Ansible Vaultはどう違うのですか? Ansible Vaultを使用すると、Vaultの復号化パスワードを含むパスワードファイルを指定できます:

$ cat password_file 
password

$ ansible-playbook -i inventory.ini -e @secrets_file.enc --vault-password-file password_file main.yml

PLAY [all] ***********************************************************************************

TASK [Ensure API key is present in config file] **********************************************
changed: [localhost]

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

プレイブックを実行しているユーザーのみがアクセスできるように、復号化パスワードファイルに適切な権限を設定してください。または、スクリプトを使用して、実行時に外部パスワードストレージシステムからパスワードにアクセスすることを検討してください。

変数ファイルが暗号化されたので、それを編集する方法が必要です。暗号化されたAnsibleVaultを編集する方法は2つあります。ファイルをインプレースで編集することも、完全に復号化して編集してから再暗号化することもできます。両方の方法を以下に示します。

# The edit command will launch a text editor, such as vim
$ ansible-vault edit secrets_file.enc 
Vault password: 

# The decrypt command will fully decrypt the file, allowing you to manipulate it how you see fit.
$ ansible-vault decrypt secrets_file.enc 
Vault password: 
Decryption successful

# Notice that the file has been decrypted
$ cat secrets_file.enc 
api_key: SuperSecretPassword

# Don't forget to re-encrypt the file when you're done!
$ ansible-vault encrypt secrets_file.enc 
New Vault password: 
Confirm New Vault password: 
Encryption successful
$ cat secrets_file.enc 
$ANSIBLE_VAULT;1.1;AES256
33373832393864613335393836616538373639353538306462366464303939303838316337336662
6235303936636465366363643761383462356335336239640a356161653166643134663762323136
34616431303434646338343265666135666263633162383662323164396266616638313936303863
3337626365313666630a326465663239653731613637303437666164346531636361653837326166
34396232623138616364393130303036653564643435636639316264636531336161

シークレットにAnsibleVaultを使用することは、機密データを保存するための私のお気に入りの方法の1つです。このアプローチの利点は、機密データを通常のプレイブックと並べてソース管理に実際に保存できることです。これらのファイルは暗号化されているため、強力なパスワードを選択する限り、このアプローチのリスクはほとんどありません。他の共有シークレットと同様に、暗号化パスワードを頻繁にローテーションすることをお勧めします。 Ansibleは、Vaultごとに異なるパスワードを設定する機能など、Vault用のいくつかの高度な機能も提供します。 Ansibleのネイティブ機能を使用して秘密を保護するための優れた方法については、ドキュメントを確認してください。

既存のパスワードマネージャーを使用する

前の2つのアプローチは、シークレット管理に対処するための純粋にAnsibleのアプローチです。ただし、多くの組織には、HashiCorpVaultやThycoticSecretServerなどのツールがすでにあります。 Ansibleコミュニティは、これらのタイプのシステムと対話するためのカスタムモジュールをいくつか作成しています。

次のハンドブックは、ルックアップを使用してHashiCorp Vaultからシークレットを取得し、そのシークレットをタスクで使用します。


---

- hosts: all
  gather_facts: false
  tasks:
    - name: Ensure API key is present in config file
      ansible.builtin.lineinfile:
        path: /etc/app/configuration.ini
        line: "API_KEY={{ lookup('hashi_vault', 'secret=config-secrets/data/app/api-key:data token=s.FOmpGEHjzSdxGixLNi0AkdA7 url=http://localhost:8201')['key'] }}"

Ansible Galaxyには、さまざまなシークレット管理ツール用のさまざまなプラグインがあります。コミュニティがサポートする他のプロジェクトと同様に、コードを監査して、データとシークレットがどのように処理されているかを理解することをお勧めします。自分で書きたいと思うかもしれません。

ルックアッププラグインまたはモジュールの使用は、成熟したシークレット管理ツールをすでに導入していて、Ansibleがこの既存のシステムからシークレットを消費することを単に望んでいる組織に適しています。明らかなトレードオフは単純さの低下です。Playbookの実行は外部システムの可用性に依存するようになり、コミュニティでサポートされているモジュールに依存する(または独自のモジュールを作成する)には時間がかかる可能性があります。

ロギングに関する注意

保存データ(Ansible Vaultや外部シークレットシステムなど)を暗号化しても、データが誤ってAnsibleログファイルに出力されないように保護されているわけではないことを覚えておくことが重要です。呼び出したモジュールが通常の操作中またはエラーが発生したときにシークレットをログに記録すると、そのシークレットがログファイルに公開される可能性があります。これらのログを中央システムに保存する場合でも、単にデフォルトの標準出力ビューを使用する場合でも、偶発的な露出から秘密を保護することが重要です。

以下の出力は、このチュートリアルで使用しているものと同じAnsibleプレイブックからのものです。ただし、-vvvを使用してAnsibleのデバッグレベルを上げました 。私の秘密に注意してください( API_KEY =SuperSecretPassword )は、デバッグ出力で直接公開されます。このスニペットを少しクリーンアップしたので、これを試してみても心配しないでください。出力は少し異なります。

TASK [Ensure API key is present in config file] ***********************************************************************************************************************************************
fatal: [localhost]: FAILED! => changed=false 
  ansible_facts:
    discovered_interpreter_python: /usr/bin/python
  invocation:
    module_args:
      attributes: null
      backrefs: false
      backup: false
      content: null
      create: false
      delimiter: null
      directory_mode: null
      firstmatch: false
      follow: false
      force: null
      group: null
      insertafter: null
      insertbefore: null
      line: API_KEY=SuperSecretPassword
      mode: null
      owner: null
      path: /etc/app/configuration.ini
      regexp: null
      remote_src: null
      selevel: null
      serole: null
      setype: null
      seuser: null
      src: null
      state: present
      unsafe_writes: null
      validate: null
  msg: Destination /etc/app/configuration.ini does not exist !
  rc: 257

これは絶対に理想的ではありません。私の秘密は、はっきりと見えるところにあります。ありがたいことに、Ansibleは機密データを保護するタスクにno_logパラメーターを提供します:

---

- hosts: all
  gather_facts: false
  tasks:
    - name: Ensure API key is present in config file
      ansible.builtin.lineinfile:
        path: /etc/app/configuration.ini
        line: "API_KEY={{ api_key }}"
      no_log: True

機密データとやり取りするタスクにこのパラメーターを追加することで、失敗したタスクの出力が抑制され、秘密の機密性が保持されます。

TASK [Ensure API key is present in config file] ***********************************************************************************************************************************************
fatal: [localhost]: FAILED! => changed=false 
  censored: 'the output has been hidden due to the fact that ''no_log: true'' was specified for this result'

no_logを使用することをお勧めします 機密データと相互作用するすべてのタスク。また、その制限にも注意する必要があります。Ansibleデバッグがオンになっている場合でもログ記録が妨げられることはありません。

[システム自動化についてもっと知りたいですか? RedHatの無料の本であるTheAutomatedEnterpriseを始めましょう。 ]

最終的な考え

シークレットを適切に管理することは、自動化の展開に取り組むときに多くのシステム管理者が直面する一般的な初期の課題です。この記事では、環境でAnsibleを使用するときに機密データを保護するために使用できる3つの異なる方法について説明およびデモンストレーションしました。この記事は可能性のほんの一部にすぎないので、このディスカッション全体でリンクしたドキュメントを必ず確認してください。セキュリティはすべての人の仕事です。自動化パイプラインにふさわしい機密性でプライベートデータを処理していることを確認することで、システム管理者としての役割を果たすことができます。


Linux
  1. Ansibleガイド:Ansibleを使用してファイルを管理する

  2. AnsiblePlaybookの6つのトラブルシューティングスキル

  3. ファイル内の Ansible アンコメント行

  1. システムでSSHアクセスを保護する8つの方法

  2. Ansibleプレイブックを使用してChronyデーモンを構成します

  3. Windows10でhostsファイルを編集する方法

  1. Ansibleでファイルを作成する方法

  2. サイトをオフラインにする

  3. 既存のSSL用のpemを作成する方法