diff options
Diffstat (limited to 'roles')
52 files changed, 822 insertions, 344 deletions
diff --git a/roles/etcd/meta/main.yml b/roles/etcd/meta/main.yml index 7156a9fff..cfd72dfbc 100644 --- a/roles/etcd/meta/main.yml +++ b/roles/etcd/meta/main.yml @@ -7,7 +7,7 @@ galaxy_info: description: etcd management company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.2 + min_ansible_version: 2.1 platforms: - name: EL versions: @@ -22,4 +22,4 @@ dependencies: port: "{{etcd_client_port}}/tcp" - service: etcd peering port: "{{ etcd_peer_port }}/tcp" -- role: etcd_common +- role: etcd_server_certificates diff --git a/roles/etcd/tasks/main.yml b/roles/etcd/tasks/main.yml index 75d40216d..ba4136327 100644 --- a/roles/etcd/tasks/main.yml +++ b/roles/etcd/tasks/main.yml @@ -58,30 +58,6 @@ group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" mode: 0700 -- name: Validate permissions on certificate files - file: - path: "{{ item }}" - mode: 0600 - owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" - group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" - when: etcd_url_scheme == 'https' - with_items: - - "{{ etcd_ca_file }}" - - "{{ etcd_cert_file }}" - - "{{ etcd_key_file }}" - -- name: Validate permissions on peer certificate files - file: - path: "{{ item }}" - mode: 0600 - owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" - group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" - when: etcd_peer_url_scheme == 'https' - with_items: - - "{{ etcd_peer_ca_file }}" - - "{{ etcd_peer_cert_file }}" - - "{{ etcd_peer_key_file }}" - - name: Write etcd global config file template: src: etcd.conf.j2 diff --git a/roles/etcd/templates/etcd.conf.j2 b/roles/etcd/templates/etcd.conf.j2 index cd048ec60..7ccf78212 100644 --- a/roles/etcd/templates/etcd.conf.j2 +++ b/roles/etcd/templates/etcd.conf.j2 @@ -1,5 +1,5 @@ {% macro initial_cluster() -%} -{% for host in etcd_peers -%} +{% for host in etcd_peers | default([]) -%} {% if loop.last -%} {{ hostvars[host].etcd_hostname }}={{ etcd_peer_url_scheme }}://{{ hostvars[host].etcd_ip }}:{{ etcd_peer_port }} {%- else -%} diff --git a/roles/etcd_ca/meta/main.yml b/roles/etcd_ca/meta/main.yml index d02456ca3..e3e2f7781 100644 --- a/roles/etcd_ca/meta/main.yml +++ b/roles/etcd_ca/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: author: Jason DeTiberus - description: + description: Etcd CA company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.9 + min_ansible_version: 2.1 platforms: - name: EL versions: @@ -13,4 +13,4 @@ galaxy_info: - cloud - system dependencies: -- { role: etcd_common } +- role: etcd_common diff --git a/roles/etcd_ca/tasks/main.yml b/roles/etcd_ca/tasks/main.yml index e1bb9baed..865074e41 100644 --- a/roles/etcd_ca/tasks/main.yml +++ b/roles/etcd_ca/tasks/main.yml @@ -2,6 +2,8 @@ - name: Install openssl action: "{{ ansible_pkg_mgr }} name=openssl state=present" when: not etcd_is_atomic | bool + delegate_to: "{{ etcd_ca_host }}" + run_once: true - file: path: "{{ item }}" @@ -13,29 +15,41 @@ - "{{ etcd_ca_new_certs_dir }}" - "{{ etcd_ca_crl_dir }}" - "{{ etcd_ca_dir }}/fragments" + delegate_to: "{{ etcd_ca_host }}" + run_once: true - command: cp /etc/pki/tls/openssl.cnf ./ args: chdir: "{{ etcd_ca_dir }}/fragments" creates: "{{ etcd_ca_dir }}/fragments/openssl.cnf" + delegate_to: "{{ etcd_ca_host }}" + run_once: true - template: dest: "{{ etcd_ca_dir }}/fragments/openssl_append.cnf" src: openssl_append.j2 backup: true + delegate_to: "{{ etcd_ca_host }}" + run_once: true - assemble: src: "{{ etcd_ca_dir }}/fragments" dest: "{{ etcd_openssl_conf }}" + delegate_to: "{{ etcd_ca_host }}" + run_once: true - command: touch {{ etcd_ca_db }} args: creates: "{{ etcd_ca_db }}" + delegate_to: "{{ etcd_ca_host }}" + run_once: true - copy: dest: "{{ etcd_ca_serial }}" content: "01" force: no + delegate_to: "{{ etcd_ca_host }}" + run_once: true - command: > openssl req -config {{ etcd_openssl_conf }} -newkey rsa:4096 @@ -48,3 +62,5 @@ creates: "{{ etcd_ca_cert }}" environment: SAN: 'etcd-signer' + delegate_to: "{{ etcd_ca_host }}" + run_once: true diff --git a/roles/etcd_certificates/tasks/client.yml b/roles/etcd_certificates/tasks/client.yml deleted file mode 100644 index b497a46c0..000000000 --- a/roles/etcd_certificates/tasks/client.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -- name: Ensure generated_certs directory present - file: - path: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - state: directory - mode: 0700 - with_items: "{{ etcd_needing_client_certs | default([]) }}" - -- name: Create the client csr - command: > - openssl req -new -keyout {{ item.etcd_cert_prefix }}client.key - -config {{ etcd_openssl_conf }} - -out {{ item.etcd_cert_prefix }}client.csr - -reqexts {{ etcd_req_ext }} -batch -nodes - -subj /CN={{ item.etcd_hostname }} - args: - chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - creates: "{{ etcd_generated_certs_dir ~ '/' ~ item.etcd_cert_subdir ~ '/' - ~ item.etcd_cert_prefix ~ 'client.csr' }}" - environment: - SAN: "IP:{{ item.etcd_ip }}" - with_items: "{{ etcd_needing_client_certs | default([]) }}" - -- name: Sign and create the client crt - command: > - openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} - -out {{ item.etcd_cert_prefix }}client.crt - -in {{ item.etcd_cert_prefix }}client.csr - -batch - args: - chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - creates: "{{ etcd_generated_certs_dir ~ '/' ~ item.etcd_cert_subdir ~ '/' - ~ item.etcd_cert_prefix ~ 'client.crt' }}" - environment: - SAN: "IP:{{ item.etcd_ip }}" - with_items: "{{ etcd_needing_client_certs | default([]) }}" - -- file: - src: "{{ etcd_ca_cert }}" - dest: "{{ etcd_generated_certs_dir}}/{{ item.etcd_cert_subdir }}/{{ item.etcd_cert_prefix }}ca.crt" - state: hard - with_items: "{{ etcd_needing_client_certs | default([]) }}" diff --git a/roles/etcd_certificates/tasks/main.yml b/roles/etcd_certificates/tasks/main.yml deleted file mode 100644 index 17092ca58..000000000 --- a/roles/etcd_certificates/tasks/main.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- include: client.yml - when: etcd_needing_client_certs | default([]) | length > 0 - -- include: server.yml - when: etcd_needing_server_certs | default([]) | length > 0 diff --git a/roles/etcd_certificates/tasks/server.yml b/roles/etcd_certificates/tasks/server.yml deleted file mode 100644 index 934b8b805..000000000 --- a/roles/etcd_certificates/tasks/server.yml +++ /dev/null @@ -1,71 +0,0 @@ ---- -- name: Ensure generated_certs directory present - file: - path: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - state: directory - mode: 0700 - with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- name: Create the server csr - command: > - openssl req -new -keyout {{ item.etcd_cert_prefix }}server.key - -config {{ etcd_openssl_conf }} - -out {{ item.etcd_cert_prefix }}server.csr - -reqexts {{ etcd_req_ext }} -batch -nodes - -subj /CN={{ item.etcd_hostname }} - args: - chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - creates: "{{ etcd_generated_certs_dir ~ '/' ~ item.etcd_cert_subdir ~ '/' - ~ item.etcd_cert_prefix ~ 'server.csr' }}" - environment: - SAN: "IP:{{ item.etcd_ip }}" - with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- name: Sign and create the server crt - command: > - openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} - -out {{ item.etcd_cert_prefix }}server.crt - -in {{ item.etcd_cert_prefix }}server.csr - -extensions {{ etcd_ca_exts_server }} -batch - args: - chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - creates: "{{ etcd_generated_certs_dir ~ '/' ~ item.etcd_cert_subdir ~ '/' - ~ item.etcd_cert_prefix ~ 'server.crt' }}" - environment: - SAN: "IP:{{ item.etcd_ip }}" - with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- name: Create the peer csr - command: > - openssl req -new -keyout {{ item.etcd_cert_prefix }}peer.key - -config {{ etcd_openssl_conf }} - -out {{ item.etcd_cert_prefix }}peer.csr - -reqexts {{ etcd_req_ext }} -batch -nodes - -subj /CN={{ item.etcd_hostname }} - args: - chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - creates: "{{ etcd_generated_certs_dir ~ '/' ~ item.etcd_cert_subdir ~ '/' - ~ item.etcd_cert_prefix ~ 'peer.csr' }}" - environment: - SAN: "IP:{{ item.etcd_ip }}" - with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- name: Sign and create the peer crt - command: > - openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} - -out {{ item.etcd_cert_prefix }}peer.crt - -in {{ item.etcd_cert_prefix }}peer.csr - -extensions {{ etcd_ca_exts_peer }} -batch - args: - chdir: "{{ etcd_generated_certs_dir }}/{{ item.etcd_cert_subdir }}" - creates: "{{ etcd_generated_certs_dir ~ '/' ~ item.etcd_cert_subdir ~ '/' - ~ item.etcd_cert_prefix ~ 'peer.crt' }}" - environment: - SAN: "IP:{{ item.etcd_ip }}" - with_items: "{{ etcd_needing_server_certs | default([]) }}" - -- file: - src: "{{ etcd_ca_cert }}" - dest: "{{ etcd_generated_certs_dir}}/{{ item.etcd_cert_subdir }}/{{ item.etcd_cert_prefix }}ca.crt" - state: hard - with_items: "{{ etcd_needing_server_certs | default([]) }}" diff --git a/roles/etcd_certificates/README.md b/roles/etcd_client_certificates/README.md index 95f8f8aab..269d5296d 100644 --- a/roles/etcd_certificates/README.md +++ b/roles/etcd_client_certificates/README.md @@ -1,5 +1,5 @@ -OpenShift etcd certificates -======================== +OpenShift Etcd Certificates +=========================== TODO diff --git a/roles/etcd_client_certificates/library b/roles/etcd_client_certificates/library new file mode 120000 index 000000000..494d3c39e --- /dev/null +++ b/roles/etcd_client_certificates/library @@ -0,0 +1 @@ +../../library
\ No newline at end of file diff --git a/roles/etcd_client_certificates/meta/main.yml b/roles/etcd_client_certificates/meta/main.yml new file mode 100644 index 000000000..efebdb599 --- /dev/null +++ b/roles/etcd_client_certificates/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: + author: Jason DeTiberus + description: Etcd Client Certificates + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 2.1 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud + - system +dependencies: +- role: etcd_common diff --git a/roles/etcd_client_certificates/tasks/main.yml b/roles/etcd_client_certificates/tasks/main.yml new file mode 100644 index 000000000..275aa0a63 --- /dev/null +++ b/roles/etcd_client_certificates/tasks/main.yml @@ -0,0 +1,137 @@ +--- +- name: Ensure CA certificate exists on etcd_ca_host + stat: + path: "{{ etcd_ca_cert }}" + register: g_ca_cert_stat_result + delegate_to: "{{ etcd_ca_host }}" + run_once: true + +- fail: + msg: > + CA certificate {{ etcd_ca_cert }} doesn't exist on CA host + {{ etcd_ca_host }}. Apply 'etcd_ca' role to + {{ etcd_ca_host }}. + when: not g_ca_cert_stat_result.stat.exists | bool + run_once: true + +- name: Check status of external etcd certificatees + stat: + path: "{{ etcd_cert_config_dir }}/{{ item }}" + with_items: + - "{{ etcd_cert_prefix }}client.crt" + - "{{ etcd_cert_prefix }}client.key" + - "{{ etcd_cert_prefix }}ca.crt" + register: g_external_etcd_cert_stat_result + when: not etcd_certificates_redeploy | default(false) | bool + +- set_fact: + etcd_client_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool + else (False in (g_external_etcd_cert_stat_result.results + | default({}) + | oo_collect(attribute='stat.exists') + | list)) }}" + +- name: Ensure generated_certs directory present + file: + path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + state: directory + mode: 0700 + when: etcd_client_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Create the client csr + command: > + openssl req -new -keyout {{ etcd_cert_prefix }}client.key + -config {{ etcd_openssl_conf }} + -out {{ etcd_cert_prefix }}client.csr + -reqexts {{ etcd_req_ext }} -batch -nodes + -subj /CN={{ etcd_hostname }} + args: + chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/' + ~ etcd_cert_prefix ~ 'client.csr' }}" + environment: + SAN: "IP:{{ etcd_ip }}" + when: etcd_client_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +# Certificates must be signed serially in order to avoid competing +# for the serial file. +- name: Sign and create the client crt + delegated_serial_command: + command: > + openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} + -out {{ etcd_cert_prefix }}client.crt + -in {{ etcd_cert_prefix }}client.csr + -batch + chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/' + ~ etcd_cert_prefix ~ 'client.crt' }}" + environment: + SAN: "IP:{{ etcd_ip }}" + when: etcd_client_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- file: + src: "{{ etcd_ca_cert }}" + dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt" + state: hard + when: etcd_client_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Create local temp directory for syncing certs + local_action: command mktemp -d /tmp/etcd_certificates-XXXXXXX + register: g_etcd_client_mktemp + changed_when: False + when: etcd_client_certs_missing | bool + delegate_to: localhost + become: no + +- name: Create a tarball of the etcd certs + command: > + tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz + -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} . + args: + creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" + when: etcd_client_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Retrieve the etcd cert tarballs + fetch: + src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" + dest: "{{ g_etcd_client_mktemp.stdout }}/" + flat: yes + fail_on_missing: yes + validate_checksum: yes + when: etcd_client_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Ensure certificate directory exists + file: + path: "{{ etcd_cert_config_dir }}" + state: directory + when: etcd_client_certs_missing | bool + +- name: Unarchive etcd cert tarballs + unarchive: + src: "{{ g_etcd_client_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz" + dest: "{{ etcd_cert_config_dir }}" + when: etcd_client_certs_missing | bool + +- file: + path: "{{ etcd_cert_config_dir }}/{{ item }}" + owner: root + group: root + mode: 0600 + with_items: + - "{{ etcd_cert_prefix }}client.crt" + - "{{ etcd_cert_prefix }}client.key" + - "{{ etcd_cert_prefix }}ca.crt" + when: etcd_client_certs_missing | bool + +- name: Delete temporary directory + file: name={{ g_etcd_client_mktemp.stdout }} state=absent + changed_when: False + when: etcd_client_certs_missing | bool + delegate_to: localhost + become: no diff --git a/roles/etcd_server_certificates/README.md b/roles/etcd_server_certificates/README.md new file mode 100644 index 000000000..269d5296d --- /dev/null +++ b/roles/etcd_server_certificates/README.md @@ -0,0 +1,34 @@ +OpenShift Etcd Certificates +=========================== + +TODO + +Requirements +------------ + +TODO + +Role Variables +-------------- + +TODO + +Dependencies +------------ + +TODO + +Example Playbook +---------------- + +TODO + +License +------- + +Apache License Version 2.0 + +Author Information +------------------ + +Scott Dodson (sdodson@redhat.com) diff --git a/roles/etcd_server_certificates/library b/roles/etcd_server_certificates/library new file mode 120000 index 000000000..494d3c39e --- /dev/null +++ b/roles/etcd_server_certificates/library @@ -0,0 +1 @@ +../../library
\ No newline at end of file diff --git a/roles/etcd_certificates/meta/main.yml b/roles/etcd_server_certificates/meta/main.yml index 41370fab4..b453f2bd8 100644 --- a/roles/etcd_certificates/meta/main.yml +++ b/roles/etcd_server_certificates/meta/main.yml @@ -1,10 +1,10 @@ --- galaxy_info: author: Jason DeTiberus - description: + description: Etcd Server Certificates company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.8 + min_ansible_version: 2.1 platforms: - name: EL versions: @@ -13,4 +13,4 @@ galaxy_info: - cloud - system dependencies: -- { role: etcd_ca } +- role: etcd_ca diff --git a/roles/etcd_server_certificates/tasks/main.yml b/roles/etcd_server_certificates/tasks/main.yml new file mode 100644 index 000000000..718515023 --- /dev/null +++ b/roles/etcd_server_certificates/tasks/main.yml @@ -0,0 +1,179 @@ +--- +- name: Install etcd + action: "{{ ansible_pkg_mgr }} name=etcd state=present" + when: not etcd_is_containerized | bool + +- name: Check status of etcd certificates + stat: + path: "{{ etcd_cert_config_dir }}/{{ item }}" + with_items: + - "{{ etcd_cert_prefix }}server.crt" + - "{{ etcd_cert_prefix }}peer.crt" + - "{{ etcd_cert_prefix }}ca.crt" + register: g_etcd_server_cert_stat_result + when: not etcd_certificates_redeploy | default(false) | bool + +- set_fact: + etcd_server_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool + else (False in (g_etcd_server_cert_stat_result.results + | default({}) + | oo_collect(attribute='stat.exists') + | list)) }}" + +- name: Ensure generated_certs directory present + file: + path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + state: directory + mode: 0700 + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Create the server csr + command: > + openssl req -new -keyout {{ etcd_cert_prefix }}server.key + -config {{ etcd_openssl_conf }} + -out {{ etcd_cert_prefix }}server.csr + -reqexts {{ etcd_req_ext }} -batch -nodes + -subj /CN={{ etcd_hostname }} + args: + chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/' + ~ etcd_cert_prefix ~ 'server.csr' }}" + environment: + SAN: "IP:{{ etcd_ip }}" + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +# Certificates must be signed serially in order to avoid competing +# for the serial file. +- name: Sign and create the server crt + delegated_serial_command: + command: > + openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} + -out {{ etcd_cert_prefix }}server.crt + -in {{ etcd_cert_prefix }}server.csr + -extensions {{ etcd_ca_exts_server }} -batch + chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/' + ~ etcd_cert_prefix ~ 'server.crt' }}" + environment: + SAN: "IP:{{ etcd_ip }}" + delegate_to: "{{ etcd_ca_host }}" + +- name: Create the peer csr + command: > + openssl req -new -keyout {{ etcd_cert_prefix }}peer.key + -config {{ etcd_openssl_conf }} + -out {{ etcd_cert_prefix }}peer.csr + -reqexts {{ etcd_req_ext }} -batch -nodes + -subj /CN={{ etcd_hostname }} + args: + chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/' + ~ etcd_cert_prefix ~ 'peer.csr' }}" + environment: + SAN: "IP:{{ etcd_ip }}" + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +# Certificates must be signed serially in order to avoid competing +# for the serial file. +- name: Sign and create the peer crt + delegated_serial_command: + command: > + openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }} + -out {{ etcd_cert_prefix }}peer.crt + -in {{ etcd_cert_prefix }}peer.csr + -extensions {{ etcd_ca_exts_peer }} -batch + chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}" + creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/' + ~ etcd_cert_prefix ~ 'peer.crt' }}" + environment: + SAN: "IP:{{ etcd_ip }}" + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- file: + src: "{{ etcd_ca_cert }}" + dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt" + state: hard + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Create local temp directory for syncing certs + local_action: command mktemp -d /tmp/etcd_certificates-XXXXXXX + become: no + register: g_etcd_server_mktemp + changed_when: False + when: etcd_server_certs_missing | bool + delegate_to: localhost + +- name: Create a tarball of the etcd certs + command: > + tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz + -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} . + args: + creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Retrieve etcd cert tarball + fetch: + src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz" + dest: "{{ g_etcd_server_mktemp.stdout }}/" + flat: yes + fail_on_missing: yes + validate_checksum: yes + when: etcd_server_certs_missing | bool + delegate_to: "{{ etcd_ca_host }}" + +- name: Ensure certificate directory exists + file: + path: "{{ etcd_cert_config_dir }}" + state: directory + when: etcd_server_certs_missing | bool + +- name: Unarchive cert tarball + unarchive: + src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz" + dest: "{{ etcd_cert_config_dir }}" + when: etcd_server_certs_missing | bool + +- name: Delete temporary directory + file: name={{ g_etcd_server_mktemp.stdout }} state=absent + become: no + changed_when: False + when: etcd_server_certs_missing | bool + delegate_to: localhost + +- name: Validate permissions on certificate files + file: + path: "{{ item }}" + mode: 0600 + owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" + group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" + when: etcd_url_scheme == 'https' + with_items: + - "{{ etcd_ca_file }}" + - "{{ etcd_cert_file }}" + - "{{ etcd_key_file }}" + +- name: Validate permissions on peer certificate files + file: + path: "{{ item }}" + mode: 0600 + owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" + group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" + when: etcd_peer_url_scheme == 'https' + with_items: + - "{{ etcd_peer_ca_file }}" + - "{{ etcd_peer_cert_file }}" + - "{{ etcd_peer_key_file }}" + +- name: Validate permissions on the config dir + file: + path: "{{ etcd_conf_dir }}" + state: directory + owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" + group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}" + mode: 0700 diff --git a/roles/flannel/meta/main.yml b/roles/flannel/meta/main.yml index 909bdbfa4..616ae61d2 100644 --- a/roles/flannel/meta/main.yml +++ b/roles/flannel/meta/main.yml @@ -4,7 +4,7 @@ galaxy_info: description: flannel management company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.2 + min_ansible_version: 2.1 platforms: - name: EL versions: @@ -13,4 +13,6 @@ galaxy_info: - cloud - system dependencies: -- { role: openshift_facts } +- role: openshift_facts +- role: openshift_etcd_client_certificates + etcd_cert_prefix: flannel.etcd- diff --git a/roles/openshift_ca/meta/main.yml b/roles/openshift_ca/meta/main.yml index a08aa1686..444c5b77e 100644 --- a/roles/openshift_ca/meta/main.yml +++ b/roles/openshift_ca/meta/main.yml @@ -15,3 +15,4 @@ galaxy_info: dependencies: - role: openshift_repos - role: openshift_cli +- role: openshift_named_certificates diff --git a/roles/openshift_ca/tasks/main.yml b/roles/openshift_ca/tasks/main.yml index 4d9768ce7..bb89b65a6 100644 --- a/roles/openshift_ca/tasks/main.yml +++ b/roles/openshift_ca/tasks/main.yml @@ -3,6 +3,10 @@ msg: "openshift_ca_host variable must be defined for this role" when: openshift_ca_host is not defined +- fail: + msg: "Both 'certfile' and 'keyfile' keys must be supplied when configuring openshift_master_ca_certificate" + when: openshift_master_ca_certificate is defined and ('certfile' not in openshift_master_ca_certificate or 'keyfile' not in openshift_master_ca_certificate) + - name: Install the base package for admin tooling action: "{{ ansible_pkg_mgr }} name={{ openshift.common.service_type }}{{ openshift_pkg_version | default('') | oo_image_tag_to_rpm_version(include_dash=True) }} state=present" when: not openshift.common.is_containerized | bool @@ -28,26 +32,82 @@ path: "{{ openshift_ca_config_dir }}/{{ item }}" register: g_master_ca_stat_result with_items: + - ca-bundle.crt - ca.crt - ca.key delegate_to: "{{ openshift_ca_host }}" run_once: true - set_fact: - master_ca_missing: "{{ False in (g_master_ca_stat_result.results - | oo_collect(attribute='stat.exists') - | list) }}" + 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) }}" + run_once: true + +- name: Retain original serviceaccount keys + copy: + src: "{{ item }}" + dest: "{{ item }}.keep" + remote_src: true + with_items: + - "{{ openshift_ca_config_dir }}/serviceaccounts.private.key" + - "{{ openshift_ca_config_dir }}/serviceaccounts.public.key" + when: openshift_certificates_redeploy | default(false) | bool + +- name: Deploy master ca certificate + 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 + - src: "{{ (openshift_master_ca_certificate | default({'keyfile':none})).keyfile }}" + dest: ca.key + when: openshift_master_ca_certificate is defined + delegate_to: "{{ openshift_ca_host }}" + run_once: true + +- name: Create ca serial + copy: + content: "1" + dest: "{{ openshift_ca_config_dir }}/ca.serial.txt" + force: "{{ true if openshift_certificates_redeploy | default(false) | bool else false }}" + when: openshift_master_ca_certificate is defined delegate_to: "{{ openshift_ca_host }}" run_once: true - name: Create the master certificates if they do not already exist command: > {{ openshift.common.admin_binary }} create-master-certs - --hostnames={{ openshift_master_hostnames | join(',') }} - --master={{ openshift.master.api_url }} - --public-master={{ openshift.master.public_api_url }} - --cert-dir={{ openshift_ca_config_dir }} - --overwrite=false - when: hostvars[openshift_ca_host].master_ca_missing | bool + {% for named_ca_certificate in openshift.master.named_certificates | default([]) | oo_collect('cafile') %} + --certificate-authority {{ named_ca_certificate }} + {% endfor %} + --hostnames={{ openshift_master_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 delegate_to: "{{ openshift_ca_host }}" run_once: true + +- name: Restore original serviceaccount keys + copy: + src: "{{ item }}.keep" + dest: "{{ item }}" + remote_src: true + with_items: + - "{{ openshift_ca_config_dir }}/serviceaccounts.private.key" + - "{{ openshift_ca_config_dir }}/serviceaccounts.public.key" + when: openshift_certificates_redeploy | default(false) | bool + +- name: Remove backup serviceaccount keys + file: + path: "{{ item }}.keep" + state: absent + with_items: + - "{{ openshift_ca_config_dir }}/serviceaccounts.private.key" + - "{{ openshift_ca_config_dir }}/serviceaccounts.public.key" + when: openshift_certificates_redeploy | default(false) | bool diff --git a/roles/openshift_etcd_client_certificates/meta/main.yml b/roles/openshift_etcd_client_certificates/meta/main.yml new file mode 100644 index 000000000..3268c390f --- /dev/null +++ b/roles/openshift_etcd_client_certificates/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: + author: Jason DeTiberus + description: OpenShift Etcd Client Certificates + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 2.1 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud +dependencies: +- role: openshift_etcd_facts +- role: etcd_client_certificates diff --git a/roles/openshift_etcd_facts/tasks/main.yml b/roles/openshift_etcd_facts/tasks/main.yml new file mode 100644 index 000000000..22fb39006 --- /dev/null +++ b/roles/openshift_etcd_facts/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- openshift_facts: + role: etcd + local_facts: + etcd_image: "{{ osm_etcd_image | default(None) }}" diff --git a/roles/openshift_etcd_facts/vars/main.yml b/roles/openshift_etcd_facts/vars/main.yml index 6f3894565..cae15d61a 100644 --- a/roles/openshift_etcd_facts/vars/main.yml +++ b/roles/openshift_etcd_facts/vars/main.yml @@ -3,3 +3,8 @@ etcd_is_containerized: "{{ openshift.common.is_containerized }}" etcd_is_atomic: "{{ openshift.common.is_atomic }}" etcd_hostname: "{{ openshift.common.hostname }}" etcd_ip: "{{ openshift.common.ip }}" +etcd_cert_subdir: "etcd-{{ openshift.common.hostname }}" +etcd_cert_prefix: +etcd_cert_config_dir: /etc/etcd +etcd_peer_url_scheme: https +etcd_url_scheme: https diff --git a/roles/openshift_etcd_server_certificates/meta/main.yml b/roles/openshift_etcd_server_certificates/meta/main.yml new file mode 100644 index 000000000..7750f14af --- /dev/null +++ b/roles/openshift_etcd_server_certificates/meta/main.yml @@ -0,0 +1,16 @@ +--- +galaxy_info: + author: Jason DeTiberus + description: OpenShift Etcd Server Certificates + company: Red Hat, Inc. + license: Apache License, Version 2.0 + min_ansible_version: 2.1 + platforms: + - name: EL + versions: + - 7 + categories: + - cloud +dependencies: +- role: openshift_etcd_facts +- role: etcd_server_certificates diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py index 659f4eba6..30cec82ce 100755 --- a/roles/openshift_facts/library/openshift_facts.py +++ b/roles/openshift_facts/library/openshift_facts.py @@ -944,7 +944,12 @@ def format_url(use_ssl, hostname, port, path=''): netloc = hostname if (use_ssl and port != '443') or (not use_ssl and port != '80'): netloc += ":%s" % port - return urlparse.urlunparse((scheme, netloc, path, '', '', '')) + try: + url = urlparse.urlunparse((scheme, netloc, path, '', '', '')) + except AttributeError: + # pylint: disable=undefined-variable + url = urlunparse((scheme, netloc, path, '', '', '')) + return url def get_current_config(facts): """ Get current openshift config @@ -1599,11 +1604,13 @@ class OpenShiftFacts(object): try: # ansible-2.1 - # pylint: disable=too-many-function-args + # pylint: disable=too-many-function-args,invalid-name self.system_facts = ansible_facts(module, ['hardware', 'network', 'virtual', 'facter']) - except TypeError: - # ansible-1.9.x,ansible-2.0.x - self.system_facts = ansible_facts(module) + for (k, v) in self.system_facts.items(): + self.system_facts["ansible_%s" % k.replace('-', '_')] = v + except UnboundLocalError: + # ansible-2.2 + self.system_facts = get_all_facts(module)['ansible_facts'] self.facts = self.generate_facts(local_facts, additive_facts_to_overwrite, @@ -1684,11 +1691,11 @@ class OpenShiftFacts(object): dict: The generated default facts """ defaults = {} - ip_addr = self.system_facts['default_ipv4']['address'] + ip_addr = self.system_facts['ansible_default_ipv4']['address'] exit_code, output, _ = module.run_command(['hostname', '-f']) hostname_f = output.strip() if exit_code == 0 else '' - hostname_values = [hostname_f, self.system_facts['nodename'], - self.system_facts['fqdn']] + hostname_values = [hostname_f, self.system_facts['ansible_nodename'], + self.system_facts['ansible_fqdn']] hostname = choose_hostname(hostname_values, ip_addr) defaults['common'] = dict(use_openshift_sdn=True, ip=ip_addr, @@ -1708,6 +1715,7 @@ class OpenShiftFacts(object): {"name": "PodFitsResources"}, {"name": "PodFitsPorts"}, {"name": "NoDiskConflict"}, + {"name": "NoVolumeZoneConflict"}, {"name": "Region", "argument": {"serviceAffinity" : {"labels" : ["region"]}}} ] scheduler_priorities = [ @@ -1821,10 +1829,10 @@ class OpenShiftFacts(object): dict: The generated default facts for the detected provider """ # TODO: cloud provider facts should probably be submitted upstream - product_name = self.system_facts['product_name'] - product_version = self.system_facts['product_version'] - virt_type = self.system_facts['virtualization_type'] - virt_role = self.system_facts['virtualization_role'] + product_name = self.system_facts['ansible_product_name'] + product_version = self.system_facts['ansible_product_version'] + virt_type = self.system_facts['ansible_virtualization_type'] + virt_role = self.system_facts['ansible_virtualization_role'] provider = None metadata = None @@ -2107,12 +2115,16 @@ def main(): additive_facts_to_overwrite=dict(default=[], type='list', required=False), openshift_env=dict(default={}, type='dict', required=False), openshift_env_structures=dict(default=[], type='list', required=False), - protected_facts_to_overwrite=dict(default=[], type='list', required=False), + protected_facts_to_overwrite=dict(default=[], type='list', required=False) ), supports_check_mode=True, add_file_common_args=True, ) + module.params['gather_subset'] = ['hardware', 'network', 'virtual', 'facter'] + module.params['gather_timeout'] = 10 + module.params['filter'] = '*' + role = module.params['role'] local_facts = module.params['local_facts'] additive_facts_to_overwrite = module.params['additive_facts_to_overwrite'] diff --git a/roles/openshift_hosted/meta/main.yml b/roles/openshift_hosted/meta/main.yml index c7d20f88b..74c50ae1d 100644 --- a/roles/openshift_hosted/meta/main.yml +++ b/roles/openshift_hosted/meta/main.yml @@ -11,27 +11,4 @@ galaxy_info: - 7 categories: - cloud -dependencies: -- role: openshift_cli -- role: openshift_hosted_facts -- role: openshift_projects - # TODO: Move standard project definitions to openshift_hosted/vars/main.yml - # Vars are not accessible in meta/main.yml in ansible-1.9.x - openshift_projects: "{{ openshift_additional_projects | default({}) | oo_merge_dicts({'default':{'default_node_selector':''},'openshift-infra':{'default_node_selector':''},'logging':{'default_node_selector':''}}) }}" -- role: openshift_serviceaccounts - openshift_serviceaccounts_names: - - router - openshift_serviceaccounts_namespace: default - openshift_serviceaccounts_sccs: - - hostnetwork - when: openshift.common.version_gte_3_2_or_1_2 -- role: openshift_serviceaccounts - openshift_serviceaccounts_names: - - router - - registry - openshift_serviceaccounts_namespace: default - openshift_serviceaccounts_sccs: - - privileged - when: not openshift.common.version_gte_3_2_or_1_2 -- role: openshift_metrics - when: openshift.hosted.metrics.deploy | bool +dependencies: [] diff --git a/roles/openshift_hosted/tasks/main.yml b/roles/openshift_hosted/tasks/main.yml index c801a0e67..67c6bbfd7 100644 --- a/roles/openshift_hosted/tasks/main.yml +++ b/roles/openshift_hosted/tasks/main.yml @@ -13,7 +13,10 @@ changed_when: False - include: router/router.yml + when: openshift_hosted_manage_router | default(true) | bool + - include: registry/registry.yml + when: openshift_hosted_manage_registry | default(true) | bool - name: Delete temp directory file: diff --git a/roles/openshift_hosted/tasks/registry/registry.yml b/roles/openshift_hosted/tasks/registry/registry.yml index 08c7e944e..b28974236 100644 --- a/roles/openshift_hosted/tasks/registry/registry.yml +++ b/roles/openshift_hosted/tasks/registry/registry.yml @@ -4,12 +4,12 @@ {{ openshift.common.client_binary }} --api-version='v1' -o json get nodes -n default --config={{ openshift_hosted_kubeconfig }} --selector={{ openshift.hosted.registry.selector | default('') }} - register: openshift_hosted_registry_nodes_json + register: registry_nodes_json changed_when: false when: openshift.hosted.registry.replicas | default(none) is none - set_fact: - l_node_count: "{{ (openshift_hosted_registry_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length }}" + l_node_count: "{{ (registry_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length }}" # Determine the default number of registry/router replicas to use if no count # has been specified. @@ -50,7 +50,9 @@ when: replicas | int > 0 - include: storage/object_storage.yml + static: no when: replicas | int > 0 and openshift.hosted.registry.storage.kind | default(none) == 'object' - include: storage/persistent_volume.yml + static: no when: replicas | int > 0 and openshift.hosted.registry.storage.kind | default(none) in ['nfs', 'openstack'] diff --git a/roles/openshift_hosted/tasks/router/router.yml b/roles/openshift_hosted/tasks/router/router.yml index d0a129c95..e18b9781c 100644 --- a/roles/openshift_hosted/tasks/router/router.yml +++ b/roles/openshift_hosted/tasks/router/router.yml @@ -39,12 +39,12 @@ {{ openshift.common.client_binary }} --api-version='v1' -o json get nodes -n default --config={{ openshift_hosted_kubeconfig }} --selector={{ openshift.hosted.router.selector | default('') }} - register: openshift_hosted_router_nodes_json + register: router_nodes_json changed_when: false when: openshift.hosted.router.replicas | default(none) is none - set_fact: - replicas: "{{ openshift.hosted.router.replicas | default((openshift_hosted_router_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) }}" + replicas: "{{ openshift.hosted.router.replicas | default((router_nodes_json.stdout | default('{\"items\":[]}') | from_json)['items'] | length) }}" - name: Create OpenShift router command: > diff --git a/roles/openshift_hosted/templates/registry_config.j2 b/roles/openshift_hosted/templates/registry_config.j2 index ea5626642..71539775d 100644 --- a/roles/openshift_hosted/templates/registry_config.j2 +++ b/roles/openshift_hosted/templates/registry_config.j2 @@ -58,6 +58,10 @@ auth: openshift: realm: openshift middleware: +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} + registry: + - name: openshift +{% endif -%} repository: - name: openshift options: @@ -69,4 +73,7 @@ middleware: baseurl: {{ openshift.hosted.registry.storage.s3.cloudfront.baseurl }} privatekey: {{ openshift.hosted.registry.storage.s3.cloudfront.privatekeyfile }} keypairid: {{ openshift.hosted.registry.storage.s3.cloudfront.keypairid }} +{% elif openshift.common.version_gte_3_3_or_1_3 | bool %} + storage: + - name: openshift {% endif -%} diff --git a/roles/openshift_master/handlers/main.yml b/roles/openshift_master/handlers/main.yml index f7dfb11f7..edb7369de 100644 --- a/roles/openshift_master/handlers/main.yml +++ b/roles/openshift_master/handlers/main.yml @@ -17,7 +17,12 @@ # Using curl here since the uri module requires python-httplib2 and # wait_for port doesn't provide health information. command: > - curl --silent --cacert {{ openshift.common.config_base }}/master/ca.crt + curl --silent + {% if openshift.common.version_gte_3_2_or_1_2 | bool %} + --cacert {{ openshift.common.config_base }}/master/ca-bundle.crt + {% else %} + --cacert {{ openshift.common.config_base }}/master/ca.crt + {% endif %} {{ openshift.master.api_url }}/healthz/ready register: api_available_output until: api_available_output.stdout == 'ok' diff --git a/roles/openshift_master/meta/main.yml b/roles/openshift_master/meta/main.yml index be70d9102..a2f665702 100644 --- a/roles/openshift_master/meta/main.yml +++ b/roles/openshift_master/meta/main.yml @@ -11,32 +11,4 @@ galaxy_info: - 7 categories: - cloud -dependencies: -- role: openshift_clock -- role: openshift_master_certificates -- role: openshift_cloud_provider -- role: openshift_builddefaults -- role: openshift_master_facts -- role: openshift_hosted_facts -- role: os_firewall - os_firewall_allow: - - service: etcd embedded - port: 4001/tcp - - service: api server https - port: "{{ openshift.master.api_port }}/tcp" - - service: api controllers https - port: "{{ openshift.master.controllers_port }}/tcp" - - service: skydns tcp - port: "{{ openshift.master.dns_port }}/tcp" - - service: skydns udp - port: "{{ openshift.master.dns_port }}/udp" - - service: Fluentd td-agent tcp - port: 24224/tcp - - service: Fluentd td-agent udp - port: 24224/udp - - service: pcsd - port: 2224/tcp - - service: Corosync UDP - port: 5404/udp - - service: Corosync UDP - port: 5405/udp +dependencies: [] diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml index 115a64aeb..6259fd996 100644 --- a/roles/openshift_master/tasks/main.yml +++ b/roles/openshift_master/tasks/main.yml @@ -224,7 +224,12 @@ # Using curl here since the uri module requires python-httplib2 and # wait_for port doesn't provide health information. command: > - curl --silent --cacert {{ openshift.common.config_base }}/master/ca.crt + curl --silent + {% if openshift.common.version_gte_3_2_or_1_2 | bool %} + --cacert {{ openshift.common.config_base }}/master/ca-bundle.crt + {% else %} + --cacert {{ openshift.common.config_base }}/master/ca.crt + {% endif %} {{ openshift.master.api_url }}/healthz/ready register: api_available_output until: api_available_output.stdout == 'ok' @@ -272,37 +277,3 @@ - name: Set the cluster user password shell: echo {{ openshift_master_cluster_password | quote }} | passwd --stdin hacluster when: install_result | changed - -- 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 }}" - -# TODO: Update this file if the contents of the source file are not present in -# the dest file, will need to make sure to ignore things that could be added -- name: Copy the admin client config(s) - command: cp {{ openshift_master_config_dir }}/admin.kubeconfig ~{{ item }}/.kube/config - args: - creates: ~{{ item }}/.kube/config - 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 }}" diff --git a/roles/openshift_master/tasks/systemd_units.yml b/roles/openshift_master/tasks/systemd_units.yml index 458b56fd1..0c0c7e61e 100644 --- a/roles/openshift_master/tasks/systemd_units.yml +++ b/roles/openshift_master/tasks/systemd_units.yml @@ -16,7 +16,7 @@ # workaround for missing systemd unit files - name: Create the systemd unit files template: - src: "docker/master.docker.service.j2" + src: "master_docker/master.docker.service.j2" dest: "{{ containerized_svc_dir }}/{{ openshift.common.service_type }}-master.service" when: openshift.common.is_containerized | bool and (openshift.master.ha is not defined or not openshift.master.ha | bool) register: create_master_unit_file @@ -84,12 +84,12 @@ line: "{{ item }}" with_items: "{{ master_controllers_proxy.stdout_lines | default([]) }}" when: openshift.master.ha is defined and openshift.master.ha | bool and openshift_master_cluster_method == "native" - and master_controllers_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common + and master_controllers_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common - name: Install Master docker service file template: dest: "/etc/systemd/system/{{ openshift.common.service_type }}-master.service" - src: docker/master.docker.service.j2 + src: master_docker/master.docker.service.j2 register: install_result when: openshift.common.is_containerized | bool and openshift.master.ha is defined and not openshift.master.ha | bool @@ -112,4 +112,4 @@ dest: /etc/sysconfig/{{ openshift.common.service_type }}-master line: "{{ item }}" with_items: "{{ master_proxy.stdout_lines | default([]) }}" - when: master_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common
\ No newline at end of file + when: master_proxy.rc == 0 and 'http_proxy' not in openshift.common and 'https_proxy' not in openshift.common diff --git a/roles/openshift_master/templates/master.yaml.v1.j2 b/roles/openshift_master/templates/master.yaml.v1.j2 index b18a42e32..31e86f5bd 100644 --- a/roles/openshift_master/templates/master.yaml.v1.j2 +++ b/roles/openshift_master/templates/master.yaml.v1.j2 @@ -131,7 +131,21 @@ kubernetesMasterConfig: {% endif %} masterClients: {# TODO: allow user to set externalKubernetesKubeConfig #} +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} + externalKubernetesClientConnectionOverrides: + acceptContentTypes: application/vnd.kubernetes.protobuf,application/json + contentType: application/vnd.kubernetes.protobuf + burst: 400 + qps: 200 +{% endif %} externalKubernetesKubeConfig: "" +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} + openshiftLoopbackClientConnectionOverrides: + acceptContentTypes: application/vnd.kubernetes.protobuf,application/json + contentType: application/vnd.kubernetes.protobuf + burst: 600 + qps: 300 +{% endif %} openshiftLoopbackKubeConfig: openshift-master.kubeconfig masterPublicURL: {{ openshift.master.public_api_url }} networkConfig: @@ -156,7 +170,11 @@ oauthConfig: {% for line in translated_identity_providers.splitlines() %} {{ line }} {% endfor %} - masterCA: ca.crt +{% if openshift.common.version_gte_3_2_or_1_2 | bool %} + masterCA: ca-bundle.crt +{% else %} + masterCA: ca.rt +{% endif %} masterPublicURL: {{ openshift.master.public_api_url }} masterURL: {{ openshift.master.api_url }} sessionConfig: @@ -189,7 +207,11 @@ serviceAccountConfig: - default - builder - deployer - masterCA: ca.crt +{% if openshift.common.version_gte_3_2_or_1_2 | bool %} + masterCA: ca-bundle.crt +{% else %} + masterCA: ca.rt +{% endif %} privateKeyFile: serviceaccounts.private.key publicKeyFiles: - serviceaccounts.public.key @@ -201,7 +223,7 @@ servingInfo: keyFile: master.server.key maxRequestsInFlight: {{ openshift.master.max_requests_inflight }} requestTimeoutSeconds: 3600 -{% if openshift.master.named_certificates %} +{% if openshift.master.named_certificates | default([]) | length > 0 %} namedCertificates: {% for named_certificate in openshift.master.named_certificates %} - certFile: {{ named_certificate['certfile'] }} diff --git a/roles/openshift_master/templates/docker/master.docker.service.j2 b/roles/openshift_master/templates/master_docker/master.docker.service.j2 index 97f698b68..97f698b68 100644 --- a/roles/openshift_master/templates/docker/master.docker.service.j2 +++ b/roles/openshift_master/templates/master_docker/master.docker.service.j2 diff --git a/roles/openshift_master_certificates/meta/main.yml b/roles/openshift_master_certificates/meta/main.yml index dd19c8ded..018186e86 100644 --- a/roles/openshift_master_certificates/meta/main.yml +++ b/roles/openshift_master_certificates/meta/main.yml @@ -13,4 +13,5 @@ galaxy_info: - cloud - system dependencies: +- role: openshift_master_facts - role: openshift_ca diff --git a/roles/openshift_master_certificates/tasks/main.yml b/roles/openshift_master_certificates/tasks/main.yml index 6fb5830cf..aafb06f93 100644 --- a/roles/openshift_master_certificates/tasks/main.yml +++ b/roles/openshift_master_certificates/tasks/main.yml @@ -21,18 +21,22 @@ with_items: - "{{ openshift_master_certs }}" register: g_master_cert_stat_result + when: not openshift_certificates_redeploy | default(false) | bool - set_fact: - master_certs_missing: "{{ False in (g_master_cert_stat_result.results - | oo_collect(attribute='stat.exists') - | list) }}" + master_certs_missing: "{{ true if openshift_certificates_redeploy | default(false) | bool + else (False in (g_master_cert_stat_result.results + | default({}) + | oo_collect(attribute='stat.exists') + | list)) }}" + - name: Ensure the generated_configs directory present file: path: "{{ openshift_master_generated_config_dir }}" state: directory mode: 0700 - when: master_certs_missing | bool + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host delegate_to: "{{ openshift_ca_host }}" - file: @@ -43,18 +47,21 @@ - ca.crt - ca.key - ca.serial.txt - when: master_certs_missing | bool + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host delegate_to: "{{ openshift_ca_host }}" - name: Create the master certificates if they do not already exist command: > {{ openshift.common.admin_binary }} create-master-certs - --hostnames={{ openshift.common.all_hostnames | join(',') }} - --master={{ openshift.master.api_url }} - --public-master={{ openshift.master.public_api_url }} - --cert-dir={{ openshift_master_generated_config_dir }} - --overwrite=false - when: master_certs_missing | bool + {% for named_ca_certificate in openshift.master.named_certificates | default([]) | oo_collect('cafile') %} + --certificate-authority {{ named_ca_certificate }} + {% endfor %} + --hostnames={{ openshift.common.all_hostnames | join(',') }} + --master={{ openshift.master.api_url }} + --public-master={{ openshift.master.public_api_url }} + --cert-dir={{ openshift_master_generated_config_dir }} + --overwrite=false + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host delegate_to: "{{ openshift_ca_host }}" - file: @@ -64,7 +71,7 @@ force: true with_items: - "{{ hostvars[inventory_hostname] | certificates_to_synchronize }}" - when: master_certs_missing | bool + when: master_certs_missing | bool and inventory_hostname != openshift_ca_host delegate_to: "{{ openshift_ca_host }}" - name: Remove generated etcd client certs when using external etcd @@ -121,3 +128,39 @@ when: master_certs_missing | bool delegate_to: localhost become: no + +- 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 }}" + +# TODO: Update this file if the contents of the source file are not present in +# the dest file, will need to make sure to ignore things that could be added +- name: Copy the admin client config(s) + copy: + src: "{{ openshift_master_config_dir }}/admin.kubeconfig" + dest: "~{{ item }}/.kube/config" + remote_src: yes + force: "{{ openshift_certificates_redeploy | default(false) }}" + 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 }}" diff --git a/roles/openshift_named_certificates/README.md b/roles/openshift_named_certificates/README.md new file mode 100644 index 000000000..41f895813 --- /dev/null +++ b/roles/openshift_named_certificates/README.md @@ -0,0 +1,32 @@ +OpenShift Named Certificates +============================ + +TODO + +Requirements +------------ + +Role Variables +-------------- + +TODO + +Dependencies +------------ + +TODO + +Example Playbook +---------------- + +TODO + +License +------- + +Apache License Version 2.0 + +Author Information +------------------ + +Andrew Butcher <abutcher@redhat.com> diff --git a/roles/openshift_etcd_certificates/meta/main.yml b/roles/openshift_named_certificates/meta/main.yml index 2725fdb51..2c6e12494 100644 --- a/roles/openshift_etcd_certificates/meta/main.yml +++ b/roles/openshift_named_certificates/meta/main.yml @@ -1,16 +1,16 @@ --- galaxy_info: author: Andrew Butcher - description: OpenShift etcd Certificates + description: OpenShift Named Certificates company: Red Hat, Inc. license: Apache License, Version 2.0 - min_ansible_version: 1.9 + min_ansible_version: 2.1 platforms: - name: EL versions: - 7 categories: - cloud + - system dependencies: -- role: openshift_etcd_facts -- role: etcd_certificates +- role: openshift_facts diff --git a/roles/openshift_named_certificates/tasks/main.yml b/roles/openshift_named_certificates/tasks/main.yml new file mode 100644 index 000000000..7f20cf401 --- /dev/null +++ b/roles/openshift_named_certificates/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- set_fact: + parsed_named_certificates: "{{ named_certificates | oo_parse_named_certificates(named_certs_dir, internal_hostnames) }}" + when: named_certificates | length > 0 + delegate_to: localhost + become: no + run_once: true + +- openshift_facts: + role: master + local_facts: + named_certificates: "{{ parsed_named_certificates | default([]) }}" + additive_facts_to_overwrite: + - "{{ 'master.named_certificates' if overwrite_named_certs | bool else omit }}" + +- name: Clear named certificates + file: + path: "{{ named_certs_dir }}" + state: absent + when: overwrite_named_certs | bool + +- name: Ensure named certificate directory exists + file: + path: "{{ named_certs_dir }}" + state: directory + mode: 0700 + +- name: Land named certificates + copy: + src: "{{ item.certfile }}" + dest: "{{ named_certs_dir }}" + with_items: "{{ named_certificates }}" + +- name: Land named certificate keys + copy: + src: "{{ item.keyfile }}" + dest: "{{ named_certs_dir }}" + mode: 0600 + with_items: "{{ named_certificates }}" + +- name: Land named CA certificates + copy: + src: "{{ item }}" + dest: "{{ named_certs_dir }}" + mode: 0600 + with_items: "{{ named_certificates | oo_collect('cafile') }}" diff --git a/roles/openshift_named_certificates/tasks/named_certificates.yml b/roles/openshift_named_certificates/tasks/named_certificates.yml new file mode 100644 index 000000000..7b097b443 --- /dev/null +++ b/roles/openshift_named_certificates/tasks/named_certificates.yml @@ -0,0 +1,32 @@ +--- +- name: Clear named certificates + file: + path: "{{ named_certs_dir }}" + state: absent + when: overwrite_named_certs | bool + +- name: Ensure named certificate directory exists + file: + path: "{{ named_certs_dir }}" + state: directory + mode: 0700 + +- name: Land named certificates + copy: + src: "{{ item.certfile }}" + dest: "{{ named_certs_dir }}" + with_items: "{{ openshift_master_named_certificates | default([]) }}" + +- name: Land named certificate keys + copy: + src: "{{ item.keyfile }}" + dest: "{{ named_certs_dir }}" + mode: 0600 + with_items: "{{ openshift_master_named_certificates | default([]) }}" + +- name: Land named CA certificates + copy: + src: "{{ item }}" + dest: "{{ named_certs_dir }}" + mode: 0600 + with_items: "{{ openshift_master_named_certificates | default([]) | oo_collect('cafile') }}" diff --git a/roles/openshift_named_certificates/vars/main.yml b/roles/openshift_named_certificates/vars/main.yml new file mode 100644 index 000000000..368e9bdac --- /dev/null +++ b/roles/openshift_named_certificates/vars/main.yml @@ -0,0 +1,11 @@ +--- +openshift_ca_config_dir: "{{ openshift.common.config_base }}/master" +openshift_ca_cert: "{{ openshift_ca_config_dir }}/ca.crt" +openshift_ca_key: "{{ openshift_ca_config_dir }}/ca.key" +openshift_ca_serial: "{{ openshift_ca_config_dir }}/ca.serial.txt" +openshift_version: "{{ openshift_pkg_version | default('') }}" + +overwrite_named_certs: "{{ openshift_master_overwrite_named_certificates | default(false) }}" +named_certs_dir: "{{ openshift.common.config_base }}/master/named_certificates/" +internal_hostnames: "{{ openshift.common.internal_hostnames }}" +named_certificates: "{{ openshift_master_named_certificates | default([]) }}" diff --git a/roles/openshift_node/meta/main.yml b/roles/openshift_node/meta/main.yml index fd493340b..c39269f33 100644 --- a/roles/openshift_node/meta/main.yml +++ b/roles/openshift_node/meta/main.yml @@ -11,26 +11,4 @@ galaxy_info: - 7 categories: - cloud -dependencies: -- role: openshift_clock -- role: openshift_docker -- role: openshift_node_certificates -- role: openshift_cloud_provider -- role: openshift_common -- role: openshift_node_dnsmasq - when: openshift.common.use_dnsmasq -- role: os_firewall - os_firewall_allow: - - service: Kubernetes kubelet - port: 10250/tcp - - service: http - port: 80/tcp - - service: https - port: 443/tcp - - service: Openshift kubelet ReadOnlyPort - port: 10255/tcp - - service: Openshift kubelet ReadOnlyPort udp - port: 10255/udp - - service: OpenShift OVS sdn - port: 4789/udp - when: openshift.node.use_openshift_sdn | bool +dependencies: [] diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml index 889541e25..9c71af6d9 100644 --- a/roles/openshift_node/tasks/main.yml +++ b/roles/openshift_node/tasks/main.yml @@ -106,8 +106,20 @@ notify: - restart node -- name: Additional storage plugin configuration - include: storage_plugins/main.yml +- name: NFS storage plugin configuration + include: storage_plugins/nfs.yml + +- name: GlusterFS storage plugin configuration + include: storage_plugins/glusterfs.yml + when: "'glusterfs' in openshift.node.storage_plugin_deps" + +- name: Ceph storage plugin configuration + include: storage_plugins/ceph.yml + when: "'ceph' in openshift.node.storage_plugin_deps" + +- name: iSCSI storage plugin configuration + include: storage_plugins/iscsi.yml + when: "'iscsi' in openshift.node.storage_plugin_deps" # Necessary because when you're on a node that's also a master the master will be # restarted after the node restarts docker and it will take up to 60 seconds for diff --git a/roles/openshift_node/tasks/storage_plugins/main.yml b/roles/openshift_node/tasks/storage_plugins/main.yml deleted file mode 100644 index fe638718d..000000000 --- a/roles/openshift_node/tasks/storage_plugins/main.yml +++ /dev/null @@ -1,17 +0,0 @@ ---- -# The NFS storage plugin is always enabled since it doesn't require any -# additional package dependencies -- name: NFS storage plugin configuration - include: nfs.yml - -- name: GlusterFS storage plugin configuration - include: glusterfs.yml - when: "'glusterfs' in openshift.node.storage_plugin_deps" - -- name: Ceph storage plugin configuration - include: ceph.yml - when: "'ceph' in openshift.node.storage_plugin_deps" - -- name: iSCSI storage plugin configuration - include: iscsi.yml - when: "'iscsi' in openshift.node.storage_plugin_deps" diff --git a/roles/openshift_node/templates/node.yaml.v1.j2 b/roles/openshift_node/templates/node.yaml.v1.j2 index a37770c4a..414f0d5e3 100644 --- a/roles/openshift_node/templates/node.yaml.v1.j2 +++ b/roles/openshift_node/templates/node.yaml.v1.j2 @@ -12,15 +12,22 @@ imageConfig: latest: false kind: NodeConfig kubeletArguments: {{ openshift.node.kubelet_args | default(None) | to_padded_yaml(level=1) }} +{% if openshift.common.version_gte_3_3_or_1_3 | bool %} +masterClientConnectionOverrides: + acceptContentTypes: application/vnd.kubernetes.protobuf,application/json + contentType: application/vnd.kubernetes.protobuf + burst: 200 + qps: 100 +{% endif %} masterKubeConfig: system:node:{{ openshift.common.hostname }}.kubeconfig -{% if openshift.common.use_openshift_sdn %} +{% if openshift.common.use_openshift_sdn | bool and not openshift.common.version_gte_3_3_or_1_3 | bool %} networkPluginName: {{ openshift.common.sdn_network_plugin_name }} {% endif %} # networkConfig struct introduced in origin 1.0.6 and OSE 3.0.2 which # deprecates networkPluginName above. The two should match. networkConfig: mtu: {{ openshift.node.sdn_mtu }} -{% if openshift.common.use_openshift_sdn or openshift.common.use_nuage %} +{% if ( openshift.common.use_openshift_sdn | bool or openshift.common.use_nuage | bool ) and not openshift.common.version_gte_3_3_or_1_3 | bool%} networkPluginName: {{ openshift.common.sdn_network_plugin_name }} {% endif %} {% if openshift.node.set_node_ip | bool %} diff --git a/roles/openshift_node_certificates/tasks/main.yml b/roles/openshift_node_certificates/tasks/main.yml index 0e69dc6f0..fef7caab8 100644 --- a/roles/openshift_node_certificates/tasks/main.yml +++ b/roles/openshift_node_certificates/tasks/main.yml @@ -25,11 +25,14 @@ - server.key - server.crt register: g_node_cert_stat_result + when: not openshift_certificates_redeploy | default(false) | bool - set_fact: - node_certs_missing: "{{ False in (g_node_cert_stat_result.results - | oo_collect(attribute='stat.exists') - | list) }}" + node_certs_missing: "{{ true if openshift_certificates_redeploy | default(false) | bool + else (False in (g_node_cert_stat_result.results + | default({}) + | oo_collect(attribute='stat.exists') + | list)) }}" - name: Create openshift_generated_configs_dir if it does not exist file: @@ -42,6 +45,9 @@ - name: Generate the node client config command: > {{ openshift.common.admin_binary }} 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_node_generated_config_dir }} --groups=system:nodes diff --git a/roles/openshift_repos/files/fedora-openshift-enterprise/gpg_keys/.gitkeep b/roles/openshift_repos/files/fedora-openshift-enterprise/gpg_keys/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/fedora-openshift-enterprise/gpg_keys/.gitkeep diff --git a/roles/openshift_repos/files/fedora-openshift-enterprise/repos/.gitkeep b/roles/openshift_repos/files/fedora-openshift-enterprise/repos/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/fedora-openshift-enterprise/repos/.gitkeep diff --git a/roles/openshift_repos/files/openshift-enterprise/gpg_keys/.gitkeep b/roles/openshift_repos/files/openshift-enterprise/gpg_keys/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/openshift-enterprise/gpg_keys/.gitkeep diff --git a/roles/openshift_repos/files/openshift-enterprise/repos/.gitkeep b/roles/openshift_repos/files/openshift-enterprise/repos/.gitkeep new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/roles/openshift_repos/files/openshift-enterprise/repos/.gitkeep diff --git a/roles/openshift_repos/tasks/main.yaml b/roles/openshift_repos/tasks/main.yaml index d8e43438a..07a8d28fd 100644 --- a/roles/openshift_repos/tasks/main.yaml +++ b/roles/openshift_repos/tasks/main.yaml @@ -34,7 +34,12 @@ path: "/etc/yum.repos.d/{{ item | basename }}" state: absent with_fileglob: - - '*/repos/*' + - "fedora-openshift-enterprise/repos/*" + - "fedora-origin/repos/*" + - "online/repos/*" + - "openshift-enterprise/repos/*" + - "origin/repos/*" + - "removed/repos/*" when: not openshift.common.is_containerized | bool and not (item | search("/files/" ~ openshift_deployment_type ~ "/repos")) and (ansible_os_family == "RedHat" and ansible_distribution != "Fedora") @@ -42,10 +47,15 @@ - name: Remove any yum repo files for other deployment types Fedora file: - path: "/etc/yum.repos.d/{{ item | basename }}" + path: "{{ item | basename }}" state: absent with_fileglob: - - '*/repos/*' + - "fedora-openshift-enterprise/repos/*" + - "fedora-origin/repos/*" + - "online/repos/*" + - "openshift-enterprise/repos/*" + - "origin/repos/*" + - "removed/repos/*" when: not openshift.common.is_containerized | bool and not (item | search("/files/fedora-" ~ openshift_deployment_type ~ "/repos")) and (ansible_distribution == "Fedora") |