diff --git a/ansible/inventory/group_vars/all/kolla b/ansible/inventory/group_vars/all/kolla index 08dcdf95d..a6fefc173 100644 --- a/ansible/inventory/group_vars/all/kolla +++ b/ansible/inventory/group_vars/all/kolla @@ -457,6 +457,16 @@ kolla_ansible_target_venv: "{{ virtualenv_path ~ '/kolla-ansible' }}" # Password to use to encrypt the kolla-ansible passwords.yml file. kolla_ansible_vault_password: "{{ lookup('env', 'KAYOBE_VAULT_PASSWORD') | default }}" +# Hashi Vault +kolla_ansible_vault_addr: "{{ lookup('env', 'KAYOBE_VAULT_ADDR') | default }}" +kolla_ansible_vault_mount_point: "{{ lookup('env', 'KAYOBE_VAULT_MOUNT_POINT') | default }}" +kolla_ansible_vault_kv_path: "{{ lookup('env', 'KAYOBE_VAULT_KV_PATH') | default }}" +kolla_ansible_vault_namespace: "{{ lookup('env', 'KAYOBE_VAULT_NAMESPACE') | default }}" +kolla_ansible_vault_role_id: "{{ lookup('env', 'KAYOBE_VAULT_ROLE_ID') | default }}" +kolla_ansible_vault_secret_id: "{{ lookup('env', 'KAYOBE_VAULT_SECRET_ID') | default }}" +kolla_ansible_vault_token: "{{ lookup('env', 'KAYOBE_VAULT_TOKEN') | default }}" +kolla_ansible_vault_cacert: "{{ lookup('env', 'KAYOBE_VAULT_CACERT') | default }}" + # Whether TLS is enabled for the external API endpoints. kolla_enable_tls_external: "{{ kolla_enable_tls_internal if public_net_name == internal_net_name else 'no' }}" diff --git a/ansible/roles/kolla-ansible/defaults/main.yml b/ansible/roles/kolla-ansible/defaults/main.yml index 3cee9c96c..82458f77f 100644 --- a/ansible/roles/kolla-ansible/defaults/main.yml +++ b/ansible/roles/kolla-ansible/defaults/main.yml @@ -43,6 +43,16 @@ kolla_ansible_install_epel: false # Password to use to encrypt the passwords.yml file. kolla_ansible_vault_password: +# Hashi Vault +kolla_ansible_vault_addr: +kolla_ansible_vault_mount_point: +kolla_ansible_vault_kv_path: +kolla_ansible_vault_namespace: +kolla_ansible_vault_role_id: +kolla_ansible_vault_secret_id: +kolla_ansible_vault_token: +kolla_ansible_vault_cacert: + # Directory where Kolla config files will be installed. kolla_config_path: diff --git a/ansible/roles/kolla-ansible/library/kolla_passwords.py b/ansible/roles/kolla-ansible/library/kolla_passwords.py index 049f2b09f..4c728f75f 100644 --- a/ansible/roles/kolla-ansible/library/kolla_passwords.py +++ b/ansible/roles/kolla-ansible/library/kolla_passwords.py @@ -51,6 +51,49 @@ def kolla_mergepwd(module, old_path, new_path, final_path): module.run_command(cmd, check_rc=True, path_prefix=virtualenv_path_prefix(module)) +def kolla_readpwd(module, file_path, vault_addr="", vault_mount_point="", vault_kv_path="", + vault_namespace="", vault_role_id=None, vault_secret_id=None, + vault_token=None, vault_cacert=""): + """Run the kolla-readpwd command.""" + + if vault_role_id and vault_secret_id: + vault_auth = ["--vault-role-id", vault_role_id, + "--vault-secret-id", vault_secret_id] + else: + vault_auth = ["--vault-token", vault_token] + + cmd = ["kolla-readpwd", + "--passwords", file_path, + "--vault-addr", vault_addr, + "--vault-mount-point", vault_mount_point, + "--vault-kv-path", vault_kv_path, + "--vault-namespace", vault_namespace, + "--vault-cacert", vault_cacert] + vault_auth + + module.run_command(cmd, check_rc=True, + path_prefix=virtualenv_path_prefix(module)) + +def kolla_writepwd(module, file_path, vault_addr="", vault_mount_point="", vault_kv_path="", + vault_namespace="", vault_role_id=None, vault_secret_id=None, + vault_token=None, vault_cacert=""): + """Run the kolla-writepwd command.""" + + if vault_role_id and vault_secret_id: + vault_auth = ["--vault-role-id", vault_role_id, + "--vault-secret-id", vault_secret_id, ] + else: + vault_auth = ["--vault-token", vault_token, ] + cmd = ["kolla-writepwd", + "--passwords", file_path, + "--vault-addr", vault_addr, + "--vault-mount-point", vault_mount_point, + "--vault-kv-path", vault_kv_path, + "--vault-namespace", vault_namespace, + "--vault-cacert", vault_cacert] + vault_auth + + module.run_command(cmd, check_rc=True, + path_prefix=virtualenv_path_prefix(module)) + def create_vault_password_file(module): """Create a vault password file.""" @@ -128,6 +171,33 @@ def kolla_passwords(module): finally: os.unlink(src_path) + if module.params['vault_addr']: + src_path = create_named_tempfile() + try: + shutil.copyfile(module.params['src'], src_path) + kolla_readpwd(module, src_path, + module.params['vault_addr'], + module.params['vault_mount_point'], + module.params['vault_kv_path'], + module.params['vault_namespace'], + module.params['vault_role_id'], + module.params['vault_secret_id'], + module.params['vault_token'], + module.params['vault_cacert']) + kolla_mergepwd(module, src_path, temp_file_path, temp_file_path) + kolla_genpwd(module, temp_file_path) + kolla_writepwd(module, temp_file_path, + module.params['vault_addr'], + module.params['vault_mount_point'], + module.params['vault_kv_path'], + module.params['vault_namespace'], + module.params['vault_role_id'], + module.params['vault_secret_id'], + module.params['vault_token'], + module.params['vault_cacert']) + finally: + os.unlink(src_path) + # Merge in overrides. if module.params['overrides']: with tempfile.NamedTemporaryFile(delete=False) as f: @@ -137,6 +207,16 @@ def kolla_passwords(module): overrides_path = f.name try: kolla_mergepwd(module, overrides_path, temp_file_path, temp_file_path) + if module.params['vault_addr']: + kolla_writepwd(module, temp_file_path, + module.params['vault_addr'], + module.params['vault_mount_point'], + module.params['vault_kv_path'], + module.params['vault_namespace'], + module.params['vault_role_id'], + module.params['vault_secret_id'], + module.params['vault_token'], + module.params['vault_cacert']) finally: os.unlink(overrides_path) @@ -189,10 +269,23 @@ def main(): sample=dict(default='/usr/share/kolla-ansible/etc_examples/kolla/passwords.yml', type='str'), src=dict(default='/etc/kolla/passwords.yml', type='str'), vault_password=dict(type='str', no_log=True), + vault_addr=dict(type='str', no_log=False), + vault_mount_point=dict(type='str', no_log=False), + vault_kv_path=dict(type='str', no_log=False), + vault_namespace=dict(type='str', no_log=False), + vault_role_id=dict(type='str', no_log=True), + vault_secret_id=dict(type='str', no_log=True), + vault_token=dict(type='str', no_log=True), + vault_cacert=dict(type='str', no_log=False), virtualenv=dict(type='str'), ), add_file_common_args=True, supports_check_mode=True, + required_together=[['vault_mount_point', 'vault_addr'], + ['vault_role_id', 'vault_secret_id'], + ['vault_mount_point','vault_kv_path']], + mutually_exclusive=[['vault_token', 'vault_role_id'], + ['vault_token', 'vault_secret_id']] ) if IMPORT_ERRORS: diff --git a/ansible/roles/kolla-ansible/tasks/config.yml b/ansible/roles/kolla-ansible/tasks/config.yml index 276700f01..b22608775 100644 --- a/ansible/roles/kolla-ansible/tasks/config.yml +++ b/ansible/roles/kolla-ansible/tasks/config.yml @@ -90,6 +90,14 @@ sample: "{{ kolla_ansible_install_dir }}/etc_examples/kolla/passwords.yml" overrides: "{{ kolla_ansible_custom_passwords }}" vault_password: "{{ kolla_ansible_vault_password }}" + vault_addr: "{{ kolla_ansible_vault_addr }}" + vault_mount_point: "{{ kolla_ansible_vault_mount_point }}" + vault_kv_path: "{{ kolla_ansible_vault_kv_path }}" + vault_namespace: "{{ kolla_ansible_vault_namespace }}" + vault_role_id: "{{ kolla_ansible_vault_role_id or omit }}" + vault_secret_id: "{{ kolla_ansible_vault_secret_id or omit }}" + vault_token: "{{ kolla_ansible_vault_token or omit }}" + vault_cacert: "{{ kolla_ansible_vault_cacert }}" virtualenv: "{{ kolla_ansible_venv or omit }}" - name: Ensure the Kolla passwords file is copied into place diff --git a/etc/kayobe/kolla.yml b/etc/kayobe/kolla.yml index 9ed9e6534..2d9a1e696 100644 --- a/etc/kayobe/kolla.yml +++ b/etc/kayobe/kolla.yml @@ -236,6 +236,19 @@ # remotely on the target nodes. If None, no virtualenv will be used. #kolla_ansible_target_venv: +# Password to use to encrypt the kolla-ansible passwords.yml file. +#kolla_ansible_vault_password: + +# Hashi Vault +#kolla_ansible_vault_addr: +#kolla_ansible_vault_mount_point: +#kolla_ansible_vault_kv_path: +#kolla_ansible_vault_namespace: +#kolla_ansible_vault_role_id: +#kolla_ansible_vault_secret_id: +#kolla_ansible_vault_token: +#kolla_ansible_vault_cacert: + # Whether TLS is enabled for the external API endpoints. Default is 'no'. #kolla_enable_tls_external: diff --git a/releasenotes/notes/hashi-vault-kolla-passwords-c4584aeeecd36e80.yaml b/releasenotes/notes/hashi-vault-kolla-passwords-c4584aeeecd36e80.yaml new file mode 100644 index 000000000..ad7ed7a6b --- /dev/null +++ b/releasenotes/notes/hashi-vault-kolla-passwords-c4584aeeecd36e80.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adds functionality into the kolla_passwords module to allow passwords that + are generated for Kolla Ansible to be stored in Hashicorp Vault. diff --git a/requirements.txt b/requirements.txt index 2f4e5b8f7..19decf8ac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ selinux # MIT oslo.config>=5.2.0 # Apache-2.0 paramiko # LGPL jsonschema<5 # MIT +hvac>=0.10.1