From 59be5788422cc9a1b71ad800872e4b2b1bc90e49 Mon Sep 17 00:00:00 2001 From: Matthew Mosesohn Date: Wed, 6 Jun 2018 17:22:25 +0300 Subject: [PATCH] Revert "wip pr for improved cert sync" (#2849) --- library/vault_cert_issue.py | 199 ------------------ roles/etcd/tasks/gen_certs_vault.yml | 2 - roles/etcd/tasks/sync_etcd_master_certs.yml | 40 ++-- roles/etcd/tasks/sync_etcd_node_certs.yml | 42 ++-- .../secrets/tasks/gen_certs_vault.yml | 35 +-- roles/vault/tasks/shared/issue_cert.yml | 3 +- 6 files changed, 63 insertions(+), 258 deletions(-) delete mode 100644 library/vault_cert_issue.py diff --git a/library/vault_cert_issue.py b/library/vault_cert_issue.py deleted file mode 100644 index c0d198ae3..000000000 --- a/library/vault_cert_issue.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python -DOCUMENTATION = ''' ---- -module: hashivault_pki_issue -version_added: "0.1" -short_description: Hashicorp Vault PKI issue module -description: - - Module to issue PKI certs from Hashicorp Vault. -options: - url: - description: - - url for vault - default: to environment variable VAULT_ADDR - ca_cert: - description: - - "path to a PEM-encoded CA cert file to use to verify the Vault server TLS certificate" - default: to environment variable VAULT_CACERT - ca_path: - description: - - "path to a directory of PEM-encoded CA cert files to verify the Vault server TLS certificate : if ca_cert is specified, its value will take precedence" - default: to environment variable VAULT_CAPATH - client_cert: - description: - - "path to a PEM-encoded client certificate for TLS authentication to the Vault server" - default: to environment variable VAULT_CLIENT_CERT - client_key: - description: - - "path to an unencrypted PEM-encoded private key matching the client certificate" - default: to environment variable VAULT_CLIENT_KEY - verify: - description: - - "if set, do not verify presented TLS certificate before communicating with Vault server : setting this variable is not recommended except during testing" - default: to environment variable VAULT_SKIP_VERIFY - authtype: - description: - - "authentication type to use: token, userpass, github, ldap, approle" - default: token - token: - description: - - token for vault - default: to environment variable VAULT_TOKEN - username: - description: - - username to login to vault. - default: to environment variable VAULT_USER - password: - description: - - password to login to vault. - default: to environment variable VAULT_PASSWORD - secret: - description: - - secret to read. - data: - description: - - Keys and values to write. - update: - description: - - Update rather than overwrite. - default: False - min_ttl: - description: - - Issue new cert if existing cert has lower TTL expressed in hours or a percentage. Examples: 70800h, 50% - force: - description: - - Force issue of new cert - -''' -EXAMPLES = ''' ---- -- hosts: localhost - tasks: - - hashivault_write: - secret: giant - data: - foo: foe - fie: fum -''' - - -def main(): - argspec = hashivault_argspec() - argspec['secret'] = dict(required=True, type='str') - argspec['update'] = dict(required=False, default=False, type='bool') - argspec['data'] = dict(required=False, default={}, type='dict') - module = hashivault_init(argspec, supports_check_mode=True) - result = hashivault_write(module) - if result.get('failed'): - module.fail_json(**result) - else: - module.exit_json(**result) - - -def _convert_to_seconds(original_value): - try: - value = str(original_value) - seconds = 0 - if 'h' in value: - ray = value.split('h') - seconds = int(ray.pop(0)) * 3600 - value = ''.join(ray) - if 'm' in value: - ray = value.split('m') - seconds += int(ray.pop(0)) * 60 - value = ''.join(ray) - if value: - ray = value.split('s') - seconds += int(ray.pop(0)) - return seconds - except Exception: - pass - return original_value - -def hashivault_needs_refresh(old_data, min_ttl): - print("Checking refresh") - print_r(old_data) - return False -# if sorted(old_data.keys()) != sorted(new_data.keys()): -# return True -# for key in old_data: -# old_value = old_data[key] -# new_value = new_data[key] -# if old_value == new_value: -# continue -# if key != 'ttl' and key != 'max_ttl': -# return True -# old_value = _convert_to_seconds(old_value) -# new_value = _convert_to_seconds(new_value) -# if old_value != new_value: -# return True -# return False -# -def hashivault_changed(old_data, new_data): - if sorted(old_data.keys()) != sorted(new_data.keys()): - return True - for key in old_data: - old_value = old_data[key] - new_value = new_data[key] - if old_value == new_value: - continue - if key != 'ttl' and key != 'max_ttl': - return True - old_value = _convert_to_seconds(old_value) - new_value = _convert_to_seconds(new_value) - if old_value != new_value: - return True - return False - - -from ansible.module_utils.hashivault import * - - -@hashiwrapper -def hashivault_write(module): - result = {"changed": False, "rc": 0} - params = module.params - client = hashivault_auth_client(params) - secret = params.get('secret') - force = params.get('force', False) - min_ttl = params.get('min_ttl', "100%") - returned_data = None - - if secret.startswith('/'): - secret = secret.lstrip('/') - #else: - # secret = ('secret/%s' % secret) - data = params.get('data') - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - changed = True - write_data = data - - if params.get('update') or module.check_mode: - # Do not move this read outside of the update - read_data = client.read(secret) or {} - read_data = read_data.get('data', {}) - - write_data = dict(read_data) - write_data.update(data) - - result['write_data'] = write_data - result['read_data'] = read_data - changed = hashivault_changed(read_data, write_data) - if not changed: - changed = hashivault_needs_refresh(read_data, min_ttl) - - if changed: - if not module.check_mode: - returned_data = client.write((secret), **write_data) - - if returned_data: - result['data'] = returned_data - result['msg'] = "Secret %s written" % secret - result['changed'] = changed - return result - - -if __name__ == '__main__': - main() - diff --git a/roles/etcd/tasks/gen_certs_vault.yml b/roles/etcd/tasks/gen_certs_vault.yml index 1f0f67149..aa3274bd7 100644 --- a/roles/etcd/tasks/gen_certs_vault.yml +++ b/roles/etcd/tasks/gen_certs_vault.yml @@ -62,5 +62,3 @@ with_items: "{{ etcd_node_certs_needed|d([]) }}" when: inventory_hostname in etcd_node_cert_hosts notify: set etcd_secret_changed - -- fail: diff --git a/roles/etcd/tasks/sync_etcd_master_certs.yml b/roles/etcd/tasks/sync_etcd_master_certs.yml index ff33f0a24..b810ff775 100644 --- a/roles/etcd/tasks/sync_etcd_master_certs.yml +++ b/roles/etcd/tasks/sync_etcd_master_certs.yml @@ -8,13 +8,13 @@ "member-" + inventory_hostname + ".pem" ] }} -#- include_tasks: ../../vault/tasks/shared/sync_file.yml -# vars: -# sync_file: "{{ item }}" -# sync_file_dir: "{{ etcd_cert_dir }}" -# sync_file_hosts: [ "{{ inventory_hostname }}" ] -# sync_file_is_cert: true -# with_items: "{{ etcd_master_cert_list|d([]) }}" +- include_tasks: ../../vault/tasks/shared/sync_file.yml + vars: + sync_file: "{{ item }}" + sync_file_dir: "{{ etcd_cert_dir }}" + sync_file_hosts: [ "{{ inventory_hostname }}" ] + sync_file_is_cert: true + with_items: "{{ etcd_master_cert_list|d([]) }}" - name: sync_etcd_certs | Set facts for etcd sync_file results set_fact: @@ -22,16 +22,16 @@ with_items: "{{ sync_file_results|d([]) }}" when: item.no_srcs|bool -#- name: sync_etcd_certs | Unset sync_file_results after etcd certs sync -# set_fact: -# sync_file_results: [] -# -#- include_tasks: ../../vault/tasks/shared/sync_file.yml -# vars: -# sync_file: ca.pem -# sync_file_dir: "{{ etcd_cert_dir }}" -# sync_file_hosts: [ "{{ inventory_hostname }}" ] -# -#- name: sync_etcd_certs | Unset sync_file_results after ca.pem sync -# set_fact: -# sync_file_results: [] +- name: sync_etcd_certs | Unset sync_file_results after etcd certs sync + set_fact: + sync_file_results: [] + +- include_tasks: ../../vault/tasks/shared/sync_file.yml + vars: + sync_file: ca.pem + sync_file_dir: "{{ etcd_cert_dir }}" + sync_file_hosts: [ "{{ inventory_hostname }}" ] + +- name: sync_etcd_certs | Unset sync_file_results after ca.pem sync + set_fact: + sync_file_results: [] diff --git a/roles/etcd/tasks/sync_etcd_node_certs.yml b/roles/etcd/tasks/sync_etcd_node_certs.yml index ffb9e73b8..3e075364f 100644 --- a/roles/etcd/tasks/sync_etcd_node_certs.yml +++ b/roles/etcd/tasks/sync_etcd_node_certs.yml @@ -4,30 +4,30 @@ set_fact: etcd_node_cert_list: "{{ etcd_node_cert_list|default([]) + ['node-' + inventory_hostname + '.pem'] }}" -#- include_tasks: ../../vault/tasks/shared/sync_file.yml -# vars: -# sync_file: "{{ item }}" -# sync_file_dir: "{{ etcd_cert_dir }}" -# sync_file_hosts: [ "{{ inventory_hostname }}" ] -# sync_file_is_cert: true -# with_items: "{{ etcd_node_cert_list|d([]) }}" -# +- include_tasks: ../../vault/tasks/shared/sync_file.yml + vars: + sync_file: "{{ item }}" + sync_file_dir: "{{ etcd_cert_dir }}" + sync_file_hosts: [ "{{ inventory_hostname }}" ] + sync_file_is_cert: true + with_items: "{{ etcd_node_cert_list|d([]) }}" + - name: sync_etcd_node_certs | Set facts for etcd sync_file results set_fact: etcd_node_certs_needed: "{{ etcd_node_certs_needed|default([]) + [item.path] }}" with_items: "{{ sync_file_results|d([]) }}" when: item.no_srcs|bool -#- name: sync_etcd_node_certs | Unset sync_file_results after etcd node certs -# set_fact: -# sync_file_results: [] -# -#- include_tasks: ../../vault/tasks/shared/sync_file.yml -# vars: -# sync_file: ca.pem -# sync_file_dir: "{{ etcd_cert_dir }}" -# sync_file_hosts: "{{ groups['etcd'] }}" -# -#- name: sync_etcd_node_certs | Unset sync_file_results after ca.pem -# set_fact: -# sync_file_results: [] +- name: sync_etcd_node_certs | Unset sync_file_results after etcd node certs + set_fact: + sync_file_results: [] + +- include_tasks: ../../vault/tasks/shared/sync_file.yml + vars: + sync_file: ca.pem + sync_file_dir: "{{ etcd_cert_dir }}" + sync_file_hosts: "{{ groups['etcd'] }}" + +- name: sync_etcd_node_certs | Unset sync_file_results after ca.pem + set_fact: + sync_file_results: [] diff --git a/roles/kubernetes/secrets/tasks/gen_certs_vault.yml b/roles/kubernetes/secrets/tasks/gen_certs_vault.yml index db93f64e5..88db2f5a4 100644 --- a/roles/kubernetes/secrets/tasks/gen_certs_vault.yml +++ b/roles/kubernetes/secrets/tasks/gen_certs_vault.yml @@ -1,22 +1,23 @@ --- -#- import_tasks: sync_kube_master_certs.yml -# when: inventory_hostname in groups['kube-master'] -# -#- import_tasks: sync_kube_node_certs.yml -# when: inventory_hostname in groups['k8s-cluster'] +- import_tasks: sync_kube_master_certs.yml + when: inventory_hostname in groups['kube-master'] + +- import_tasks: sync_kube_node_certs.yml + when: inventory_hostname in groups['k8s-cluster'] # Issue admin certs to kube-master hosts - include_tasks: ../../../vault/tasks/shared/issue_cert.yml vars: issue_cert_common_name: "admin" - issue_cert_copy_ca: true + issue_cert_copy_ca: "{{ item == kube_admin_certs_needed|first }}" issue_cert_file_group: "{{ kube_cert_group }}" issue_cert_file_owner: kube issue_cert_hosts: "{{ groups['kube-master'] }}" - issue_cert_path: "{{ inventory_hostname }}" + issue_cert_path: "{{ item }}" issue_cert_role: kube-master issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}" issue_cert_mount_path: "{{ kube_vault_mount_path }}" + with_items: "{{ kube_admin_certs_needed|d([]) }}" when: inventory_hostname in groups['kube-master'] - name: gen_certs_vault | Set fact about certificate alt names @@ -58,10 +59,11 @@ {%- endif -%} "127.0.0.1","::1","{{ kube_apiserver_ip }}" ] - issue_cert_path: "{{ inventory_hostname }}" + issue_cert_path: "{{ item }}" issue_cert_role: kube-master issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}" issue_cert_mount_path: "{{ kube_vault_mount_path }}" + with_items: "{{ kube_master_components_certs_needed|d([]) }}" when: inventory_hostname in groups['kube-master'] notify: set secret_changed @@ -71,33 +73,37 @@ # Need to strip out the 'node-' prefix from the cert name so it can be used # with the node authorization plugin ( CN matches kubelet node name ) issue_cert_common_name: "system:node:{{ item.rsplit('/', 1)[1].rsplit('.', 1)[0] | regex_replace('^node-', '') }}" - issue_cert_copy_ca: yes + issue_cert_copy_ca: "{{ item == kube_node_certs_needed|first }}" issue_cert_file_group: "{{ kube_cert_group }}" issue_cert_file_owner: kube issue_cert_hosts: "{{ groups['k8s-cluster'] }}" - issue_cert_path: "{{ inventory_hostname }}" + issue_cert_path: "{{ item }}" issue_cert_role: kube-node issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}" issue_cert_mount_path: "{{ kube_vault_mount_path }}" + with_items: "{{ kube_node_certs_needed|d([]) }}" + when: inventory_hostname in groups['k8s-cluster'] # Issue proxy certs to k8s-cluster nodes - include_tasks: ../../../vault/tasks/shared/issue_cert.yml vars: issue_cert_common_name: "system:kube-proxy" - issue_cert_copy_ca: true + issue_cert_copy_ca: "{{ item == kube_proxy_certs_needed|first }}" issue_cert_file_group: "{{ kube_cert_group }}" issue_cert_file_owner: kube issue_cert_hosts: "{{ groups['k8s-cluster'] }}" - issue_cert_path: "{{ inventory_hostname }}" + issue_cert_path: "{{ item }}" issue_cert_role: kube-proxy issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}" issue_cert_mount_path: "{{ kube_vault_mount_path }}" + with_items: "{{ kube_proxy_certs_needed|d([]) }}" + when: inventory_hostname in groups['k8s-cluster'] # Issue front proxy cert to kube-master hosts - include_tasks: ../../../vault/tasks/shared/issue_cert.yml vars: issue_cert_common_name: "front-proxy-client" - issue_cert_copy_ca: true + issue_cert_copy_ca: "{{ item == kube_front_proxy_clients_certs_needed|first }}" issue_cert_ca_filename: front-proxy-ca.pem issue_cert_alt_names: "{{ kube_cert_alt_names }}" issue_cert_file_group: "{{ kube_cert_group }}" @@ -118,9 +124,10 @@ {%- endif -%} "127.0.0.1","::1","{{ kube_apiserver_ip }}" ] - issue_cert_path: "{{ inventory_hostname }}" + issue_cert_path: "{{ item }}" issue_cert_role: front-proxy-client issue_cert_url: "{{ hostvars[groups.vault|first]['vault_leader_url'] }}" issue_cert_mount_path: "{{ kube_vault_mount_path }}" + with_items: "{{ kube_front_proxy_clients_certs_needed|d([]) }}" when: inventory_hostname in groups['kube-master'] notify: set secret_changed diff --git a/roles/vault/tasks/shared/issue_cert.yml b/roles/vault/tasks/shared/issue_cert.yml index b04cd0e23..89921b345 100644 --- a/roles/vault/tasks/shared/issue_cert.yml +++ b/roles/vault/tasks/shared/issue_cert.yml @@ -76,8 +76,7 @@ run_once: true - name: "issue_cert | Generate {{ issue_cert_path }} for {{ issue_cert_role }} role" - #hashivault_write: - vault_cert_issue: + hashivault_write: url: "{{ issue_cert_url }}" token: "{{ vault_client_token }}" ca_cert: "{% if 'https' in issue_cert_url %}{{ vault_cert_dir }}/ca.pem{% endif %}"