diff options
43 files changed, 1026 insertions, 422 deletions
diff --git a/filter_plugins/openshift_master.py b/filter_plugins/openshift_master.py index f209d6c3b..77b0a3dc9 100644 --- a/filter_plugins/openshift_master.py +++ b/filter_plugins/openshift_master.py @@ -517,13 +517,11 @@ class FilterModule(object):          return valid      @staticmethod -    def certificates_to_synchronize(hostvars, include_keys=True): +    def certificates_to_synchronize(hostvars, include_keys=True, include_ca=True):          ''' Return certificates to synchronize based on facts. '''          if not issubclass(type(hostvars), dict):              raise errors.AnsibleFilterError("|failed expects hostvars is a dict") -        certs = ['ca.crt', -                 'ca.key', -                 'admin.crt', +        certs = ['admin.crt',                   'admin.key',                   'admin.kubeconfig',                   'master.kubelet-client.crt', @@ -534,6 +532,8 @@ class FilterModule(object):                   'openshift-router.crt',                   'openshift-router.key',                   'openshift-router.kubeconfig'] +        if bool(include_ca): +            certs += ['ca.crt', 'ca.key']          if bool(include_keys):              certs += ['serviceaccounts.private.key',                        'serviceaccounts.public.key'] diff --git a/inventory/byo/hosts.origin.example b/inventory/byo/hosts.origin.example index 0a1b8c5c4..da05a83c3 100644 --- a/inventory/byo/hosts.origin.example +++ b/inventory/byo/hosts.origin.example @@ -528,10 +528,7 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',  # NOTE: CA certificate will not be replaced with existing clusters.  # This option may only be specified when creating a new cluster or  # when redeploying cluster certificates with the redeploy-certificates -# playbook. If replacing the CA certificate in an existing cluster -# with a custom ca certificate, the following variable must also be -# set. -#openshift_certificates_redeploy_ca=true +# playbook.  # Configure custom named certificates (SNI certificates)  # diff --git a/inventory/byo/hosts.ose.example b/inventory/byo/hosts.ose.example index 89b9d7e48..65cc65745 100644 --- a/inventory/byo/hosts.ose.example +++ b/inventory/byo/hosts.ose.example @@ -528,10 +528,7 @@ openshift_master_identity_providers=[{'name': 'htpasswd_auth', 'login': 'true',  # NOTE: CA certificate will not be replaced with existing clusters.  # This option may only be specified when creating a new cluster or  # when redeploying cluster certificates with the redeploy-certificates -# playbook. If replacing the CA certificate in an existing cluster -# with a custom ca certificate, the following variable must also be -# set. -#openshift_certificates_redeploy_ca=true +# playbook.  # Configure custom named certificates (SNI certificates)  # diff --git a/library/kubeclient_ca.py b/library/kubeclient_ca.py new file mode 100644 index 000000000..163624a76 --- /dev/null +++ b/library/kubeclient_ca.py @@ -0,0 +1,90 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 + +''' kubeclient_ca ansible module ''' + +import base64 +import yaml +from ansible.module_utils.basic import AnsibleModule + + +DOCUMENTATION = ''' +--- +module: kubeclient_ca +short_description: Modify kubeclient certificate-authority-data +author: Andrew Butcher +requirements: [ ] +''' +EXAMPLES = ''' +- kubeclient_ca: +    client_path: /etc/origin/master/admin.kubeconfig +    ca_path: /etc/origin/master/ca-bundle.crt + +- slurp: +    src: /etc/origin/master/ca-bundle.crt +  register: ca_data +- kubeclient_ca: +    client_path: /etc/origin/master/admin.kubeconfig +    ca_data: "{{ ca_data.content }}" +''' + + +def main(): +    ''' Modify kubeconfig located at `client_path`, setting the +        certificate authority data to specified `ca_data` or contents of +        `ca_path`. +    ''' + +    module = AnsibleModule(  # noqa: F405 +        argument_spec=dict( +            client_path=dict(required=True), +            ca_data=dict(required=False, default=None), +            ca_path=dict(required=False, default=None), +            backup=dict(required=False, default=True, type='bool'), +        ), +        supports_check_mode=True, +        mutually_exclusive=[['ca_data', 'ca_path']], +        required_one_of=[['ca_data', 'ca_path']] +    ) + +    client_path = module.params['client_path'] +    ca_data = module.params['ca_data'] +    ca_path = module.params['ca_path'] +    backup = module.params['backup'] + +    try: +        with open(client_path) as client_config_file: +            client_config_data = yaml.safe_load(client_config_file.read()) + +        if ca_data is None: +            with open(ca_path) as ca_file: +                ca_data = base64.standard_b64encode(ca_file.read()) + +        changes = [] +        # Naively update the CA information for each cluster in the +        # kubeconfig. +        for cluster in client_config_data['clusters']: +            if cluster['cluster']['certificate-authority-data'] != ca_data: +                cluster['cluster']['certificate-authority-data'] = ca_data +                changes.append(cluster['name']) + +        if not module.check_mode: +            if len(changes) > 0 and backup: +                module.backup_local(client_path) + +            with open(client_path, 'w') as client_config_file: +                client_config_string = yaml.dump(client_config_data, default_flow_style=False) +                client_config_string = client_config_string.replace('\'\'', '""') +                client_config_file.write(client_config_string) + +        return module.exit_json(changed=(len(changes) > 0)) + +    # ignore broad-except error to avoid stack trace to ansible user +    # pylint: disable=broad-except +    except Exception as error: +        return module.fail_json(msg=str(error)) + + +if __name__ == '__main__': +    main() diff --git a/playbooks/byo/openshift-cluster/config.yml b/playbooks/byo/openshift-cluster/config.yml index d953b8ed3..86eff4ca4 100644 --- a/playbooks/byo/openshift-cluster/config.yml +++ b/playbooks/byo/openshift-cluster/config.yml @@ -1,27 +1,7 @@  --- -- name: Create initial host groups for localhost -  hosts: localhost -  connection: local -  become: no -  gather_facts: no +- include: ../../common/openshift-cluster/std_include.yml    tags:    - always -  tasks: -  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml -  - name: Evaluate group l_oo_all_hosts -    add_host: -      name: "{{ item }}" -      groups: l_oo_all_hosts -    with_items: "{{ g_all_hosts | default([]) }}" -    changed_when: no - -- name: Create initial host groups for all hosts -  hosts: l_oo_all_hosts -  gather_facts: no -  tags: -  - always -  tasks: -  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml  - include: ../../common/openshift-cluster/config.yml    vars: diff --git a/playbooks/byo/openshift-cluster/redeploy-certificates.yml b/playbooks/byo/openshift-cluster/redeploy-certificates.yml index 753248855..ad24b9ad0 100644 --- a/playbooks/byo/openshift-cluster/redeploy-certificates.yml +++ b/playbooks/byo/openshift-cluster/redeploy-certificates.yml @@ -1,28 +1,20 @@  --- -- name: Create initial host groups for localhost -  hosts: localhost -  connection: local -  become: no -  gather_facts: no +- include: ../../common/openshift-cluster/std_include.yml    tags:    - always -  tasks: -  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml -  - name: Evaluate group l_oo_all_hosts -    add_host: -      name: "{{ item }}" -      groups: l_oo_all_hosts -    with_items: "{{ g_all_hosts | default([]) }}" -    changed_when: False - -- name: Create initial host groups for all hosts -  hosts: l_oo_all_hosts -  gather_facts: no -  tags: -  - always -  tasks: -  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml -- include: ../../common/openshift-cluster/redeploy-certificates.yml -  vars: -    openshift_deployment_type: "{{ deployment_type }}" +- include: ../../common/openshift-cluster/redeploy-certificates/etcd.yml + +- include: ../../common/openshift-cluster/redeploy-certificates/masters.yml + +- include: ../../common/openshift-cluster/redeploy-certificates/nodes.yml + +- include: ../../common/openshift-etcd/restart.yml + +- include: ../../common/openshift-master/restart.yml + +- include: ../../common/openshift-node/restart.yml + +- include: ../../common/openshift-cluster/redeploy-certificates/router.yml + +- include: ../../common/openshift-cluster/redeploy-certificates/registry.yml diff --git a/playbooks/byo/openshift-cluster/redeploy-etcd-certificates.yml b/playbooks/byo/openshift-cluster/redeploy-etcd-certificates.yml new file mode 100644 index 000000000..ee49364fa --- /dev/null +++ b/playbooks/byo/openshift-cluster/redeploy-etcd-certificates.yml @@ -0,0 +1,10 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-cluster/redeploy-certificates/etcd.yml + +- include: ../../common/openshift-etcd/restart.yml + +- include: ../../common/openshift-master/restart.yml diff --git a/playbooks/byo/openshift-cluster/redeploy-master-certificates.yml b/playbooks/byo/openshift-cluster/redeploy-master-certificates.yml new file mode 100644 index 000000000..9c8248c4e --- /dev/null +++ b/playbooks/byo/openshift-cluster/redeploy-master-certificates.yml @@ -0,0 +1,8 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-cluster/redeploy-certificates/masters.yml + +- include: ../../common/openshift-master/restart.yml diff --git a/playbooks/byo/openshift-cluster/redeploy-node-certificates.yml b/playbooks/byo/openshift-cluster/redeploy-node-certificates.yml new file mode 100644 index 000000000..1695111d0 --- /dev/null +++ b/playbooks/byo/openshift-cluster/redeploy-node-certificates.yml @@ -0,0 +1,8 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-cluster/redeploy-certificates/nodes.yml + +- include: ../../common/openshift-node/restart.yml diff --git a/playbooks/byo/openshift-cluster/redeploy-openshift-ca.yml b/playbooks/byo/openshift-cluster/redeploy-openshift-ca.yml new file mode 100644 index 000000000..e44e95467 --- /dev/null +++ b/playbooks/byo/openshift-cluster/redeploy-openshift-ca.yml @@ -0,0 +1,6 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-cluster/redeploy-certificates/ca.yml diff --git a/playbooks/byo/openshift-cluster/redeploy-registry-certificates.yml b/playbooks/byo/openshift-cluster/redeploy-registry-certificates.yml new file mode 100644 index 000000000..53ee68db9 --- /dev/null +++ b/playbooks/byo/openshift-cluster/redeploy-registry-certificates.yml @@ -0,0 +1,6 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-cluster/redeploy-certificates/registry.yml diff --git a/playbooks/byo/openshift-cluster/redeploy-router-certificates.yml b/playbooks/byo/openshift-cluster/redeploy-router-certificates.yml new file mode 100644 index 000000000..f8c267569 --- /dev/null +++ b/playbooks/byo/openshift-cluster/redeploy-router-certificates.yml @@ -0,0 +1,6 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-cluster/redeploy-certificates/router.yml diff --git a/playbooks/byo/openshift-etcd/filter_plugins b/playbooks/byo/openshift-etcd/filter_plugins new file mode 120000 index 000000000..99a95e4ca --- /dev/null +++ b/playbooks/byo/openshift-etcd/filter_plugins @@ -0,0 +1 @@ +../../../filter_plugins
\ No newline at end of file diff --git a/playbooks/byo/openshift-etcd/lookup_plugins b/playbooks/byo/openshift-etcd/lookup_plugins new file mode 120000 index 000000000..ac79701db --- /dev/null +++ b/playbooks/byo/openshift-etcd/lookup_plugins @@ -0,0 +1 @@ +../../../lookup_plugins
\ No newline at end of file diff --git a/playbooks/byo/openshift-etcd/restart.yml b/playbooks/byo/openshift-etcd/restart.yml new file mode 100644 index 000000000..6713f07e3 --- /dev/null +++ b/playbooks/byo/openshift-etcd/restart.yml @@ -0,0 +1,8 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-etcd/restart.yml +  vars: +    openshift_deployment_type: "{{ deployment_type }}" diff --git a/playbooks/byo/openshift-etcd/roles b/playbooks/byo/openshift-etcd/roles new file mode 120000 index 000000000..20c4c58cf --- /dev/null +++ b/playbooks/byo/openshift-etcd/roles @@ -0,0 +1 @@ +../../../roles
\ No newline at end of file diff --git a/playbooks/byo/openshift-master/restart.yml b/playbooks/byo/openshift-master/restart.yml index 3e58ccbcc..2d20f69f4 100644 --- a/playbooks/byo/openshift-master/restart.yml +++ b/playbooks/byo/openshift-master/restart.yml @@ -1,38 +1,8 @@  --- -- name: Create initial host groups for localhost -  hosts: localhost -  connection: local -  become: no -  gather_facts: no +- include: ../../common/openshift-cluster/std_include.yml    tags:    - always -  tasks: -  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml -  - name: Evaluate group l_oo_all_hosts -    add_host: -      name: "{{ item }}" -      groups: l_oo_all_hosts -    with_items: "{{ g_all_hosts | default([]) }}" -    changed_when: False -- name: Create initial host groups for all hosts -  hosts: l_oo_all_hosts -  gather_facts: no -  tags: -  - always -  tasks: -  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml - -- include: ../../common/openshift-cluster/evaluate_groups.yml -- include: ../../common/openshift-master/validate_restart.yml - -- name: Restart masters -  hosts: oo_masters_to_config +- include: ../../common/openshift-master/restart.yml    vars: -    openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}" -  serial: 1 -  tasks: -  - include: restart_hosts.yml -    when: openshift.common.rolling_restart_mode == 'system' -  - include: restart_services.yml -    when: openshift.common.rolling_restart_mode == 'services' +    openshift_deployment_type: "{{ deployment_type }}" diff --git a/playbooks/byo/openshift-node/restart.yml b/playbooks/byo/openshift-node/restart.yml new file mode 100644 index 000000000..3985a83bb --- /dev/null +++ b/playbooks/byo/openshift-node/restart.yml @@ -0,0 +1,8 @@ +--- +- include: ../../common/openshift-cluster/std_include.yml +  tags: +  - always + +- include: ../../common/openshift-node/restart.yml +  vars: +    openshift_deployment_type: "{{ deployment_type }}" diff --git a/playbooks/byo/openshift_facts.yml b/playbooks/byo/openshift_facts.yml index 025983662..fcf402fa0 100644 --- a/playbooks/byo/openshift_facts.yml +++ b/playbooks/byo/openshift_facts.yml @@ -1,29 +1,7 @@  --- -- name: Create initial host groups for localhost -  hosts: localhost -  connection: local -  become: no -  gather_facts: no +- include: ../../common/openshift-cluster/std_include.yml    tags:    - always -  tasks: -  - include_vars: ../byo/openshift-cluster/cluster_hosts.yml -  - name: Evaluate group l_oo_all_hosts -    add_host: -      name: "{{ item }}" -      groups: l_oo_all_hosts -    with_items: "{{ g_all_hosts | default([]) }}" -    changed_when: False - -- name: Create initial host groups for all hosts -  hosts: l_oo_all_hosts -  gather_facts: no -  tags: -  - always -  tasks: -  - include_vars: ../byo/openshift-cluster/cluster_hosts.yml - -- include: ../common/openshift-cluster/evaluate_groups.yml  - name: Gather Cluster facts    hosts: OSEv3 diff --git a/playbooks/byo/rhel_subscribe.yml b/playbooks/byo/rhel_subscribe.yml index 8e7568e33..62f62680e 100644 --- a/playbooks/byo/rhel_subscribe.yml +++ b/playbooks/byo/rhel_subscribe.yml @@ -1,29 +1,7 @@  --- -- name: Create initial host groups for localhost -  hosts: localhost -  connection: local -  become: no -  gather_facts: no +- include: ../../common/openshift-cluster/std_include.yml    tags:    - always -  tasks: -  - include_vars: openshift-cluster/cluster_hosts.yml -  - name: Evaluate group l_oo_all_hosts -    add_host: -      name: "{{ item }}" -      groups: l_oo_all_hosts -    with_items: "{{ g_all_hosts | default([]) }}" -    changed_when: False - -- name: Create initial host groups for all hosts -  hosts: l_oo_all_hosts -  gather_facts: no -  tags: -  - always -  tasks: -  - include_vars: ../byo/openshift-cluster/cluster_hosts.yml - -- include: ../common/openshift-cluster/evaluate_groups.yml  - name: Subscribe hosts, update repos and update OS packages    hosts: l_oo_all_hosts diff --git a/playbooks/common/openshift-cluster/config.yml b/playbooks/common/openshift-cluster/config.yml index a95cb68b7..a0ba735ab 100644 --- a/playbooks/common/openshift-cluster/config.yml +++ b/playbooks/common/openshift-cluster/config.yml @@ -1,20 +1,4 @@  --- -- include: evaluate_groups.yml -  tags: -  - always - -- include: initialize_facts.yml -  tags: -  - always - -- include: validate_hostnames.yml -  tags: -  - node - -- include: initialize_openshift_version.yml -  tags: -  - always -  - name: Set oo_option facts    hosts: oo_all_hosts    tags: diff --git a/playbooks/common/openshift-cluster/redeploy-certificates.yml b/playbooks/common/openshift-cluster/redeploy-certificates.yml deleted file mode 100644 index a0e3f1d8a..000000000 --- a/playbooks/common/openshift-cluster/redeploy-certificates.yml +++ /dev/null @@ -1,250 +0,0 @@ ---- -- include: evaluate_groups.yml - -- include: initialize_facts.yml - -- include: initialize_openshift_version.yml - -- name: Load openshift_facts -  hosts: oo_etcd_to_config:oo_masters_to_config:oo_nodes_to_config -  roles: -  - openshift_facts - -- name: Redeploy etcd certificates -  hosts: oo_etcd_to_config -  any_errors_fatal: true -  vars: -    etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}" -    etcd_conf_dir: /etc/etcd -    etcd_generated_certs_dir: "{{ etcd_conf_dir }}/generated_certs" - -  pre_tasks: -  - stat: -      path: "{{ etcd_generated_certs_dir }}" -    register: etcd_generated_certs_dir_stat -  - name: Backup etcd certificates -    command: > -      tar -czvf /etc/etcd/etcd-certificate-backup-{{ ansible_date_time.epoch }}.tgz -      {{ etcd_conf_dir }}/ca.crt -      {{ etcd_conf_dir }}/ca -      {{ etcd_generated_certs_dir }} -    when: etcd_generated_certs_dir_stat.stat.exists -    delegate_to: "{{ etcd_ca_host }}" -    run_once: true -  - name: Remove existing etcd certificates -    file: -      path: "{{ item }}" -      state: absent -    with_items: -    - "{{ etcd_conf_dir }}/ca.crt" -    - "{{ etcd_conf_dir }}/ca" -    - "{{ etcd_generated_certs_dir }}" -  roles: -  - role: openshift_etcd_server_certificates -    etcd_peers: "{{ groups.oo_etcd_to_config | default([], true) }}" -    etcd_certificates_etcd_hosts: "{{ groups.oo_etcd_to_config | default([], true) }}" -    etcd_certificates_redeploy: true - -- name: Redeploy master certificates -  hosts: oo_masters_to_config -  any_errors_fatal: true -  vars: -    openshift_ca_host: "{{ groups.oo_first_master.0 }}" -    openshift_master_count: "{{ openshift.master.master_count | default(groups.oo_masters | length) }}" -  pre_tasks: -  # set_fact task copied from playbooks/common/openshift-master/config.yml -  # so that openshift_master_default_subdomain has a default value of "" -  # (emptry string). openshift_master_default_subdomain must have a default -  # value for openshift_master_facts to set metrics_public_url. -  # TODO: clean this up. -  - set_fact: -      openshift_master_default_subdomain: "{{ lookup('oo_option', 'openshift_master_default_subdomain') | default(None, true) }}" -    when: openshift_master_default_subdomain is not defined -  - stat: -      path: "{{ openshift_generated_configs_dir }}" -    register: openshift_generated_configs_dir_stat -  - name: Backup generated certificate and config directories -    command: > -      tar -czvf /etc/origin/master-node-cert-config-backup-{{ ansible_date_time.epoch }}.tgz -      {{ openshift_generated_configs_dir }} -      {{ openshift.common.config_base }}/master -    when: openshift_generated_configs_dir_stat.stat.exists -    delegate_to: "{{ openshift_ca_host }}" -    run_once: true -  - name: Remove generated certificate directories -    file: -      path: "{{ item }}" -      state: absent -    with_items: -    - "{{ openshift_generated_configs_dir }}" -  - name: Remove generated certificates -    file: -      path: "{{ openshift.common.config_base }}/master/{{ item }}" -      state: absent -    with_items: -    - "{{ hostvars[inventory_hostname] | certificates_to_synchronize(include_keys=false) }}" -    - "etcd.server.crt" -    - "etcd.server.key" -    - "master.etcd-client.crt" -    - "master.etcd-client.key" -    - "master.server.crt" -    - "master.server.key" -    - "openshift-master.crt" -    - "openshift-master.key" -    - "openshift-master.kubeconfig" -  - name: Remove CA certificate -    file: -      path: "{{ openshift.common.config_base }}/master/{{ item }}" -      state: absent -    when: openshift_certificates_redeploy_ca | default(false) | bool -    with_items: -    - "ca.crt" -    - "ca.key" -    - "ca.serial.txt" -    - "ca-bundle.crt" -  roles: -  - role: openshift_master_certificates -    openshift_master_etcd_hosts: "{{ hostvars -                                     | oo_select_keys(groups['oo_etcd_to_config'] | default([])) -                                     | oo_collect('openshift.common.hostname') -                                     | default(none, true) }}" -    openshift_certificates_redeploy: true -  - role: openshift_etcd_client_certificates -    etcd_certificates_redeploy: true -    etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}" -    etcd_cert_subdir: "openshift-master-{{ openshift.common.hostname }}" -    etcd_cert_config_dir: "{{ openshift.common.config_base }}/master" -    etcd_cert_prefix: "master.etcd-" -    when: groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config - -- name: Redeploy node certificates -  hosts: oo_nodes_to_config -  any_errors_fatal: true -  pre_tasks: -  - name: Remove CA certificate -    file: -      path: "{{ item }}" -      state: absent -    with_items: -    - "{{ openshift.common.config_base }}/node/ca.crt" -  roles: -  - role: openshift_node_certificates -    openshift_node_master_api_url: "{{ hostvars[groups.oo_first_master.0].openshift.master.api_url }}" -    openshift_ca_host: "{{ groups.oo_first_master.0 }}" -    openshift_certificates_redeploy: true - -- name: Restart etcd -  hosts: oo_etcd_to_config -  tasks: -  - name: restart etcd -    service: -      name: "{{ 'etcd' if not openshift.common.is_containerized | bool else 'etcd_container' }}" -      state: restarted - -- name: Stop master services -  hosts: oo_masters_to_config -  vars: -    openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}" -  tasks: -  - name: stop master -    service: name={{ openshift.common.service_type }}-master state=stopped -    when: not openshift_master_ha | bool -  - name: stop master api -    service: name={{ openshift.common.service_type }}-master-api state=stopped -    when: openshift_master_ha | bool and openshift_master_cluster_method == 'native' -  - name: stop master controllers -    service: name={{ openshift.common.service_type }}-master-controllers state=stopped -    when: openshift_master_ha | bool and openshift_master_cluster_method == 'native' - -- name: Start master services -  hosts: oo_masters_to_config -  serial: 1 -  vars: -    openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}" -  tasks: -  - name: start master -    service: name={{ openshift.common.service_type }}-master state=started -    when: not openshift_master_ha | bool -  - name: start master api -    service: name={{ openshift.common.service_type }}-master-api state=started -    when: openshift_master_ha | bool and openshift_master_cluster_method == 'native' -  - name: start master controllers -    service: name={{ openshift.common.service_type }}-master-controllers state=started -    when: openshift_master_ha | bool and openshift_master_cluster_method == 'native' - -- name: Restart masters (pacemaker) -  hosts: oo_first_master -  vars: -    openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}" -  tasks: -  - name: restart master -    command: pcs resource restart master -    when: openshift_master_ha | bool and openshift_master_cluster_method == 'pacemaker' - -- name: Restart nodes -  hosts: oo_nodes_to_config -  tasks: -  - name: restart node -    service: name={{ openshift.common.service_type }}-node state=restarted - -- name: Copy admin client config(s) -  hosts: oo_first_master -  tasks: -  - name: Create temp directory for kubeconfig -    command: mktemp -d /tmp/openshift-ansible-XXXXXX -    register: mktemp -    changed_when: False - -  - name: Copy admin client config(s) -    command: > -      cp {{ openshift.common.config_base }}/master//admin.kubeconfig {{ mktemp.stdout }}/admin.kubeconfig -    changed_when: False - -- name: Serially drain all nodes to trigger redeployments -  hosts: oo_nodes_to_config -  serial: 1 -  any_errors_fatal: true -  tasks: -  - name: Determine if node is currently scheduleable -    command: > -      {{ openshift.common.client_binary }} --config={{ hostvars[groups.oo_first_master.0].mktemp.stdout }}/admin.kubeconfig -      get node {{ openshift.node.nodename }} -o json -    register: node_output -    when: openshift_certificates_redeploy_ca | default(false) | bool -    delegate_to: "{{ groups.oo_first_master.0 }}" -    changed_when: false - -  - set_fact: -      was_schedulable: "{{ 'unschedulable' not in (node_output.stdout | from_json).spec }}" -    when: openshift_certificates_redeploy_ca | default(false) | bool - -  - name: Prepare for node draining -    command: > -      {{ openshift.common.client_binary }} adm --config={{ hostvars[groups.oo_first_master.0].mktemp.stdout }}/admin.kubeconfig -      manage-node {{ openshift.node.nodename }} -      --schedulable=false -    delegate_to: "{{ groups.oo_first_master.0 }}" -    when: openshift_certificates_redeploy_ca | default(false) | bool and was_schedulable | bool - -  - name: Drain node -    command: > -      {{ openshift.common.admin_binary }} --config={{ hostvars[groups.oo_first_master.0].mktemp.stdout }}/admin.kubeconfig -      drain {{ openshift.node.nodename }} --force --delete-local-data -    delegate_to: "{{ groups.oo_first_master.0 }}" -    when: openshift_certificates_redeploy_ca | default(false) | bool and was_schedulable | bool - -  - name: Set node schedulability -    command: > -      {{ openshift.common.client_binary }} adm --config={{ hostvars[groups.oo_first_master.0].mktemp.stdout }}/admin.kubeconfig -      manage-node {{ openshift.node.nodename }} --schedulable=true -    delegate_to: "{{ groups.oo_first_master.0 }}" -    when: openshift_certificates_redeploy_ca | default(false) | bool and was_schedulable | bool - -- name: Delete temporary directory -  hosts: oo_first_master -  tasks: -  - name: Delete temp directory -    file: -      name: "{{ mktemp.stdout }}" -      state: absent -    changed_when: False diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/ca.yml b/playbooks/common/openshift-cluster/redeploy-certificates/ca.yml new file mode 100644 index 000000000..0b1c39ba4 --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/ca.yml @@ -0,0 +1,353 @@ +--- +- name: Verify OpenShift version is greater than or equal to 1.2 or 3.2 +  hosts: oo_first_master +  tasks: +  - fail: +      msg: "The current OpenShift version is less than 1.2/3.2 and does not support CA bundles." +    when: not openshift.common.version_gte_3_2_or_1_2 | bool + +- name: Backup existing etcd CA certificate directories +  hosts: oo_etcd_to_config +  roles: +  - etcd_common +  tasks: +  - name: Determine if CA certificate directory exists +    stat: +      path: "{{ etcd_ca_dir }}" +    register: etcd_ca_certs_dir_stat +  - name: Backup generated etcd certificates +    command: > +      tar -czf {{ etcd_conf_dir }}/etcd-ca-certificate-backup-{{ ansible_date_time.epoch }}.tgz +      {{ etcd_ca_dir }} +    args: +      warn: no +    when: etcd_ca_certs_dir_stat.stat.exists | bool +  - name: Remove CA certificate directory +    file: +      path: "{{ etcd_ca_dir }}" +      state: absent +    when: etcd_ca_certs_dir_stat.stat.exists | bool + +- name: Generate new etcd CA +  hosts: oo_first_etcd +  roles: +  - role: etcd_ca +    etcd_peers: "{{ groups.oo_etcd_to_config | default([], true) }}" +    etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}" +    etcd_certificates_etcd_hosts: "{{ groups.oo_etcd_to_config | default([], true) }}" + +- name: Create temp directory for syncing certs +  hosts: localhost +  connection: local +  become: no +  gather_facts: no +  tasks: +  - name: Create local temp directory for syncing certs +    local_action: command mktemp -d /tmp/openshift-ansible-XXXXXXX +    register: g_etcd_mktemp +    changed_when: false + +- name: Distribute etcd CA to etcd hosts +  hosts: oo_etcd_to_config +  vars: +    etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}" +  roles: +  - etcd_common +  tasks: +  - name: Create a tarball of the etcd ca certs +    command: > +      tar -czvf {{ etcd_conf_dir }}/{{ etcd_ca_name }}.tgz +        -C {{ etcd_ca_dir }} . +    args: +      creates: "{{ etcd_conf_dir }}/{{ etcd_ca_name }}.tgz" +      warn: no +    delegate_to: "{{ etcd_ca_host }}" +    run_once: true +  - name: Retrieve etcd ca cert tarball +    fetch: +      src: "{{ etcd_conf_dir }}/{{ etcd_ca_name }}.tgz" +      dest: "{{ hostvars['localhost'].g_etcd_mktemp.stdout }}/" +      flat: yes +      fail_on_missing: yes +      validate_checksum: yes +    delegate_to: "{{ etcd_ca_host }}" +    run_once: true +  - name: Ensure ca directory exists +    file: +      path: "{{ etcd_ca_dir }}" +      state: directory +  - name: Unarchive etcd ca cert tarballs +    unarchive: +      src: "{{ hostvars['localhost'].g_etcd_mktemp.stdout }}/{{ etcd_ca_name }}.tgz" +      dest: "{{ etcd_ca_dir }}" +  - name: Read current etcd CA +    slurp: +      src: "{{ etcd_conf_dir }}/ca.crt" +    register: g_current_etcd_ca_output +  - name: Read new etcd CA +    slurp: +      src: "{{ etcd_ca_dir }}/ca.crt" +    register: g_new_etcd_ca_output +  - copy: +      content: "{{ (g_new_etcd_ca_output.content|b64decode) + (g_current_etcd_ca_output.content|b64decode) }}" +      dest: "{{ item }}/ca.crt" +    with_items: +    - "{{ etcd_conf_dir }}" +    - "{{ etcd_ca_dir }}" + +- name: Retrieve etcd CA certificate +  hosts: oo_first_etcd +  roles: +  - etcd_common +  tasks: +  - name: Retrieve etcd CA certificate +    fetch: +      src: "{{ etcd_conf_dir }}/ca.crt" +      dest: "{{ hostvars['localhost'].g_etcd_mktemp.stdout }}/" +      flat: yes +      fail_on_missing: yes +      validate_checksum: yes + +- name: Distribute etcd CA to masters +  hosts: oo_masters_to_config +  vars: +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +  tasks: +  - name: Deploy CA certificate, key, bundle and serial +    copy: +      src: "{{ hostvars['localhost'].g_etcd_mktemp.stdout }}/ca.crt" +      dest: "{{ openshift.common.config_base }}/master/master.etcd-ca.crt" +    when: groups.oo_etcd_to_config | default([]) | length > 0 + +- name: Delete temporary directory on localhost +  hosts: localhost +  connection: local +  become: no +  gather_facts: no +  tasks: +  - file: +      name: "{{ g_etcd_mktemp.stdout }}" +      state: absent +    changed_when: false + +- include: ../../../common/openshift-etcd/restart.yml + +# Update master config when ca-bundle not referenced. Services will be +# restarted below after new CA certificate has been distributed. +- name: Ensure ca-bundle.crt is referenced in master configuration +  hosts: oo_masters_to_config +  tasks: +  - slurp: +      src: "{{ openshift.common.config_base }}/master/master-config.yaml" +    register: g_master_config_output +  - modify_yaml: +      dest: "{{ openshift.common.config_base }}/master/master-config.yaml" +      yaml_key: kubeletClientInfo.ca +      yaml_value: ca-bundle.crt +    when: (g_master_config_output.content|b64decode|from_yaml).kubeletClientInfo.ca != 'ca-bundle.crt' +  - modify_yaml: +      dest: "{{ openshift.common.config_base }}/master/master-config.yaml" +      yaml_key: serviceAccountConfig.masterCA +      yaml_value: ca-bundle.crt +    when: (g_master_config_output.content|b64decode|from_yaml).serviceAccountConfig.masterCA != 'ca-bundle.crt' +  - modify_yaml: +      dest: "{{ openshift.common.config_base }}/master/master-config.yaml" +      yaml_key: oauthConfig.masterCA +      yaml_value: ca-bundle.crt +    when: (g_master_config_output.content|b64decode|from_yaml).oauthConfig.masterCA != 'ca-bundle.crt' +  - modify_yaml: +      dest: "{{ openshift.common.config_base }}/master/master-config.yaml" +      yaml_key: servingInfo.clientCA +      yaml_value: ca-bundle.crt +    when: (g_master_config_output.content|b64decode|from_yaml).servingInfo.clientCA != 'ca-bundle.crt' + +- name: Copy current OpenShift CA to legacy directory +  hosts: oo_masters_to_config +  pre_tasks: +  - name: Create legacy-ca directory +    file: +      path: "{{ openshift.common.config_base }}/master/legacy-ca" +      state: directory +      mode: 0700 +      owner: root +      group: root +  - command: mktemp -u XXXXXX +    register: g_legacy_ca_mktemp +    changed_when: false +  # Copy CA certificate, key, serial and bundle to legacy-ca with a +  # prefix generated by mktemp, ie. XXXXXX-ca.crt. +  # +  # The following roles will pick up all CA certificates matching +  # /.*-ca.crt/ in the legacy-ca directory and ensure they are present +  # in the OpenShift CA bundle. +  # - openshift_ca +  # - openshift_master_certificates +  # - openshift_node_certificates +  - name: Copy current OpenShift CA to legacy directory +    copy: +      src: "{{ openshift.common.config_base }}/master/{{ item }}" +      dest: "{{ openshift.common.config_base }}/master/legacy-ca/{{ g_legacy_ca_mktemp.stdout }}-{{ item }}" +      remote_src: true +    # It is possible that redeploying failed and files may be missing. +    # Ignore errors in this case. Files should have been copied to +    # legacy-ca directory in previous run. +    ignore_errors: true +    with_items: +    - "ca.crt" +    - "ca.key" +    - "ca.serial.txt" +    - "ca-bundle.crt" + +- name: Generate new OpenShift CA certificate +  hosts: oo_first_master +  pre_tasks: +  - name: Create temporary directory for creating new CA certificate +    command: > +      mktemp -d /tmp/openshift-ansible-XXXXXXX +    register: g_new_openshift_ca_mktemp +    changed_when: false +  roles: +  - role: openshift_ca +    # Set openshift_ca_config_dir to a temporary directory where CA +    # will be created. We'll replace the existing CA with the CA +    # created in the temporary directory. +    openshift_ca_config_dir: "{{ g_new_openshift_ca_mktemp.stdout }}" +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +    openshift_master_hostnames: "{{ hostvars +                                    | oo_select_keys(groups['oo_masters_to_config'] | default([])) +                                    | oo_collect('openshift.common.all_hostnames') +                                    | oo_flatten | unique }}" + +- name: Create temp directory for syncing certs +  hosts: localhost +  connection: local +  become: no +  gather_facts: no +  tasks: +  - name: Create local temp directory for syncing certs +    local_action: command mktemp -d /tmp/openshift-ansible-XXXXXXX +    register: g_master_mktemp +    changed_when: false + +- name: Retrieve OpenShift CA +  hosts: oo_first_master +  vars: +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +  tasks: +  - name: Retrieve CA certificate, key, bundle and serial +    fetch: +      src: "{{ hostvars[openshift_ca_host].g_new_openshift_ca_mktemp.stdout }}/{{ item }}" +      dest: "{{ hostvars['localhost'].g_master_mktemp.stdout }}/" +      flat: yes +      fail_on_missing: yes +      validate_checksum: yes +    with_items: +    - ca.crt +    - ca.key +    - ca-bundle.crt +    - ca.serial.txt +    delegate_to: "{{ openshift_ca_host }}" +    run_once: true +    changed_when: false + +- name: Distribute OpenShift CA to masters +  hosts: oo_masters_to_config +  vars: +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +  tasks: +  - name: Deploy CA certificate, key, bundle and serial +    copy: +      src: "{{ hostvars['localhost'].g_master_mktemp.stdout }}/{{ item }}" +      dest: "{{ openshift.common.config_base }}/master/" +    with_items: +    - ca.crt +    - ca.key +    - ca-bundle.crt +    - ca.serial.txt +  - name: Update master client kubeconfig CA data +    kubeclient_ca: +      client_path: "{{ openshift.common.config_base }}/master/openshift-master.kubeconfig" +      ca_path: "{{ openshift.common.config_base }}/master/ca-bundle.crt" +  - name: Update admin client kubeconfig CA data +    kubeclient_ca: +      client_path: "{{ openshift.common.config_base }}/master/admin.kubeconfig" +      ca_path: "{{ openshift.common.config_base }}/master/ca-bundle.crt" +  - name: Lookup default group for ansible_ssh_user +    command: "/usr/bin/id -g {{ ansible_ssh_user }}" +    changed_when: false +    register: _ansible_ssh_user_gid +  - set_fact: +      client_users: "{{ [ansible_ssh_user, 'root'] | unique }}" +  - name: Create the client config dir(s) +    file: +      path: "~{{ item }}/.kube" +      state: directory +      mode: 0700 +      owner: "{{ item }}" +      group: "{{ 'root' if item == 'root' else _ansible_ssh_user_gid.stdout  }}" +    with_items: "{{ client_users }}" +  - name: Copy the admin client config(s) +    copy: +      src: "{{ openshift.common.config_base }}/master/admin.kubeconfig" +      dest: "~{{ item }}/.kube/config" +      remote_src: yes +    with_items: "{{ client_users }}" +  - name: Update the permissions on the admin client config(s) +    file: +      path: "~{{ item }}/.kube/config" +      state: file +      mode: 0700 +      owner: "{{ item }}" +      group: "{{ 'root' if item == 'root' else _ansible_ssh_user_gid.stdout  }}" +    with_items: "{{ client_users }}" + +- include: ../../../common/openshift-master/restart.yml + +- name: Distribute OpenShift CA certificate to nodes +  hosts: oo_nodes_to_config +  vars: +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +  tasks: +  - copy: +      src: "{{ hostvars['localhost'].g_master_mktemp.stdout }}/ca-bundle.crt" +      dest: "{{ openshift.common.config_base }}/node/ca.crt" +  - name: Copy OpenShift CA to system CA trust +    copy: +      src: "{{ item.cert }}" +      dest: "/etc/pki/ca-trust/source/anchors/{{ item.id }}-{{ item.cert | basename }}" +      remote_src: yes +    with_items: +    - id: openshift +      cert: "{{ openshift.common.config_base }}/node/ca.crt" +    notify: +    - update ca trust +  - name: Update node client kubeconfig CA data +    kubeclient_ca: +      client_path: "{{ openshift.common.config_base }}/node/system:node:{{ openshift.common.hostname }}.kubeconfig" +      ca_path: "{{ openshift.common.config_base }}/node/ca.crt" +  handlers: +  # Normally this handler would restart docker after updating ca +  # trust. We'll do that when we restart nodes to avoid restarting +  # docker on all nodes in parallel. +  - name: update ca trust +    command: update-ca-trust + +- name: Delete temporary directory on CA host +  hosts: oo_first_master +  tasks: +  - file: +      path: "{{ g_new_openshift_ca_mktemp.stdout }}" +      state: absent + +- name: Delete temporary directory on localhost +  hosts: localhost +  connection: local +  become: no +  gather_facts: no +  tasks: +  - file: +      name: "{{ g_master_mktemp.stdout }}" +      state: absent +    changed_when: false + +- include: ../../../common/openshift-node/restart.yml diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/etcd.yml b/playbooks/common/openshift-cluster/redeploy-certificates/etcd.yml new file mode 100644 index 000000000..2963a5940 --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/etcd.yml @@ -0,0 +1,66 @@ +--- +- name: Backup and remove generated etcd certificates +  hosts: oo_first_etcd +  any_errors_fatal: true +  roles: +    - etcd_common +  post_tasks: +    - name: Determine if generated etcd certificates exist +      stat: +        path: "{{ etcd_conf_dir }}/generated_certs" +      register: etcd_generated_certs_dir_stat +    - name: Backup generated etcd certificates +      command: > +        tar -czf {{ etcd_conf_dir }}/etcd-generated-certificate-backup-{{ ansible_date_time.epoch }}.tgz +        {{ etcd_conf_dir }}/generated_certs +      args: +        warn: no +      when: etcd_generated_certs_dir_stat.stat.exists | bool +    - name: Remove generated etcd certificates +      file: +        path: "{{ item }}" +        state: absent +      with_items: +        - "{{ etcd_conf_dir }}/generated_certs" + +- name: Backup and removed deployed etcd certificates +  hosts: oo_etcd_to_config +  any_errors_fatal: true +  roles: +    - etcd_common +  post_tasks: +    - name: Backup etcd certificates +      command: > +        tar -czvf /etc/etcd/etcd-server-certificate-backup-{{ ansible_date_time.epoch }}.tgz +        {{ etcd_conf_dir }}/ca.crt +        {{ etcd_conf_dir }}/server.crt +        {{ etcd_conf_dir }}/server.key +        {{ etcd_conf_dir }}/peer.crt +        {{ etcd_conf_dir }}/peer.key +      args: +        warn: no + +- name: Redeploy etcd certificates +  hosts: oo_etcd_to_config +  any_errors_fatal: true +  roles: +    - role: openshift_etcd_server_certificates +      etcd_certificates_redeploy: true +      etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}" +      etcd_peers: "{{ groups.oo_etcd_to_config | default([], true) }}" +      etcd_certificates_etcd_hosts: "{{ groups.oo_etcd_to_config | default([], true) }}" +      openshift_ca_host: "{{ groups.oo_first_master.0 }}" + +- name: Redeploy etcd client certificates for masters +  hosts: oo_masters_to_config +  any_errors_fatal: true +  roles: +    - role: openshift_etcd_client_certificates +      etcd_certificates_redeploy: true +      etcd_ca_host: "{{ groups.oo_etcd_to_config.0 }}" +      etcd_cert_subdir: "openshift-master-{{ openshift.common.hostname }}" +      etcd_cert_config_dir: "{{ openshift.common.config_base }}/master" +      etcd_cert_prefix: "master.etcd-" +      openshift_ca_host: "{{ groups.oo_first_master.0 }}" +      openshift_master_count: "{{ openshift.master.master_count | default(groups.oo_masters | length) }}" +      when: groups.oo_etcd_to_config is defined and groups.oo_etcd_to_config diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/filter_plugins b/playbooks/common/openshift-cluster/redeploy-certificates/filter_plugins new file mode 120000 index 000000000..b1213dedb --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/filter_plugins @@ -0,0 +1 @@ +../../../../filter_plugins
\ No newline at end of file diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/library b/playbooks/common/openshift-cluster/redeploy-certificates/library new file mode 120000 index 000000000..9a53f009d --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/library @@ -0,0 +1 @@ +../../../../library
\ No newline at end of file diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/lookup_plugins b/playbooks/common/openshift-cluster/redeploy-certificates/lookup_plugins new file mode 120000 index 000000000..aff753026 --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/lookup_plugins @@ -0,0 +1 @@ +../../../../lookup_plugins
\ No newline at end of file diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/masters.yml b/playbooks/common/openshift-cluster/redeploy-certificates/masters.yml new file mode 100644 index 000000000..f653a111f --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/masters.yml @@ -0,0 +1,45 @@ +--- +- name: Redeploy master certificates +  hosts: oo_masters_to_config +  any_errors_fatal: true +  vars: +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +    openshift_master_count: "{{ openshift.master.master_count | default(groups.oo_masters | length) }}" +  pre_tasks: +  - stat: +      path: "{{ openshift_generated_configs_dir }}" +    register: openshift_generated_configs_dir_stat +  - name: Backup generated certificate and config directories +    command: > +      tar -czvf /etc/origin/master-node-cert-config-backup-{{ ansible_date_time.epoch }}.tgz +      {{ openshift_generated_configs_dir }} +      {{ openshift.common.config_base }}/master +    when: openshift_generated_configs_dir_stat.stat.exists +    delegate_to: "{{ openshift_ca_host }}" +    run_once: true +  - name: Remove generated certificate directories +    file: +      path: "{{ item }}" +      state: absent +    with_items: +    - "{{ openshift_generated_configs_dir }}" +  - name: Remove generated certificates +    file: +      path: "{{ openshift.common.config_base }}/master/{{ item }}" +      state: absent +    with_items: +    - "{{ hostvars[inventory_hostname] | certificates_to_synchronize(include_keys=false, include_ca=false) }}" +    - "etcd.server.crt" +    - "etcd.server.key" +    - "master.server.crt" +    - "master.server.key" +    - "openshift-master.crt" +    - "openshift-master.key" +    - "openshift-master.kubeconfig" +  roles: +  - role: openshift_master_certificates +    openshift_master_etcd_hosts: "{{ hostvars +                                     | oo_select_keys(groups['oo_etcd_to_config'] | default([])) +                                     | oo_collect('openshift.common.hostname') +                                     | default(none, true) }}" +    openshift_certificates_redeploy: true diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/nodes.yml b/playbooks/common/openshift-cluster/redeploy-certificates/nodes.yml new file mode 100644 index 000000000..4990a03f2 --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/nodes.yml @@ -0,0 +1,29 @@ +--- +- name: Ensure node directory is absent from generated configs +  hosts: oo_first_master +  tasks: +  # The generated configs directory (/etc/origin/generated-configs) is +  # backed up during redeployment of the control plane certificates. +  # We need to ensure that the generated config directory for +  # individual nodes has been deleted before continuing, so verify +  # that it is missing here. +  - name: Ensure node directories and tarballs are absent from generated configs +    shell: > +      rm -rf {{ openshift.common.config_base }}/generated-configs/node-* +    args: +      warn: no + +- name: Redeploy node certificates +  hosts: oo_nodes_to_config +  pre_tasks: +  - name: Remove CA certificate +    file: +      path: "{{ item }}" +      state: absent +    with_items: +    - "{{ openshift.common.config_base }}/node/ca.crt" +  roles: +  - role: openshift_node_certificates +    openshift_node_master_api_url: "{{ hostvars[groups.oo_first_master.0].openshift.master.api_url }}" +    openshift_ca_host: "{{ groups.oo_first_master.0 }}" +    openshift_certificates_redeploy: true diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/registry.yml b/playbooks/common/openshift-cluster/redeploy-certificates/registry.yml new file mode 100644 index 000000000..18b93e1d6 --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/registry.yml @@ -0,0 +1,93 @@ +--- +- name: Update registry certificates +  hosts: oo_first_master +  vars: +  tasks: +  - name: Create temp directory for kubeconfig +    command: mktemp -d /tmp/openshift-ansible-XXXXXX +    register: mktemp +    changed_when: false + +  - name: Copy admin client config(s) +    command: > +      cp {{ openshift.common.config_base }}/master//admin.kubeconfig {{ mktemp.stdout }}/admin.kubeconfig +    changed_when: false + +  - name: Determine if docker-registry exists +    command: > +      {{ openshift.common.client_binary }} get dc/docker-registry -o json +      --config={{ mktemp.stdout }}/admin.kubeconfig +      -n default +    register: l_docker_registry_dc +    failed_when: false +    changed_when: false + +  - set_fact: +      docker_registry_env_vars: "{{ ((l_docker_registry_dc.stdout | from_json)['spec']['template']['spec']['containers'][0]['env'] +                                      | oo_collect('name')) +                                      | default([]) }}" +      docker_registry_secrets: "{{ ((l_docker_registry_dc.stdout | from_json)['spec']['template']['spec']['volumes'] +                                     | oo_collect('secret') +                                     | oo_collect('secretName')) +                                     | default([]) }}" +    changed_when: false +    when: l_docker_registry_dc.rc == 0 + +  # Replace dc/docker-registry environment variable certificate data if set. +  - name: Update docker-registry environment variables +    shell: > +      {{ openshift.common.client_binary }} env dc/docker-registry +      OPENSHIFT_CA_DATA="$(cat /etc/origin/master/ca.crt)" +      OPENSHIFT_CERT_DATA="$(cat /etc/origin/master/openshift-registry.crt)" +      OPENSHIFT_KEY_DATA="$(cat /etc/origin/master/openshift-registry.key)" +      --config={{ mktemp.stdout }}/admin.kubeconfig +      -n default +    when: l_docker_registry_dc.rc == 0 and 'OPENSHIFT_CA_DATA' in docker_registry_env_vars and 'OPENSHIFT_CERT_DATA' in docker_registry_env_vars and 'OPENSHIFT_KEY_DATA' in docker_registry_env_vars + +  # Replace dc/docker-registry certificate secret contents if set. +  - block: +    - name: Retrieve registry service IP +      command: > +        {{ openshift.common.client_binary }} get service docker-registry +        -o jsonpath='{.spec.clusterIP}' +        --config={{ mktemp.stdout }}/admin.kubeconfig +        -n default +      register: docker_registry_service_ip +      changed_when: false + +    - set_fact: +        docker_registry_route_hostname: "{{ 'docker-registry-default.' ~ (openshift.master.default_subdomain | default('router.default.svc.cluster.local', true)) }}" +      changed_when: false + +    - name: Generate registry certificate +      command: > +        {{ openshift.common.client_binary }} adm ca create-server-cert +        --signer-cert={{ openshift.common.config_base }}/master/ca.crt +        --signer-key={{ openshift.common.config_base }}/master/ca.key +        --signer-serial={{ openshift.common.config_base }}/master/ca.serial.txt +        --hostnames="{{ docker_registry_service_ip.stdout }},docker-registry.default.svc.cluster.local,{{ docker_registry_route_hostname }}" +        --cert={{ openshift.common.config_base }}/master/registry.crt +        --key={{ openshift.common.config_base }}/master/registry.key + +    - name: Update registry certificates secret +      shell: > +        {{ openshift.common.client_binary }} secret new registry-certificates +        {{ openshift.common.config_base }}/master/registry.crt +        {{ openshift.common.config_base }}/master/registry.key +        --config={{ mktemp.stdout }}/admin.kubeconfig +        -n default +        -o json | oc replace -f - +    when: l_docker_registry_dc.rc == 0 and 'registry-certificates' in docker_registry_secrets and 'REGISTRY_HTTP_TLS_CERTIFICATE' in docker_registry_env_vars and 'REGISTRY_HTTP_TLS_KEY' in docker_registry_env_vars + +  - name: Redeploy docker registry +    command: > +      {{ openshift.common.client_binary }} deploy dc/docker-registry +      --latest +      --config={{ mktemp.stdout }}/admin.kubeconfig +      -n default + +  - name: Delete temp directory +    file: +      name: "{{ mktemp.stdout }}" +      state: absent +    changed_when: False diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/roles b/playbooks/common/openshift-cluster/redeploy-certificates/roles new file mode 120000 index 000000000..4bdbcbad3 --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/roles @@ -0,0 +1 @@ +../../../../roles
\ No newline at end of file diff --git a/playbooks/common/openshift-cluster/redeploy-certificates/router.yml b/playbooks/common/openshift-cluster/redeploy-certificates/router.yml new file mode 100644 index 000000000..03d64685d --- /dev/null +++ b/playbooks/common/openshift-cluster/redeploy-certificates/router.yml @@ -0,0 +1,79 @@ +--- +- name: Update router certificates +  hosts: oo_first_master +  vars: +  tasks: +  - name: Create temp directory for kubeconfig +    command: mktemp -d /tmp/openshift-ansible-XXXXXX +    register: mktemp +    changed_when: false + +  - name: Copy admin client config(s) +    command: > +      cp {{ openshift.common.config_base }}/master//admin.kubeconfig {{ mktemp.stdout }}/admin.kubeconfig +    changed_when: false + +  - name: Determine if router exists +    command: > +      {{ openshift.common.client_binary }} get dc/router -o json +      --config={{ mktemp.stdout }}/admin.kubeconfig +      -n default +    register: l_router_dc +    failed_when: false +    changed_when: false + +  - set_fact: +      router_env_vars: "{{ ((l_router_dc.stdout | from_json)['spec']['template']['spec']['containers'][0]['env'] +                             | oo_collect('name')) +                             | default([]) }}" +      router_secrets: "{{ ((l_router_dc.stdout | from_json)['spec']['template']['spec']['volumes'] +                            | oo_collect('secret') +                            | oo_collect('secretName')) +                            | default([]) }}" +    changed_when: false +    when: l_router_dc.rc == 0 + +  - name: Update router environment variables +    shell: > +      {{ openshift.common.client_binary }} env dc/router +      OPENSHIFT_CA_DATA="$(cat /etc/origin/master/ca.crt)" +      OPENSHIFT_CERT_DATA="$(cat /etc/origin/master/openshift-router.crt)" +      OPENSHIFT_KEY_DATA="$(cat /etc/origin/master/openshift-router.key)" +      --config={{ mktemp.stdout }}/admin.kubeconfig +      -n default +    when: l_router_dc.rc == 0 and 'OPENSHIFT_CA_DATA' in router_env_vars and 'OPENSHIFT_CERT_DATA' in router_env_vars and 'OPENSHIFT_KEY_DATA' in router_env_vars + +  - block: +    - name: Generate router certificate +      command: > +        {{ openshift.common.client_binary }} adm ca create-server-cert +        --hostnames=router.default.svc,router.default.svc.cluster.local +        --signer-cert={{ openshift.common.config_base }}/master/service-signer.crt +        --signer-key={{ openshift.common.config_base }}/master/service-signer.key +        --signer-serial={{ openshift.common.config_base }}/master/ca.serial.txt +        --cert={{ mktemp.stdout }}/tls.crt +        --key={{ mktemp.stdout }}/tls.key + +    - name: Update router certificates secret +      shell: > +        {{ openshift.common.client_binary }} secret new router-certs +        {{ mktemp.stdout }}/tls.crt +        {{ mktemp.stdout }}/tls.key +        --type=kubernetes.io/tls +        --config={{ mktemp.stdout }}/admin.kubeconfig +        -n default +        -o json | oc replace -f - +    when: l_router_dc.rc == 0 and 'router-certs' in router_secrets + +  - name: Redeploy router +    command: > +      {{ openshift.common.client_binary }} deploy dc/router +      --latest +      --config={{ mktemp.stdout }}/admin.kubeconfig +      -n default + +  - name: Delete temp directory +    file: +      name: "{{ mktemp.stdout }}" +      state: absent +    changed_when: False diff --git a/playbooks/common/openshift-cluster/std_include.yml b/playbooks/common/openshift-cluster/std_include.yml new file mode 100644 index 000000000..078991b12 --- /dev/null +++ b/playbooks/common/openshift-cluster/std_include.yml @@ -0,0 +1,42 @@ +--- +- name: Create initial host groups for localhost +  hosts: localhost +  connection: local +  become: no +  gather_facts: no +  tags: +  - always +  tasks: +  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml +  - name: Evaluate group l_oo_all_hosts +    add_host: +      name: "{{ item }}" +      groups: l_oo_all_hosts +    with_items: "{{ g_all_hosts | default([]) }}" +    changed_when: no + +- name: Create initial host groups for all hosts +  hosts: l_oo_all_hosts +  gather_facts: no +  tags: +  - always +  tasks: +  - include_vars: ../../byo/openshift-cluster/cluster_hosts.yml +  - set_fact: +      openshift_deployment_type: "{{ deployment_type }}" + +- include: evaluate_groups.yml +  tags: +  - always + +- include: initialize_facts.yml +  tags: +  - always + +- include: validate_hostnames.yml +  tags: +  - node + +- include: initialize_openshift_version.yml +  tags: +  - always diff --git a/playbooks/common/openshift-etcd/restart.yml b/playbooks/common/openshift-etcd/restart.yml new file mode 100644 index 000000000..196c86f28 --- /dev/null +++ b/playbooks/common/openshift-etcd/restart.yml @@ -0,0 +1,9 @@ +--- +- name: Restart etcd +  hosts: oo_etcd_to_config +  serial: 1 +  tasks: +    - name: restart etcd +      service: +        name: "{{ 'etcd' if not openshift.common.is_containerized | bool else 'etcd_container' }}" +        state: restarted diff --git a/playbooks/common/openshift-master/restart.yml b/playbooks/common/openshift-master/restart.yml new file mode 100644 index 000000000..b35368bf1 --- /dev/null +++ b/playbooks/common/openshift-master/restart.yml @@ -0,0 +1,19 @@ +--- +- include: ../../common/openshift-master/validate_restart.yml + +- name: Restart masters +  hosts: oo_masters_to_config +  vars: +    openshift_master_ha: "{{ groups.oo_masters_to_config | length > 1 }}" +  serial: 1 +  handlers: +  - include: roles/openshift_master/handlers/main.yml +    static: yes +  roles: +  - openshift_facts +  post_tasks: +  - include: ../../common/openshift-master/restart_hosts.yml +    when: openshift_rolling_restart_mode | default('services') == 'system' + +  - include: ../../common/openshift-master/restart_services.yml +    when: openshift_rolling_restart_mode | default('services') == 'services' diff --git a/playbooks/common/openshift-node/restart.yml b/playbooks/common/openshift-node/restart.yml new file mode 100644 index 000000000..6e9b1cca3 --- /dev/null +++ b/playbooks/common/openshift-node/restart.yml @@ -0,0 +1,47 @@ +--- +- name: Restart nodes +  hosts: oo_nodes_to_config +  serial: "{{ openshift_restart_nodes_serial | default(1) }}" +  tasks: +  - name: Restart docker +    service: name=docker state=restarted + +  - name: Update docker facts +    openshift_facts: +      role: docker + +  - name: Restart containerized services +    service: name={{ item }} state=started +    with_items: +    - etcd_container +    - openvswitch +    - "{{ openshift.common.service_type }}-master" +    - "{{ openshift.common.service_type }}-master-api" +    - "{{ openshift.common.service_type }}-master-controllers" +    - "{{ openshift.common.service_type }}-node" +    failed_when: false +    when: openshift.common.is_containerized | bool + +  - name: Wait for master API to come back online +    wait_for: +      host: "{{ openshift.common.hostname }}" +      state: started +      delay: 10 +      port: "{{ openshift.master.api_port }}" +    when: inventory_hostname in groups.oo_masters_to_config + +  - name: restart node +    service: +      name: "{{ openshift.common.service_type }}-node" +      state: restarted + +  - name: Wait for node to be ready +    command: > +      {{ hostvars[groups.oo_first_master.0].openshift.common.client_binary }} get node {{ openshift.common.hostname | lower }} --no-headers +    register: node_output +    delegate_to: "{{ groups.oo_first_master.0 }}" +    when: inventory_hostname in groups.oo_nodes_to_config +    until: "{{ node_output.stdout.split()[1].startswith('Ready')}}" +    # Give the node two minutes to come back online. +    retries: 24 +    delay: 5 diff --git a/roles/etcd_ca/tasks/main.yml b/roles/etcd_ca/tasks/main.yml index c4d5efa14..b4dea4a07 100644 --- a/roles/etcd_ca/tasks/main.yml +++ b/roles/etcd_ca/tasks/main.yml @@ -60,7 +60,8 @@    delegate_to: "{{ etcd_ca_host }}"    run_once: true -- command: > +- name: Create etcd CA certificate +  command: >      openssl req -config {{ etcd_openssl_conf }} -newkey rsa:4096      -keyout {{ etcd_ca_key }} -new -out {{ etcd_ca_cert }}      -x509 -extensions {{ etcd_ca_exts_self }} -batch -nodes diff --git a/roles/etcd_server_certificates/tasks/main.yml b/roles/etcd_server_certificates/tasks/main.yml index 1acdf1c85..242c1e997 100644 --- a/roles/etcd_server_certificates/tasks/main.yml +++ b/roles/etcd_server_certificates/tasks/main.yml @@ -58,6 +58,7 @@                   ~ etcd_cert_prefix ~ 'server.crt' }}"    environment:      SAN: "IP:{{ etcd_ip }}" +  when: etcd_server_certs_missing | bool    delegate_to: "{{ etcd_ca_host }}"  - name: Create the peer csr diff --git a/roles/openshift_ca/tasks/main.yml b/roles/openshift_ca/tasks/main.yml index e21397170..4efc77f11 100644 --- a/roles/openshift_ca/tasks/main.yml +++ b/roles/openshift_ca/tasks/main.yml @@ -41,10 +41,9 @@    run_once: true  - set_fact: -    master_ca_missing: "{{ true if openshift_certificates_redeploy | default(false) | bool -                           else False in (g_master_ca_stat_result.results -                                         | oo_collect(attribute='stat.exists') -                                         | list) }}" +    master_ca_missing: "{{ False in (g_master_ca_stat_result.results +                                     | oo_collect(attribute='stat.exists') +                                     | list) }}"    run_once: true  - name: Retain original serviceaccount keys @@ -61,7 +60,6 @@    copy:      src: "{{ item.src }}"      dest: "{{ openshift_ca_config_dir }}/{{ item.dest }}" -    force: "{{ true if openshift_certificates_redeploy_ca | default(false) | bool else false }}"    with_items:    - src: "{{ (openshift_master_ca_certificate | default({'certfile':none})).certfile }}"      dest: ca.crt @@ -73,25 +71,35 @@  - name: Create ca serial    copy: -    content: "1" +    content: "00"      dest: "{{ openshift_ca_config_dir }}/ca.serial.txt" -    force: "{{ true if openshift_certificates_redeploy | default(false) | bool else false }}" +    force: "{{ openshift_certificates_redeploy | default(false) | bool }}"    when: openshift_master_ca_certificate is defined    delegate_to: "{{ openshift_ca_host }}"    run_once: true +- find: +    paths: "{{ openshift.common.config_base }}/master/legacy-ca/" +    patterns: ".*-ca.crt" +    use_regex: true +  register: g_master_legacy_ca_result + +# This should NOT replace the CA due to --overwrite=false when a CA already exists.  - name: Create the master certificates if they do not already exist    command: >      {{ openshift.common.client_binary }} adm create-master-certs      {% for named_ca_certificate in openshift.master.named_certificates | default([]) | oo_collect('cafile') %}      --certificate-authority {{ named_ca_certificate }}      {% endfor %} +    {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | oo_collect('path') %} +    --certificate-authority {{ legacy_ca_certificate }} +    {% endfor %}      --hostnames={{ openshift.common.all_hostnames | join(',') }}      --master={{ openshift.master.api_url }}      --public-master={{ openshift.master.public_api_url }}      --cert-dir={{ openshift_ca_config_dir }}      --overwrite=false -  when: master_ca_missing | bool +  when: master_ca_missing | bool or openshift_certificates_redeploy | default(false) | bool    delegate_to: "{{ openshift_ca_host }}"    run_once: true diff --git a/roles/openshift_master/templates/master.yaml.v1.j2 b/roles/openshift_master/templates/master.yaml.v1.j2 index cf7ceacff..9ae54dac1 100644 --- a/roles/openshift_master/templates/master.yaml.v1.j2 +++ b/roles/openshift_master/templates/master.yaml.v1.j2 @@ -102,7 +102,11 @@ imagePolicyConfig:{{ openshift.master.image_policy_config | to_padded_yaml(level  kind: MasterConfig  kubeletClientInfo:  {# TODO: allow user specified kubelet port #} +{% if openshift.common.version_gte_3_2_or_1_2 | bool %} +  ca: ca-bundle.crt +{% else %}    ca: ca.crt +{% endif %}    certFile: master.kubelet-client.crt    keyFile: master.kubelet-client.key    port: 10250 @@ -221,7 +225,11 @@ servingInfo:    bindAddress: {{ openshift.master.bind_addr }}:{{ openshift.master.api_port }}    bindNetwork: tcp4    certFile: master.server.crt +{% if openshift.common.version_gte_3_2_or_1_2 | bool %} +  clientCA: ca-bundle.crt +{% else %}    clientCA: ca.crt +{% endif %}    keyFile: master.server.key    maxRequestsInFlight: {{ openshift.master.max_requests_inflight }}    requestTimeoutSeconds: 3600 diff --git a/roles/openshift_master_certificates/tasks/main.yml b/roles/openshift_master_certificates/tasks/main.yml index 4620dd877..7a5ed51ec 100644 --- a/roles/openshift_master_certificates/tasks/main.yml +++ b/roles/openshift_master_certificates/tasks/main.yml @@ -38,12 +38,22 @@    when: master_certs_missing | bool and inventory_hostname != openshift_ca_host    delegate_to: "{{ openshift_ca_host }}" +- find: +    paths: "{{ openshift_master_config_dir }}/legacy-ca/" +    patterns: ".*-ca.crt" +    use_regex: true +  register: g_master_legacy_ca_result +  delegate_to: "{{ openshift_ca_host }}" +  - name: Create the master server certificate    command: >      {{ hostvars[openshift_ca_host].openshift.common.client_binary }} adm ca create-server-cert      {% for named_ca_certificate in openshift.master.named_certificates | default([]) | oo_collect('cafile') %}      --certificate-authority {{ named_ca_certificate }}      {% endfor %} +    {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | oo_collect('path') %} +    --certificate-authority {{ legacy_ca_certificate }} +    {% endfor %}      --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }}      --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt      --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key diff --git a/roles/openshift_node_certificates/handlers/main.yml b/roles/openshift_node_certificates/handlers/main.yml index a74668b13..1aa826c09 100644 --- a/roles/openshift_node_certificates/handlers/main.yml +++ b/roles/openshift_node_certificates/handlers/main.yml @@ -8,3 +8,4 @@    systemd:      name: docker      state: restarted +  when: not openshift_certificates_redeploy | default(false) | bool diff --git a/roles/openshift_node_certificates/tasks/main.yml b/roles/openshift_node_certificates/tasks/main.yml index a263f4f3a..4cb89aba2 100644 --- a/roles/openshift_node_certificates/tasks/main.yml +++ b/roles/openshift_node_certificates/tasks/main.yml @@ -42,20 +42,30 @@    when: node_certs_missing | bool    delegate_to: "{{ openshift_ca_host }}" +- find: +    paths: "{{ openshift.common.config_base }}/master/legacy-ca/" +    patterns: ".*-ca.crt" +    use_regex: true +  register: g_master_legacy_ca_result +  delegate_to: "{{ openshift_ca_host }}" +  - name: Generate the node client config    command: >      {{ hostvars[openshift_ca_host].openshift.common.client_binary }} adm create-api-client-config -      {% for named_ca_certificate in hostvars[openshift_ca_host].openshift.master.named_certificates | default([]) | oo_collect('cafile') %} -      --certificate-authority {{ named_ca_certificate }} -      {% endfor %} -      --certificate-authority={{ openshift_ca_cert }} -      --client-dir={{ openshift_generated_configs_dir }}/node-{{ hostvars[item].openshift.common.hostname }} -      --groups=system:nodes -      --master={{ hostvars[openshift_ca_host].openshift.master.api_url }} -      --signer-cert={{ openshift_ca_cert }} -      --signer-key={{ openshift_ca_key }} -      --signer-serial={{ openshift_ca_serial }} -      --user=system:node:{{ hostvars[item].openshift.common.hostname }} +    {% for named_ca_certificate in hostvars[openshift_ca_host].openshift.master.named_certificates | default([]) | oo_collect('cafile') %} +    --certificate-authority {{ named_ca_certificate }} +    {% endfor %} +    {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | oo_collect('path') %} +    --certificate-authority {{ legacy_ca_certificate }} +    {% endfor %} +    --certificate-authority={{ openshift_ca_cert }} +    --client-dir={{ openshift_generated_configs_dir }}/node-{{ hostvars[item].openshift.common.hostname }} +    --groups=system:nodes +    --master={{ hostvars[openshift_ca_host].openshift.master.api_url }} +    --signer-cert={{ openshift_ca_cert }} +    --signer-key={{ openshift_ca_key }} +    --signer-serial={{ openshift_ca_serial }} +    --user=system:node:{{ hostvars[item].openshift.common.hostname }}    args:      creates: "{{ openshift_generated_configs_dir }}/node-{{ hostvars[item].openshift.common.hostname }}"    with_items: "{{ hostvars  | 
