web-dev-qa-db-ja.com

Pythonスクリプト内からAnsible Vault資格情報ファイルを表示/復号化する方法は?

私はPythonスクリプトに以下の機能を提供して、それができるようにする方法を理解しようとしています:

  1. AnsibleのインポートPythonモジュール
  2. 私の定義したansible.cfgvault_password_file変数
  3. 読んだ vault_password_fileとPython変数に一時的に保存します
  4. 参照されているAnsibleボルトファイルを復号化する

私は google経由のこのコード を見つけましたが、試したときに機能していないようです:

import ansible.utils

bar = dict()

bar = ansible.utils._load_vars_from_path("secrets.yml", results=bar, vault_password="password")

print bar

このエラーをスローします:

$ python ansible-vault-ex.py
Traceback (most recent call last):
  File "ansible-vault-ex.py", line 5, in <module>
    bar = ansible.utils._load_vars_from_path("credentials.vault", results=bar, vault_password="password")
AttributeError: 'module' object has no attribute '_load_vars_from_path'

これを調査したところ、Ansibleの関連ファイルにこの関数の兆候が見られなかったため、このメソッドが一部の新しいバージョンのAnsibleでは機能しなくなったと思いました。

結論としては、PythonスクリプトからAnsibleライブラリ/モジュールをインポートするためのいくつかの方法が欲しいので、ansible-vault Pythonからプログラムで管理されたファイル。

9
slm

Kubaの答えを拡張して、ansible-vaultはVaultLibのラッパーです。これは、Ansible 2.4より前のバージョンのVaultlibと、2.4より後のバージョンをうまく処理します。

Ansible-vault load()メソッドはファイルを復号化するだけでなく、ファイルを解析して内容をdictとして返します。解析せずにコンテンツが必要な場合は、おそらく次のようなものでansible-vaultを拡張するのが最も簡単です。

from ansible_vault import Vault

class MyVault(Vault):
    def load_raw(self, stream):
        return self.vault.decrypt(stream)

    def dump_raw(self, text, stream=None):
        encrypted = self.vault.encrypt(text)
        if stream:
            stream.write(encrypted)
        else:
            return encrypted
2
Chuck

ansible-vaultパッケージ の使用を検討してください

次の方法でインストールします。

$ pip install ansible-vault

そしてそれは次のように簡単です:

from ansible_vault import Vault

vault = Vault('password')
print vault.load(open('/path/to/your/vault.yml').read())

Ansibleコードを使用するには、そのパッケージの source を直接調べます。最も簡単なのは:

Ansible<= 2.3

from ansible.parsing.vault import VaultLib

vault = VaultLib('password')
print vault.decrypt(open('/path/to/vault.yml').read())

Ansible> = 2.4

from ansible.constants import DEFAULT_VAULT_ID_MATCH
from ansible.parsing.vault import VaultLib
from ansible.parsing.vault import VaultSecret

vault = VaultLib([(DEFAULT_VAULT_ID_MATCH, VaultSecret('password'))])
print vault.decrypt(open('/path/to/vault.yml').read())

ソースコードの量は同じですが、パッケージは両方のAnsibleバージョンの自動yaml解析+処理を提供します。

8
Kuba

Ansible.cfgでvault_password_fileを設定している場合、次のようにパスワードをVaultLibに渡すことができます

インポート:

from ansible import constants as C
from ansible.parsing.vault import VaultLib
from ansible.cli import CLI
from ansible.parsing.dataloader import DataLoader

そして、あなたは呼び出すことができます:

loader = DataLoader()
vault_secret = CLI.setup_vault_secrets(
    loader=loader,
    vault_ids=C.DEFAULT_VAULT_IDENTITY_LIST
)
vault = VaultLib(vault_secret)
vault.decrypt(open('/path/to/vault.yml').read())
2
broferek

上記の回答で復号化を機能させることはできませんでしたが、サブプロセスを使用して適切に機能する関数がここにあります。

def vault_decrypt(text, vault_password_file):
    """
    Calls ansible vault and pass the payload via stdin
    :param text: str, text to decode
    :param vault_password_file: str, vault password
    :return: str, decoded text
    """
    cmd = ['ansible-vault', 'decrypt', '--vault-password-file={}'.format(vault_password_file)]
    p = Popen(cmd,
              stdout=PIPE, stdin=PIPE, stderr=PIPE)
    output = p.communicate(input=str.encode(text))
    return output[0].decode("utf-8")

Ansible pythonモジュールを直接使用するように更新した場合、直接更新します。乾杯。

1
radtek

暗号化されたファイルをAnsible Python API、よろしいですか?

Ansible 2.0以降:

def execute_ansible_command(play_source, stdout_callback):
    from ansible.executor.task_queue_manager import TaskQueueManager
    from ansible.inventory import Inventory
    from ansible.parsing.dataloader import DataLoader
    from ansible.playbook import Play
    from ansible.vars import VariableManager

    Options = namedtuple('Options', ['connection', 'module_path', 'forks', 'remote_user',
                                     'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args',
                                     'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity',
                                     'check'])
    variable_manager = VariableManager()
    loader = DataLoader()
    loader.set_vault_password(ANSIBLE_VAULT_PASS)
    options = Options(connection='smart', module_path=None, forks=100,
                      remote_user=None, private_key_file=None, ssh_common_args="-o StrictHostKeyChecking=no",
                      ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=None,
                      become_method=None, become_user=None, verbosity=None, check=False)
    passwords = dict()
    inventory = Inventory(loader=loader, variable_manager=variable_manager, Host_list=ANSIBLE_INVENTORY)
    variable_manager.set_inventory(inventory)

    play = Play().load(play_source, variable_manager=variable_manager, loader=loader)

    tqm = None
    try:
        tqm = TaskQueueManager(
            inventory=inventory,
            variable_manager=variable_manager,
            loader=loader,
            options=options,
            passwords=passwords,
            stdout_callback=stdout_callback,
        )
        tqm.run(play)
    finally:
        if tqm is not None:
            tqm.cleanup()

DataLoaderクラスは、YAMLまたはJSONコンテンツの読み込みと解析に使用され、set_vault_password関数、ボールトのパスワードを送信して、ボールトで暗号化されたファイルを復号化できます

1
Leo

yaferファイル全体が暗号化されている場合、broferekの答えは機能します。 yamlファイルが暗号化されていないが暗号化された変数が含まれている場合、文句を言うでしょう。これはどちらの方法でも機能するはずです。

インポート:

from ansible import constants as C
from ansible.cli import CLI
from ansible.parsing.vault import VaultLib
from ansible.parsing.dataloader import DataLoader

次に、DataLoaderクラスを使用してファイルをdictに読み込みます

cfgfile = "/path/to/yaml/file.yml"
loader = DataLoader()
vault_secrets = CLI.setup_vault_secrets(loader=loader,
            vault_ids=C.DEFAULT_VAULT_IDENTITY_LIST)
loader.set_vault_secrets(vault_secrets)
data = loader.load_from_file(cfgfile)
pprint.pprint(data)
1
Chris Vance

これは正確には私が望んでいることではありませんが、subprocessを介してansible view <vaultfile>コマンドを実行することにより、上記の問題を回避しました。

import subprocess
import yaml

def getCreds():
    cmd = "ansible-vault view credentials.vault"
    process = subprocess.Popen(cmd, Shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()

    resultYaml = yaml.load(result)

    accesskey = resultYaml['accesskey']
    secretkey = resultYaml['secretkey']

    return(accesskey, secretkey)

Pythonで直接Ansibleメソッドを直接呼び出すことは、依然として最善でしょう。

0
slm