diff --git a/qe_server.yml b/qe_server.yml index f0da1960..80d9aecd 100644 --- a/qe_server.yml +++ b/qe_server.yml @@ -10,6 +10,7 @@ - { role: epel, epel_enabled: 1 } - rh-python36 - tendrl-ansible.gluster-gdeploy-copr + - qe-ssl-ca - qe-server - name: Prepare test environment of usmqe user diff --git a/qe_server_jenkins.yml b/qe_server_jenkins.yml index 67f19e11..e1bdc78a 100644 --- a/qe_server_jenkins.yml +++ b/qe_server_jenkins.yml @@ -10,6 +10,7 @@ - epel - rh-python36 - tendrl-ansible.gluster-gdeploy-copr + - qe-ssl-ca - qe-server tasks: - name: Add jenkins user into usmqe group diff --git a/qe_ssl_certs.yml b/qe_ssl_certs.yml deleted file mode 100644 index 8dc416db..00000000 --- a/qe_ssl_certs.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -# -# obtain ssl certs on all servers -# - -- hosts: usm_server:usm_nodes:usm_client - remote_user: root - roles: - - {role: qe-ssl-cert, ssl_cert_name: "server"} diff --git a/roles/qe-server/meta/main.yml b/roles/qe-server/meta/main.yml index aa45c549..2f663f48 100644 --- a/roles/qe-server/meta/main.yml +++ b/roles/qe-server/meta/main.yml @@ -2,3 +2,4 @@ dependencies: - { role: epel, epel_enabled: 1, qe_not_production_testing_server: True} - { role: rh-python36 } + - { role: qe-ssl-ca } diff --git a/roles/qe-ssl-ca/README.rst b/roles/qe-ssl-ca/README.rst new file mode 100644 index 00000000..b5af9112 --- /dev/null +++ b/roles/qe-ssl-ca/README.rst @@ -0,0 +1,12 @@ +================= + QE SSL CA Setup +================= + +This role downloads OpenSSL Certificate Authority file of QE team and imports +it into system so that it's trusted on the machine by default. + +The role is expected to be used on qe-server and client machine only. + +Mandatory ansible variables: + +* ``ca_usmqe_cert_url`` is url of QE CA cert file diff --git a/roles/qe-ssl-ca/defaults/main.yml b/roles/qe-ssl-ca/defaults/main.yml new file mode 100644 index 00000000..91b231d4 --- /dev/null +++ b/roles/qe-ssl-ca/defaults/main.yml @@ -0,0 +1,2 @@ +--- +ssl_cert_perm: "0644" diff --git a/roles/qe-ssl-ca/tasks/main.yml b/roles/qe-ssl-ca/tasks/main.yml new file mode 100644 index 00000000..f3e5effd --- /dev/null +++ b/roles/qe-ssl-ca/tasks/main.yml @@ -0,0 +1,30 @@ +--- + +- name: Make sure openssl is installed + yum: + name: openssl + state: present + +- name: Make sure anchors directory exists + file: + path: /etc/pki/ca-trust/source/anchors + state: directory + +- name: Check that mandatory variables are defined + assert: + that: + - ca_usmqe_cert_url is defined + msg: > + You need to define all mandatory ansible variables to run this + playbook, see README file for guidance. + +- name: Get QE CA cert file + get_url: + url: "{{ ca_usmqe_cert_url }}" + dest: "/etc/pki/ca-trust/source/anchors/ca-usmqe.crt" + mode: "{{ ssl_cert_perm }}" + register: ca_trust + +- name: Run update-ca-trust extract + command: update-ca-trust extract + when: ca_trust.changed diff --git a/roles/tendrl-httpd-ssl/README.rst b/roles/tendrl-httpd-ssl/README.rst new file mode 100644 index 00000000..cf69625a --- /dev/null +++ b/roles/tendrl-httpd-ssl/README.rst @@ -0,0 +1,31 @@ +=============================================== + Setup of HTTPS for Tendrl UI, API and Grafana +=============================================== + +This role configures apache to use ssl for Tendrl Web, API and Grafana. + +Based on upstream wiki: `Enabling Https on tendrl server +`_ + +See also overview of tendrl ssl related upstream work: `SSL Configuration for +Tendrl +`_ + +Some code was reused from: +https://github.com/Tendrl/tendrl-ansible/pull/46/files + +Variables +========= + +* ``httpd_ip_address``: public ip address of WA server, where the web is hosted + (default value provided in the role is valid for standard usmqe environment) +* ``httpd_server_name``: ``ServerName`` of the Tendrl Web + (default value provided in the role is valid for standard usmqe environment) +* ``httpd_ssl_certificate_key_file``: ``SLCertificateFile`` of the Tendrl Web, + if not specified, default self signed one is used +* ``httpd_ssl_certificate_file``: ``SSLCertificateKeyFile`` of the Tendrl Web, + if not specified, default self signed one is used +* ``tendrl_https_redirection``: should we redirect http request to https? + (default True) +* ``tendrl_https_disable_port_80``: should we disable http port for better + testing? (default False) diff --git a/roles/tendrl-httpd-ssl/defaults/main.yml b/roles/tendrl-httpd-ssl/defaults/main.yml new file mode 100644 index 00000000..b0ba2f70 --- /dev/null +++ b/roles/tendrl-httpd-ssl/defaults/main.yml @@ -0,0 +1,5 @@ +--- +httpd_server_name: "{{ inventory_hostname }}" +httpd_ip_address: "{{ ansible_default_ipv4.address }}" +tendrl_https_redirection: True +tendrl_https_disable_port_80: False diff --git a/roles/tendrl-httpd-ssl/handlers/main.yml b/roles/tendrl-httpd-ssl/handlers/main.yml new file mode 100644 index 00000000..f037ebdc --- /dev/null +++ b/roles/tendrl-httpd-ssl/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: restart httpd + service: + name=httpd + state=reloaded diff --git a/roles/tendrl-httpd-ssl/tasks/main.yml b/roles/tendrl-httpd-ssl/tasks/main.yml new file mode 100644 index 00000000..85110d98 --- /dev/null +++ b/roles/tendrl-httpd-ssl/tasks/main.yml @@ -0,0 +1,131 @@ +--- + +- debug: + var: httpd_server_name + +- debug: + var: httpd_ip_address + +- name: Install mod_ssl package + yum: + name: mod_ssl + state: latest + +- name: Initialize new tendrl-ssl.conf file based on sample conf file + copy: + src: /etc/httpd/conf.d/tendrl-ssl.conf.sample + remote_src: True + dest: /etc/httpd/conf.d/tendrl-ssl.conf + +- name: Replace ssl_virtualhost_ip with the correct ip address + lineinfile: + path: /etc/httpd/conf.d/tendrl-ssl.conf + regexp: '^' + line: "" + notify: + - restart httpd + +- name: Adjust ServerName + lineinfile: + path: /etc/httpd/conf.d/tendrl-ssl.conf + insertafter: '' + regexp: '^ *ServerName .*' + line: " ServerName {{ httpd_server_name }}" + state: present + notify: + - restart httpd + +# +# Specify different cert files if needed +# + +- name: Configure SSL certificate files + lineinfile: + path: /etc/httpd/conf.d/ssl.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + with_items: + - regexp: '^ *SSLCertificateFile .*' + line: ' SSLCertificateFile {{ httpd_ssl_certificate_file }}' + - regexp: '^ *SSLCertificateKeyFile .*' + line: ' SSLCertificateKeyFile {{ httpd_ssl_certificate_key_file }}' + when: httpd_ssl_certificate_key_file is defined and httpd_ssl_certificate_file is defined + notify: + - restart httpd + +# +# Automatic redirect of all http urls to https +# + +- name: Backup tendrl.conf (for easy teardown) + copy: + src: /etc/httpd/conf.d/tendrl.conf + dest: /etc/httpd/conf.d/tendrl.conf.usmqe_backup + remote_src: yes + backup: yes + force: no + +- name: Configure SSL redirect in tendrl.conf + lineinfile: + path: /etc/httpd/conf.d/tendrl.conf + regexp: ' *#? *Redirect permanent / https://.*/' + line: " Redirect permanent / https://{{ httpd_server_name }}/" + when: tendrl_https_redirection == True + notify: + - restart httpd + +- name: Comment out DocumentRoot, ProxyPass and ProxyPassReverse in tendrl.conf + lineinfile: + path: /etc/httpd/conf.d/tendrl.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + with_items: + - regexp: ' *#?DocumentRoot /var/www/tendrl' + line: ' #DocumentRoot /var/www/tendrl' + - regexp: ' *#?ProxyPass "/api" http://127.0.0.1:9292/' + line: ' #ProxyPass "/api" http://127.0.0.1:9292/' + - regexp: ' *#?ProxyPassReverse "/api" http://127.0.0.1:9292/' + line: ' #ProxyPassReverse "/api" http://127.0.0.1:9292/' + - regexp: ' *#?ProxyPass /grafana http://127.0.0.1:3000' + line: ' #ProxyPass /grafana http://127.0.0.1:3000' + - regexp: ' *#?ProxyPassReverse /grafana http://127.0.0.1:3000/grafana' + line: ' #ProxyPassReverse /grafana http://127.0.0.1:3000/grafana' + when: tendrl_https_redirection == True + notify: + - restart httpd + +# +# Config validation +# + +- name: Run apachectl configtest to validate new configuration + command: apachectl -t + changed_when: False + register: apachectl_configtest + +- name: Recheck result of config validation (based on previous task) + assert: + that: + - apachectl_configtest.stderr == 'Syntax OK' + - apachectl_configtest.stdout == '' + +# +# Firewall +# + +- name: Open port for https in firewalld + firewalld: + service=https + zone=public permanent=true state=enabled immediate=true + +- name: Disable http service in firewalld (for proper testing) + firewalld: + service=http + zone=public permanent=true state=disabled immediate=true + when: tendrl_https_disable_port_80 == True + +- name: Close port 80 in firewalld (for proper testing) + firewalld: + port="80/tcp" + zone=public permanent=true state=disabled immediate=true + when: tendrl_https_disable_port_80 == True diff --git a/test_setup.tendrl_httpd_ssl_qeca.yml b/test_setup.tendrl_httpd_ssl_qeca.yml new file mode 100644 index 00000000..2ca10e3e --- /dev/null +++ b/test_setup.tendrl_httpd_ssl_qeca.yml @@ -0,0 +1,38 @@ +--- +# =============================================================== +# Setup of HTTPS for Tendrl UI, API and Grafana using QE SSL CA +# =============================================================== +# +# This is real world use case which doesn't use self signed SSL certs, but +# instead it: +# +# * generates new SSL certificate for httpd on Tendrl server +# * sings this new cert with QE SSL CA +# * SSL key and cert for http is different from SSL key and cert used for +# etcd client server auth (but it's signed by the same QE SSL CA) +# +# Browsers and clients of QE team have this QE CA imported, so that there +# should be no warning about unknown SSL certificate, and accessing Tendrl +# via https should just work. + +- hosts: usm_server + remote_user: root + vars: + tendrl_ssl_cert_name: "tendrl-grafana-http" + roles: + - role: qe-ssl-cert + ssl_cert_name: "{{ tendrl_ssl_cert_name }}" + ssl_owner: "apache" + ssl_group: "apache" + - role: tendrl-httpd-ssl + httpd_ssl_certificate_key_file: "/etc/pki/tls/private/{{ tendrl_ssl_cert_name }}.key" + httpd_ssl_certificate_file: "/etc/pki/tls/certs/{{ tendrl_ssl_cert_name }}.crt" + +# For client machine to be able to communicate with Tendrl over https without +# any problems, QE CA cert file (which signed the just deployed Tendrl httpd +# cert) is imported on the client. + +- hosts: usm_client + remote_user: root + roles: + - role: qe-ssl-ca diff --git a/test_setup.tendrl_httpd_ssl_selfsigned.yml b/test_setup.tendrl_httpd_ssl_selfsigned.yml new file mode 100644 index 00000000..7c9ae63a --- /dev/null +++ b/test_setup.tendrl_httpd_ssl_selfsigned.yml @@ -0,0 +1,12 @@ +--- +# =============================================== +# Setup of HTTPS for Tendrl UI, API and Grafana +# =============================================== +# +# This is **minimal setup**, which **uses default local ssl certs** provided by +# mod_ssl rpm package. + +- hosts: usm_server + remote_user: root + roles: + - role: tendrl-httpd-ssl diff --git a/test_teardown.tendrl_httpd_ssl.yml b/test_teardown.tendrl_httpd_ssl.yml new file mode 100644 index 00000000..d12cbb83 --- /dev/null +++ b/test_teardown.tendrl_httpd_ssl.yml @@ -0,0 +1,68 @@ +--- +# ================================================== +# Teardown of HTTPS for Tendrl UI, API and Grafana +# ================================================== +# +# This just removes any SSL Tendrl configuration (no matter if default local +# self signed certs or actuall CA is used) and configures Tendrl to use plain +# http again. + +- hosts: usm_server + remote_user: root + handlers: + - name: restart httpd + service: name=httpd state=restarted + tasks: + + - name: Remove tendrl-ssl.conf file + file: + path: /etc/httpd/conf.d/tendrl-ssl.conf + state: absent + notify: restart httpd + + - name: Restore tendrl.conf from backup + copy: + src: /etc/httpd/conf.d/tendrl.conf.usmqe_backup + dest: /etc/httpd/conf.d/tendrl.conf + remote_src: yes + backup: yes + force: yes + notify: restart httpd + + - name: Run rpm -qV tendrl-api-httpd to validate config file restoration + command: rpm -qV tendrl-api-httpd + changed_when: False + register: rpm_qv_tendrl_api_httpd + failed_when: rpm_qv_tendrl_api_httpd.rc > 1 + + - name: Recheck result of config file restoration (based on previous task) + assert: + that: + - (rpm_qv_tendrl_api_httpd.rc == 0) or (rpm_qv_tendrl_api_httpd.stdout == '.......T. c /etc/httpd/conf.d/tendrl.conf') + - rpm_qv_tendrl_api_httpd.stderr == '' + + - name: Remove mod_ssl package + yum: + name: mod_ssl + state: absent + + - name: Run apachectl configtest to validate new configuration + command: apachectl -t + changed_when: False + register: apachectl_configtest + + - name: Recheck result of config validation (based on previous task) + assert: + that: + - apachectl_configtest.stderr == 'Syntax OK' + - apachectl_configtest.stdout == '' + + - name: Disable https service in firewalld + firewalld: + service=https + zone=public permanent=true state=disabled immediate=true + + - name: Enable http service in firewalld + firewalld: + service=http + zone=public permanent=true state=enabled immediate=true