如何从 Python 脚本中 view/decrypt Ansible 保险库凭据文件?
How to view/decrypt Ansible vault credentials files from within a Python script?
我正在尝试弄清楚如何为 Python 脚本提供以下功能,以便它可以:
- 导入 Ansible Python 模块
- 打开我定义的
ansible.cfg
并读取 vault_password_file
变量
- 读取
vault_password_file
并暂时存储在Python变量中
- 解密引用的 Ansible 保管文件
我找到了 this code via 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 libraries/modules 的方法,这样我就可以从 [=40] 以编程方式与 ansible-vault
管理的文件进行交互=].
这不是我想要的,但通过 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 方法仍然是最好的。
通过以下方式安装:
$ 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, VaultSecret
vault = VaultLib([(DEFAULT_VAULT_ID_MATCH, VaultSecret('password'.encode()))])
print(vault.decrypt(open('/path/to/vault.yml').read()))
源代码的数量相等,但包提供自动 yaml 解析 + 处理两个 Ansible 版本。
您想通过 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 class用于加载和解析YAML或JSON内容,它有一个set_vault_password
功能,您可以发送一个保险库密码来解密一个保险库加密的文件
扩展 Kuba 的答案,ansible-vault 是 VaultLib 的包装器。它很好地处理了 Vaultlib 的 Ansible 2.4 之前版本以及 post 2.4 版本。
ansible-vault load() 方法不仅解密文件,而且还将文件和 returns 内容解析为字典。如果您想要不解析的内容,可能最简单的方法是使用类似以下内容的扩展 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
如果您在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())
如果您的整个 yaml 文件都已加密,则 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 class 将文件读入字典
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)
我无法使用上述答案进行解密,但我这里确实有一个使用子进程且运行良好的函数:
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 模块,我会更新。干杯。
我正在尝试弄清楚如何为 Python 脚本提供以下功能,以便它可以:
- 导入 Ansible Python 模块
- 打开我定义的
ansible.cfg
并读取vault_password_file
变量 - 读取
vault_password_file
并暂时存储在Python变量中 - 解密引用的 Ansible 保管文件
我找到了 this code via 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 libraries/modules 的方法,这样我就可以从 [=40] 以编程方式与 ansible-vault
管理的文件进行交互=].
这不是我想要的,但通过 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 方法仍然是最好的。
通过以下方式安装:
$ 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, VaultSecret
vault = VaultLib([(DEFAULT_VAULT_ID_MATCH, VaultSecret('password'.encode()))])
print(vault.decrypt(open('/path/to/vault.yml').read()))
源代码的数量相等,但包提供自动 yaml 解析 + 处理两个 Ansible 版本。
您想通过 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 class用于加载和解析YAML或JSON内容,它有一个set_vault_password
功能,您可以发送一个保险库密码来解密一个保险库加密的文件
扩展 Kuba 的答案,ansible-vault 是 VaultLib 的包装器。它很好地处理了 Vaultlib 的 Ansible 2.4 之前版本以及 post 2.4 版本。
ansible-vault load() 方法不仅解密文件,而且还将文件和 returns 内容解析为字典。如果您想要不解析的内容,可能最简单的方法是使用类似以下内容的扩展 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
如果您在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())
如果您的整个 yaml 文件都已加密,则 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 class 将文件读入字典
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)
我无法使用上述答案进行解密,但我这里确实有一个使用子进程且运行良好的函数:
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 模块,我会更新。干杯。