mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Vault secrets default vault ids list (#28190)
* Add config option for a default list of vault-ids This is the vault-id equilivent of ANSIBLE_DEFAULT_PASSWORD_FILE except ANSIBLE_DEFAULT_VAULT_IDENTITY_LIST is a list.
This commit is contained in:
parent
1b8fe94e5a
commit
5739bb075f
6 changed files with 59 additions and 4 deletions
|
@ -214,6 +214,9 @@ class CLI(with_metaclass(ABCMeta, object)):
|
||||||
# certain vault password prompt format, so 'promp_ask_vault_pass' vault_id gets the old format.
|
# certain vault password prompt format, so 'promp_ask_vault_pass' vault_id gets the old format.
|
||||||
prompt_formats = {}
|
prompt_formats = {}
|
||||||
|
|
||||||
|
# If there are configured default vault identities, they are considered 'first'
|
||||||
|
# so we prepend them to vault_ids (from cli) here
|
||||||
|
|
||||||
vault_password_files = vault_password_files or []
|
vault_password_files = vault_password_files or []
|
||||||
if C.DEFAULT_VAULT_PASSWORD_FILE:
|
if C.DEFAULT_VAULT_PASSWORD_FILE:
|
||||||
vault_password_files.append(C.DEFAULT_VAULT_PASSWORD_FILE)
|
vault_password_files.append(C.DEFAULT_VAULT_PASSWORD_FILE)
|
||||||
|
|
|
@ -415,8 +415,11 @@ class ConsoleCLI(CLI, cmd.Cmd):
|
||||||
|
|
||||||
self.loader, self.inventory, self.variable_manager = self._play_prereqs(self.options)
|
self.loader, self.inventory, self.variable_manager = self._play_prereqs(self.options)
|
||||||
|
|
||||||
|
default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST
|
||||||
|
vault_ids = self.options.vault_ids
|
||||||
|
vault_ids = default_vault_ids + vault_ids
|
||||||
vault_secrets = self.setup_vault_secrets(self.loader,
|
vault_secrets = self.setup_vault_secrets(self.loader,
|
||||||
vault_id=self.options.vault_ids,
|
vault_ids=vault_ids,
|
||||||
vault_password_files=self.options.vault_password_files,
|
vault_password_files=self.options.vault_password_files,
|
||||||
ask_vault_pass=self.options.ask_vault_pass)
|
ask_vault_pass=self.options.ask_vault_pass)
|
||||||
self.loader.set_vault_secrets(vault_secrets)
|
self.loader.set_vault_secrets(vault_secrets)
|
||||||
|
|
|
@ -23,6 +23,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from ansible.cli import CLI
|
from ansible.cli import CLI
|
||||||
|
from ansible import constants as C
|
||||||
from ansible.errors import AnsibleOptionsError
|
from ansible.errors import AnsibleOptionsError
|
||||||
from ansible.module_utils._text import to_text, to_bytes
|
from ansible.module_utils._text import to_text, to_bytes
|
||||||
from ansible.parsing.dataloader import DataLoader
|
from ansible.parsing.dataloader import DataLoader
|
||||||
|
@ -156,6 +157,9 @@ class VaultCLI(CLI):
|
||||||
# ask for a new password and confirm it, and 'read/write (rekey) that asks for the
|
# ask for a new password and confirm it, and 'read/write (rekey) that asks for the
|
||||||
# old password, then asks for a new one and confirms it.
|
# old password, then asks for a new one and confirms it.
|
||||||
|
|
||||||
|
default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST
|
||||||
|
vault_ids = default_vault_ids + vault_ids
|
||||||
|
|
||||||
# TODO: instead of prompting for these before, we could let VaultEditor
|
# TODO: instead of prompting for these before, we could let VaultEditor
|
||||||
# call a callback when it needs it.
|
# call a callback when it needs it.
|
||||||
if self.action in ['decrypt', 'view', 'rekey']:
|
if self.action in ['decrypt', 'view', 'rekey']:
|
||||||
|
@ -163,7 +167,6 @@ class VaultCLI(CLI):
|
||||||
vault_ids=vault_ids,
|
vault_ids=vault_ids,
|
||||||
vault_password_files=self.options.vault_password_files,
|
vault_password_files=self.options.vault_password_files,
|
||||||
ask_vault_pass=self.options.ask_vault_pass)
|
ask_vault_pass=self.options.ask_vault_pass)
|
||||||
|
|
||||||
if not vault_secrets:
|
if not vault_secrets:
|
||||||
raise AnsibleOptionsError("A vault password is required to use Ansible's Vault")
|
raise AnsibleOptionsError("A vault password is required to use Ansible's Vault")
|
||||||
|
|
||||||
|
@ -178,7 +181,6 @@ class VaultCLI(CLI):
|
||||||
vault_password_files=self.options.vault_password_files,
|
vault_password_files=self.options.vault_password_files,
|
||||||
ask_vault_pass=self.options.ask_vault_pass,
|
ask_vault_pass=self.options.ask_vault_pass,
|
||||||
create_new_password=True)
|
create_new_password=True)
|
||||||
|
|
||||||
if not vault_secrets:
|
if not vault_secrets:
|
||||||
raise AnsibleOptionsError("A vault password is required to use Ansible's Vault")
|
raise AnsibleOptionsError("A vault password is required to use Ansible's Vault")
|
||||||
|
|
||||||
|
|
|
@ -1088,6 +1088,15 @@ DEFAULT_VAULT_IDENTITY:
|
||||||
- {key: vault_identity, section: defaults}
|
- {key: vault_identity, section: defaults}
|
||||||
vars: []
|
vars: []
|
||||||
yaml: {key: defaults.vault_identity}
|
yaml: {key: defaults.vault_identity}
|
||||||
|
DEFAULT_VAULT_IDENTITY_LIST:
|
||||||
|
default: []
|
||||||
|
desc: 'A list of vault-ids to use by default. Equivalent to multiple --vault-id args. Vault-ids are tried in order.'
|
||||||
|
env: [{name: ANSIBLE_VAULT_IDENTITY_LIST}]
|
||||||
|
ini:
|
||||||
|
- {key: vault_identity_list, section: defaults}
|
||||||
|
value_type: list
|
||||||
|
vars: []
|
||||||
|
yaml: {key: defaults.vault_identity_list}
|
||||||
DEFAULT_VAULT_PASSWORD_FILE:
|
DEFAULT_VAULT_PASSWORD_FILE:
|
||||||
default:
|
default:
|
||||||
desc: 'TODO: write it'
|
desc: 'TODO: write it'
|
||||||
|
|
|
@ -98,6 +98,15 @@ WRONG_RC=$?
|
||||||
echo "rc was $WRONG_RC (1 is expected)"
|
echo "rc was $WRONG_RC (1 is expected)"
|
||||||
[ $WRONG_RC -eq 1 ]
|
[ $WRONG_RC -eq 1 ]
|
||||||
|
|
||||||
|
# test with a default vault-id list set via config/env, right password
|
||||||
|
ANSIBLE_VAULT_PASSWORD_FILE=wrong@vault-password-wrong,correct@vault-password ansible-vault view "$@" format_1_1_AES.yml && :
|
||||||
|
|
||||||
|
# test with a default vault-id list set via config/env,wrong passwords
|
||||||
|
ANSIBLE_VAULT_PASSWORD_FILE=wrong@vault-password-wrong,alsowrong@vault-password-wrong ansible-vault view "$@" format_1_1_AES.yml && :
|
||||||
|
WRONG_RC=$?
|
||||||
|
echo "rc was $WRONG_RC (1 is expected)"
|
||||||
|
[ $WRONG_RC -eq 1 ]
|
||||||
|
|
||||||
# encrypt it
|
# encrypt it
|
||||||
ansible-vault encrypt "$@" --vault-password-file vault-password "${TEST_FILE}"
|
ansible-vault encrypt "$@" --vault-password-file vault-password "${TEST_FILE}"
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ class TestCliSetupVaultSecrets(unittest.TestCase):
|
||||||
vault_id_names = ['prompt1', 'prompt2', 'prompt3', 'default']
|
vault_id_names = ['prompt1', 'prompt2', 'prompt3', 'default']
|
||||||
self._assert_ids(vault_id_names, res)
|
self._assert_ids(vault_id_names, res)
|
||||||
|
|
||||||
@patch('ansible.cli.C', name='MockConfig')
|
@patch('ansible.cli.C')
|
||||||
@patch('ansible.cli.get_file_vault_secret')
|
@patch('ansible.cli.get_file_vault_secret')
|
||||||
@patch('ansible.cli.PromptVaultSecret')
|
@patch('ansible.cli.PromptVaultSecret')
|
||||||
def test_default_file_vault(self, mock_prompt_secret,
|
def test_default_file_vault(self, mock_prompt_secret,
|
||||||
|
@ -146,6 +146,35 @@ class TestCliSetupVaultSecrets(unittest.TestCase):
|
||||||
self.assertEqual(matches[0][1].bytes, b'file1_password')
|
self.assertEqual(matches[0][1].bytes, b'file1_password')
|
||||||
self.assertEqual(matches[1][1].bytes, b'prompt1_password')
|
self.assertEqual(matches[1][1].bytes, b'prompt1_password')
|
||||||
|
|
||||||
|
@patch('ansible.cli.get_file_vault_secret')
|
||||||
|
@patch('ansible.cli.PromptVaultSecret')
|
||||||
|
def test_default_file_vault_identity_list(self, mock_prompt_secret,
|
||||||
|
mock_file_secret):
|
||||||
|
default_vault_ids = ['some_prompt@prompt',
|
||||||
|
'some_file@/dev/null/secret']
|
||||||
|
|
||||||
|
mock_prompt_secret.return_value = MagicMock(bytes=b'some_prompt_password',
|
||||||
|
vault_id='some_prompt')
|
||||||
|
|
||||||
|
filename = '/dev/null/secret'
|
||||||
|
mock_file_secret.return_value = MagicMock(bytes=b'some_file_password',
|
||||||
|
vault_id='some_file',
|
||||||
|
filename=filename)
|
||||||
|
|
||||||
|
vault_ids = default_vault_ids
|
||||||
|
res = cli.CLI.setup_vault_secrets(loader=self.fake_loader,
|
||||||
|
vault_ids=vault_ids,
|
||||||
|
create_new_password=False,
|
||||||
|
ask_vault_pass=True)
|
||||||
|
|
||||||
|
self.assertIsInstance(res, list)
|
||||||
|
matches = vault.match_secrets(res, ['some_file'])
|
||||||
|
# --vault-password-file/DEFAULT_VAULT_PASSWORD_FILE is higher precendce than prompts
|
||||||
|
# if the same vault-id ('default') regardless of cli order since it didn't matter in 2.3
|
||||||
|
self.assertEqual(matches[0][1].bytes, b'some_file_password')
|
||||||
|
matches = vault.match_secrets(res, ['some_prompt'])
|
||||||
|
self.assertEqual(matches[0][1].bytes, b'some_prompt_password')
|
||||||
|
|
||||||
@patch('ansible.cli.PromptVaultSecret')
|
@patch('ansible.cli.PromptVaultSecret')
|
||||||
def test_prompt_just_ask_vault_pass(self, mock_prompt_secret):
|
def test_prompt_just_ask_vault_pass(self, mock_prompt_secret):
|
||||||
mock_prompt_secret.return_value = MagicMock(bytes=b'prompt1_password',
|
mock_prompt_secret.return_value = MagicMock(bytes=b'prompt1_password',
|
||||||
|
|
Loading…
Reference in a new issue