From b6ec6fc026362ba0f1a72af46377c8ffc058c3df Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Thu, 28 Nov 2024 16:26:06 +0000 Subject: [PATCH 01/14] Only copy server certs to nginx if hashes different --- roles/nginx/tasks/main.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml index 5edb101a..51a66670 100644 --- a/roles/nginx/tasks/main.yml +++ b/roles/nginx/tasks/main.yml @@ -45,6 +45,20 @@ mode: "0700" when: nginx_use_ssl +- name: Check current SSL certificate hash + ansible.builtin.stat: + path: "{{ nginx_ssl_cert_file }}" + get_checksum: true + register: current_cert_stat + when: nginx_use_ssl + +- name: Check cached SSL certificate hash + ansible.builtin.stat: + path: "{{ nginx_server_cert_cache }}" + get_checksum: true + register: cached_cert_stat + when: nginx_use_ssl + - name: Copy server certificates to nginx ansible.builtin.copy: remote_src: true @@ -59,7 +73,9 @@ - src: "{{ nginx_server_key_cache }}" dest: "{{ nginx_ssl_key_file }}" notify: Reload nginx - when: nginx_use_ssl + when: + - nginx_use_ssl + - current_cert_stat.stat.checksum != cached_cert_stat.stat.checksum - name: Generate Diffie-Hellman (DH) parameters. Number of {{ From e84e9f278b048090cb99c2caeea60ed3614faac3 Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Mon, 2 Dec 2024 15:17:59 +0000 Subject: [PATCH 02/14] Copy certs to and from cache depending on expiry --- roles/nginx/tasks/main.yml | 42 +++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml index 51a66670..8f40479f 100644 --- a/roles/nginx/tasks/main.yml +++ b/roles/nginx/tasks/main.yml @@ -45,21 +45,20 @@ mode: "0700" when: nginx_use_ssl -- name: Check current SSL certificate hash - ansible.builtin.stat: +- name: Get current SSL certificate info + community.crypto.x509_certificate_info: path: "{{ nginx_ssl_cert_file }}" - get_checksum: true - register: current_cert_stat + register: current_cert_info + ignore_errors: true # Handle case where file doesn't exist when: nginx_use_ssl -- name: Check cached SSL certificate hash - ansible.builtin.stat: +- name: Get cached SSL certificate info + community.crypto.x509_certificate_info: path: "{{ nginx_server_cert_cache }}" - get_checksum: true - register: cached_cert_stat + register: cached_cert_info when: nginx_use_ssl -- name: Copy server certificates to nginx +- name: Copy server certificates from cache (if it has a later expiry) to nginx ansible.builtin.copy: remote_src: true src: "{{ item.src }}" @@ -67,6 +66,7 @@ owner: "{{ nginx_owner }}" group: "{{ nginx_group }}" mode: "0600" + backup: true # Preserve overwritten certificates and keys for rollback with_items: - src: "{{ nginx_server_cert_cache }}" dest: "{{ nginx_ssl_cert_file }}" @@ -75,7 +75,29 @@ notify: Reload nginx when: - nginx_use_ssl - - current_cert_stat.stat.checksum != cached_cert_stat.stat.checksum + - current_cert_info.failed or (cached_cert_info.cert.not_after | to_datetime + > current_cert_info.cert.not_after | to_datetime) + +- name: + Copy server certificates from nginx (if it has a later expiry) back to cache + ansible.builtin.copy: + remote_src: true + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + mode: "0600" + backup: true # Preserve overwritten certificates and keys for rollback + with_items: + - src: "{{ nginx_ssl_cert_file }}" + dest: "{{ nginx_server_cert_cache }}" + - src: "{{ nginx_ssl_key_file }}" + dest: "{{ nginx_server_key_cache }}" + notify: Reload nginx + when: + - nginx_use_ssl + - (cached_cert_info.cert.not_after | to_datetime < + current_cert_info.cert.not_after | to_datetime) - name: Generate Diffie-Hellman (DH) parameters. Number of {{ From 8524d27dc562f2e60e761eec2b8e8013ff861a4b Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Mon, 2 Dec 2024 15:32:24 +0000 Subject: [PATCH 03/14] Separate ssl_enabled.yml file for nginx --- roles/nginx/tasks/main.yml | 72 +------------------------------ roles/nginx/tasks/ssl_enabled.yml | 66 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 70 deletions(-) create mode 100644 roles/nginx/tasks/ssl_enabled.yml diff --git a/roles/nginx/tasks/main.yml b/roles/nginx/tasks/main.yml index 8f40479f..263e2d8f 100644 --- a/roles/nginx/tasks/main.yml +++ b/roles/nginx/tasks/main.yml @@ -36,76 +36,8 @@ - nginx-mod-stream state: installed -- name: Ensure nginx certs directory exists - ansible.builtin.file: - path: "{{ nginx_certs_dir }}" - owner: "{{ nginx_owner }}" - group: "{{ nginx_group }}" - state: directory - mode: "0700" - when: nginx_use_ssl - -- name: Get current SSL certificate info - community.crypto.x509_certificate_info: - path: "{{ nginx_ssl_cert_file }}" - register: current_cert_info - ignore_errors: true # Handle case where file doesn't exist - when: nginx_use_ssl - -- name: Get cached SSL certificate info - community.crypto.x509_certificate_info: - path: "{{ nginx_server_cert_cache }}" - register: cached_cert_info - when: nginx_use_ssl - -- name: Copy server certificates from cache (if it has a later expiry) to nginx - ansible.builtin.copy: - remote_src: true - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ nginx_owner }}" - group: "{{ nginx_group }}" - mode: "0600" - backup: true # Preserve overwritten certificates and keys for rollback - with_items: - - src: "{{ nginx_server_cert_cache }}" - dest: "{{ nginx_ssl_cert_file }}" - - src: "{{ nginx_server_key_cache }}" - dest: "{{ nginx_ssl_key_file }}" - notify: Reload nginx - when: - - nginx_use_ssl - - current_cert_info.failed or (cached_cert_info.cert.not_after | to_datetime - > current_cert_info.cert.not_after | to_datetime) - -- name: - Copy server certificates from nginx (if it has a later expiry) back to cache - ansible.builtin.copy: - remote_src: true - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ nginx_owner }}" - group: "{{ nginx_group }}" - mode: "0600" - backup: true # Preserve overwritten certificates and keys for rollback - with_items: - - src: "{{ nginx_ssl_cert_file }}" - dest: "{{ nginx_server_cert_cache }}" - - src: "{{ nginx_ssl_key_file }}" - dest: "{{ nginx_server_key_cache }}" - notify: Reload nginx - when: - - nginx_use_ssl - - (cached_cert_info.cert.not_after | to_datetime < - current_cert_info.cert.not_after | to_datetime) - -- name: - Generate Diffie-Hellman (DH) parameters. Number of {{ - nginx_diffie_helman_size_bits }}. - community.crypto.openssl_dhparam: - path: "{{ nginx_dh_params_file }}" - size: "{{ nginx_diffie_helman_size_bits }}" - notify: Reload nginx +- name: Copy certificates when SSL is enabled + ansible.builtin.include_tasks: ssl_enabled.yml when: nginx_use_ssl - name: Copy nginx config file diff --git a/roles/nginx/tasks/ssl_enabled.yml b/roles/nginx/tasks/ssl_enabled.yml new file mode 100644 index 00000000..dc4c87a6 --- /dev/null +++ b/roles/nginx/tasks/ssl_enabled.yml @@ -0,0 +1,66 @@ +--- +- name: Ensure nginx certs directory exists + ansible.builtin.file: + path: "{{ nginx_certs_dir }}" + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + state: directory + mode: "0700" + +- name: Get current SSL certificate info + community.crypto.x509_certificate_info: + path: "{{ nginx_ssl_cert_file }}" + register: current_cert_info + ignore_errors: true # Handle case where file doesn't exist + +- name: Get cached SSL certificate info + community.crypto.x509_certificate_info: + path: "{{ nginx_server_cert_cache }}" + register: cached_cert_info + +- name: Copy server certificates from cache (if it has a later expiry) to nginx + ansible.builtin.copy: + remote_src: true + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + mode: "0600" + backup: true # Preserve overwritten certificates and keys for rollback + with_items: + - src: "{{ nginx_server_cert_cache }}" + dest: "{{ nginx_ssl_cert_file }}" + - src: "{{ nginx_server_key_cache }}" + dest: "{{ nginx_ssl_key_file }}" + notify: Reload nginx + when: + - current_cert_info.failed or (cached_cert_info.cert.not_after | to_datetime + > current_cert_info.cert.not_after | to_datetime) + +- name: + Copy server certificates from nginx (if it has a later expiry) back to cache + ansible.builtin.copy: + remote_src: true + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + mode: "0600" + backup: true # Preserve overwritten certificates and keys for rollback + with_items: + - src: "{{ nginx_ssl_cert_file }}" + dest: "{{ nginx_server_cert_cache }}" + - src: "{{ nginx_ssl_key_file }}" + dest: "{{ nginx_server_key_cache }}" + notify: Reload nginx + when: + - (cached_cert_info.cert.not_after | to_datetime < + current_cert_info.cert.not_after | to_datetime) + +- name: + Generate Diffie-Hellman (DH) parameters. Number of {{ + nginx_diffie_helman_size_bits }}. + community.crypto.openssl_dhparam: + path: "{{ nginx_dh_params_file }}" + size: "{{ nginx_diffie_helman_size_bits }}" + notify: Reload nginx From 710dec830228c0f0c66d9569c67223577e9987f5 Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Mon, 2 Dec 2024 15:58:59 +0000 Subject: [PATCH 04/14] Add test certificate and key to prepare.yml molecule --- roles/nginx/molecule/resources/prepare.yml | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/roles/nginx/molecule/resources/prepare.yml b/roles/nginx/molecule/resources/prepare.yml index 3c014205..3921e24d 100644 --- a/roles/nginx/molecule/resources/prepare.yml +++ b/roles/nginx/molecule/resources/prepare.yml @@ -44,3 +44,29 @@ ansible.builtin.systemd: name: gunicorn state: restarted + +- name: Add test certificates + hosts: all + become: true + tasks: + - name: Create the directory for Nginx certificates + ansible.builtin.file: + path: /etc/nginx/certs + state: directory + mode: "0700" + owner: nginx + group: nginx + + - name: Generate test certificate + ansible.builtin.command: + cmd: + openssl req -new -x509 -key /etc/nginx/certs/test.key -out + /etc/nginx/certs/test.crt -days 365 -subj '/CN=example.com' + args: + creates: /etc/nginx/certs/test.crt + + - name: Generate test private key + ansible.builtin.command: + cmd: openssl genrsa -out /etc/nginx/certs/test.key 2048 + args: + creates: /etc/nginx/certs/test.key From c85e8eece06884da363db442fe10e5f9e4cf1ccf Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Mon, 2 Dec 2024 16:37:09 +0000 Subject: [PATCH 05/14] Fix prepare.yml --- roles/nginx/molecule/resources/prepare.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/roles/nginx/molecule/resources/prepare.yml b/roles/nginx/molecule/resources/prepare.yml index 3921e24d..f7328483 100644 --- a/roles/nginx/molecule/resources/prepare.yml +++ b/roles/nginx/molecule/resources/prepare.yml @@ -53,9 +53,15 @@ ansible.builtin.file: path: /etc/nginx/certs state: directory - mode: "0700" - owner: nginx - group: nginx + owner: root + group: root + mode: "0644" + + - name: Generate test private key + ansible.builtin.command: + cmd: openssl genrsa -out /etc/nginx/certs/test.key 2048 + args: + creates: /etc/nginx/certs/test.key - name: Generate test certificate ansible.builtin.command: @@ -64,9 +70,3 @@ /etc/nginx/certs/test.crt -days 365 -subj '/CN=example.com' args: creates: /etc/nginx/certs/test.crt - - - name: Generate test private key - ansible.builtin.command: - cmd: openssl genrsa -out /etc/nginx/certs/test.key 2048 - args: - creates: /etc/nginx/certs/test.key From a9d0c00a864514f41ad6689caca7eac339d8e31b Mon Sep 17 00:00:00 2001 From: ruaridhg Date: Tue, 3 Dec 2024 10:03:49 +0000 Subject: [PATCH 06/14] Remove certs from prepare --- roles/nginx/molecule/resources/prepare.yml | 26 ---------------------- 1 file changed, 26 deletions(-) diff --git a/roles/nginx/molecule/resources/prepare.yml b/roles/nginx/molecule/resources/prepare.yml index f7328483..3c014205 100644 --- a/roles/nginx/molecule/resources/prepare.yml +++ b/roles/nginx/molecule/resources/prepare.yml @@ -44,29 +44,3 @@ ansible.builtin.systemd: name: gunicorn state: restarted - -- name: Add test certificates - hosts: all - become: true - tasks: - - name: Create the directory for Nginx certificates - ansible.builtin.file: - path: /etc/nginx/certs - state: directory - owner: root - group: root - mode: "0644" - - - name: Generate test private key - ansible.builtin.command: - cmd: openssl genrsa -out /etc/nginx/certs/test.key 2048 - args: - creates: /etc/nginx/certs/test.key - - - name: Generate test certificate - ansible.builtin.command: - cmd: - openssl req -new -x509 -key /etc/nginx/certs/test.key -out - /etc/nginx/certs/test.crt -days 365 -subj '/CN=example.com' - args: - creates: /etc/nginx/certs/test.crt From 0a7585a4acf2def711134d7acf0a97a26b8e693f Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 3 Dec 2024 12:56:19 +0000 Subject: [PATCH 07/14] Add selfsigned_not_after varaible for ssl_certificates role also enable ssl for molecule tests in nginx role --- playbooks/group_vars/db.yml | 1 + playbooks/group_vars/omero.yml | 1 + playbooks/group_vars/xnat.yml | 1 + .../monitoring/inventory/host_vars/mserv.yml | 1 + roles/nginx/README.md | 4 +-- .../resources/inventory/group_vars/all.yml | 35 ++++++++++++++++++- .../inventory/group_vars/centos7.yml | 1 + .../resources/inventory/group_vars/rocky9.yml | 1 + roles/nginx/molecule/resources/prepare.yml | 15 ++++++++ roles/nginx/molecule/resources/verify.yml | 2 +- roles/ssl_certificates/README.md | 2 ++ roles/ssl_certificates/tasks/main.yml | 1 + 12 files changed, 61 insertions(+), 4 deletions(-) diff --git a/playbooks/group_vars/db.yml b/playbooks/group_vars/db.yml index 374377a1..f465adb0 100644 --- a/playbooks/group_vars/db.yml +++ b/playbooks/group_vars/db.yml @@ -37,6 +37,7 @@ postgresql_ssl_certificate: csr_common_name: "{{ db_server.host }}" certificate_filename: "{{ postgresql.base_directory }}/certs/server.crt" provider: selfsigned + selfsigned_not_after: "+3650d" cache_filename: "{{ database_server_certificate_cache_filename }}" # where to store the server certificate in cache firewalld_rich_rules: diff --git a/playbooks/group_vars/omero.yml b/playbooks/group_vars/omero.yml index 8c784c45..d676bfdc 100644 --- a/playbooks/group_vars/omero.yml +++ b/playbooks/group_vars/omero.yml @@ -14,6 +14,7 @@ postgresql_client_ssl_certificate: csr_common_name: "{{ web_server.host }}" certificate_filename: /opt/omero/server/.postgresql/postgresql.crt provider: selfsigned + selfsigned_not_after: "+3650d" cache_filename: "{{ database_client_certificate_cache_filename }}" # where to store the client certificate in cache # firewalld diff --git a/playbooks/group_vars/xnat.yml b/playbooks/group_vars/xnat.yml index eb35a9fe..82a74a94 100644 --- a/playbooks/group_vars/xnat.yml +++ b/playbooks/group_vars/xnat.yml @@ -60,6 +60,7 @@ postgresql_client_ssl_certificate: csr_common_name: "{{ web_server.host }}" certificate_filename: /usr/share/tomcat/.postgresql/postgresql.crt provider: selfsigned + selfsigned_not_after: "+3650d" cache_filename: "{{ database_client_certificate_cache_filename }}" # where to store the client certificate in cache java: diff --git a/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml b/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml index 3b7a6549..e6d7d469 100644 --- a/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml +++ b/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml @@ -9,3 +9,4 @@ monitoring_server_ssl_certificate: csr_common_name: "{{ hostvars['mserv']['hostname'] }}" certificate_filename: /etc/ssl/certs/{{ hostvars['mserv']['hostname'] }}.cert provider: selfsigned + selfsigned_not_after: "+3650d" diff --git a/roles/nginx/README.md b/roles/nginx/README.md index 8f38247c..5d2b9d9c 100644 --- a/roles/nginx/README.md +++ b/roles/nginx/README.md @@ -32,8 +32,8 @@ variables: | ------------------------------- | ----------------------------------------------------------------------------------------- | | `nginx_use_ssl` | Whether to use SSL. Defaults to `true` | | `nginx_certs_dir` | Where to store the certificates. Defaults to `/etc/nginx/ssl` | -| `nginx_server_cert_cache` | Path to SSL certificate on the Ansible Controller. Required if using SSL; no default | -| `nginx_server_key_cache` | Path to SSL certificate on the Ansible Controller. Required if using SSL; no default | +| `nginx_server_cert_cache` | Path to SSL certificates on the Ansible host. Required if using SSL; no default | +| `nginx_server_key_cache` | Path to SSL certificate on the Ansible host. Required if using SSL; no default | | `nginx_ssl_cert_file` | Path to copy the SSL certificate to. Defaults to `/etc/nginx/ssl/server.cert` | | `nginx_ssl_key_file` | Path to copy the SSL key to. Defaults to `/etc/nginx/ssl/server.key` | | `nginx_diffie_helman_size_bits` | Bit size for OpenSSL Diffie-Hellman Parameters. Defaults to `4096` | diff --git a/roles/nginx/molecule/resources/inventory/group_vars/all.yml b/roles/nginx/molecule/resources/inventory/group_vars/all.yml index 018954e3..585a1fa2 100644 --- a/roles/nginx/molecule/resources/inventory/group_vars/all.yml +++ b/roles/nginx/molecule/resources/inventory/group_vars/all.yml @@ -1,6 +1,39 @@ --- +nginx_owner: root +nginx_group: root + nginx_server_name: molecule.instance.local nginx_proxy_port: 8000 nginx_diffie_helman_size_bits: 2048 nginx_root: /home/ -nginx_use_ssl: false + +nginx_use_ssl: true +nginx_certs_dir: /etc/nginx/ssl +nginx_ssl_cert_file: /etc/nginx/ssl/server.cert +nginx_ssl_key_file: /etc/nginx/ssl/server.key +nginx_server_cert_cache: /etc/ssl/certs/server.cert +nginx_server_key_cache: /etc//ssl/certs/server.key + +nginx_old_ssl_certificate: + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + certificate_directory: /etc/ssl/certs + privatekey_filename: "{{ nginx_server_key_cache }}" + use_pk8: false + csr_filename: /etc/ssl/certs/server.csr" + csr_common_name: "{{ nginx_server_name }}" + certificate_filename: "{{ nginx_server_cert_cache }}" + provider: selfsigned + selfsigned_not_after: "+365d" + +nginx_new_ssl_certificate: + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + certificate_directory: "{{ nginx_certs_dir }}" + privatekey_filename: "{{ nginx_ssl_key_file }}" + use_pk8: false + csr_filename: "{{ nginx_certs_dir }}/server.csr" + csr_common_name: "{{ nginx_server_name }}" + certificate_filename: "{{ nginx_ssl_cert_file }}" + provider: selfsigned + selfsigned_not_after: "+3650d" diff --git a/roles/nginx/molecule/resources/inventory/group_vars/centos7.yml b/roles/nginx/molecule/resources/inventory/group_vars/centos7.yml index 8be670cc..aff12e5b 100644 --- a/roles/nginx/molecule/resources/inventory/group_vars/centos7.yml +++ b/roles/nginx/molecule/resources/inventory/group_vars/centos7.yml @@ -11,6 +11,7 @@ install_python: - libselinux-python - policycoreutils-python pip_packages: + - cryptography - gunicorn - Flask diff --git a/roles/nginx/molecule/resources/inventory/group_vars/rocky9.yml b/roles/nginx/molecule/resources/inventory/group_vars/rocky9.yml index e587b569..044f6ca3 100644 --- a/roles/nginx/molecule/resources/inventory/group_vars/rocky9.yml +++ b/roles/nginx/molecule/resources/inventory/group_vars/rocky9.yml @@ -11,6 +11,7 @@ install_python: - python3-libselinux - policycoreutils-python-utils pip_packages: + - cryptography - gunicorn - flask diff --git a/roles/nginx/molecule/resources/prepare.yml b/roles/nginx/molecule/resources/prepare.yml index 3c014205..279191e4 100644 --- a/roles/nginx/molecule/resources/prepare.yml +++ b/roles/nginx/molecule/resources/prepare.yml @@ -44,3 +44,18 @@ ansible.builtin.systemd: name: gunicorn state: restarted + +- name: Create SSL certificates for nginx + hosts: all + gather_facts: true + tasks: + - name: Create SSL certificate that expires in 1 year and store in server cache + ansible.builtin.include_role: + name: mirsg.infrastructure.ssl_certificates + vars: + ssl_certificate: "{{ nginx_old_ssl_certificate }}" # noqa: var-naming[no-role-prefix] + - name: Create SSL certificate that expires in 10 years and store in nginx certificate directory + ansible.builtin.include_role: + name: mirsg.infrastructure.ssl_certificates + vars: + ssl_certificate: "{{ nginx_new_ssl_certificate }}" # noqa: var-naming[no-role-prefix] diff --git a/roles/nginx/molecule/resources/verify.yml b/roles/nginx/molecule/resources/verify.yml index 267189cd..d2c6fcc5 100644 --- a/roles/nginx/molecule/resources/verify.yml +++ b/roles/nginx/molecule/resources/verify.yml @@ -4,7 +4,7 @@ tasks: - name: Get server status ansible.builtin.uri: - url: http://localhost:8080 + url: https://localhost:8080 method: GET headers: Host: molecule.instance.local diff --git a/roles/ssl_certificates/README.md b/roles/ssl_certificates/README.md index 21a50120..4db6e0c4 100644 --- a/roles/ssl_certificates/README.md +++ b/roles/ssl_certificates/README.md @@ -95,6 +95,7 @@ ssl_certificate: csr_common_name: "db" certificate_filename: "/var/lib/pgsql/server.crt" provider: "selfsigned" + selfsigned_not_after: "+3650d" cache_filename: "{{ lookup('env', 'HOME') }}/ansible_persistent_files/pg_certificates/db.postgresql_server.crt" @@ -118,6 +119,7 @@ ssl_certificate: csr_common_name: "{{ web_hostname }}" certificate_filename: "/usr/share/tomcat/.postgresql/postgresql.crt" provider: "selfsigned" + selfsigned_not_after: "+3650d" cache_filename: "{{ lookup('env', 'HOME') }}/ansible_persistent_files/pg_certificates/db.postgresql_client.crt" diff --git a/roles/ssl_certificates/tasks/main.yml b/roles/ssl_certificates/tasks/main.yml index 636e4fe2..f6cc4884 100644 --- a/roles/ssl_certificates/tasks/main.yml +++ b/roles/ssl_certificates/tasks/main.yml @@ -35,6 +35,7 @@ privatekey_path: "{{ ssl_certificate.privatekey_filename }}" csr_path: "{{ ssl_certificate.csr_filename }}" provider: "{{ ssl_certificate.provider }}" + selfsigned_not_after: "{{ ssl_certificate.selfsigned_not_after }}" mode: "0400" owner: "{{ ssl_certificate.owner }}" group: "{{ ssl_certificate.group }}" From 7c61b68109c18828a65bc93335f37070d60103bf Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 3 Dec 2024 15:09:47 +0000 Subject: [PATCH 08/14] fix comparision of expiry dates for cache and nginx certs --- roles/nginx/molecule/resources/verify.yml | 2 +- roles/nginx/tasks/ssl_enabled.yml | 101 ++++++++++++++-------- 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/roles/nginx/molecule/resources/verify.yml b/roles/nginx/molecule/resources/verify.yml index d2c6fcc5..267189cd 100644 --- a/roles/nginx/molecule/resources/verify.yml +++ b/roles/nginx/molecule/resources/verify.yml @@ -4,7 +4,7 @@ tasks: - name: Get server status ansible.builtin.uri: - url: https://localhost:8080 + url: http://localhost:8080 method: GET headers: Host: molecule.instance.local diff --git a/roles/nginx/tasks/ssl_enabled.yml b/roles/nginx/tasks/ssl_enabled.yml index dc4c87a6..a8d5aa53 100644 --- a/roles/nginx/tasks/ssl_enabled.yml +++ b/roles/nginx/tasks/ssl_enabled.yml @@ -7,55 +7,84 @@ state: directory mode: "0700" +- name: Stat current SSL certificate + ansible.builtin.stat: + path: "{{ nginx_ssl_cert_file }}" + register: current_cert + +- name: Stat cached SSL certificate + ansible.builtin.stat: + path: "{{ nginx_server_cert_cache }}" + register: cached_cert + +- name: Check whether the certs exist + ansible.builtin.debug: + msg: + - "Cached nginx cert exists at {{ nginx_server_cert_cache }}: {{ + cached_cert.stat.exists }}." + - "nginx cert exists at {{ nginx_ssl_cert_file }}: {{ + current_cert.stat.exists }}." + failed_when: (not cached_cert.stat.exists) and (not current_cert.stat.exists) + - name: Get current SSL certificate info community.crypto.x509_certificate_info: path: "{{ nginx_ssl_cert_file }}" + when: current_cert.stat.exists register: current_cert_info - ignore_errors: true # Handle case where file doesn't exist - name: Get cached SSL certificate info community.crypto.x509_certificate_info: path: "{{ nginx_server_cert_cache }}" + when: cached_cert.stat.exists register: cached_cert_info -- name: Copy server certificates from cache (if it has a later expiry) to nginx - ansible.builtin.copy: - remote_src: true - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ nginx_owner }}" - group: "{{ nginx_group }}" - mode: "0600" - backup: true # Preserve overwritten certificates and keys for rollback - with_items: - - src: "{{ nginx_server_cert_cache }}" - dest: "{{ nginx_ssl_cert_file }}" - - src: "{{ nginx_server_key_cache }}" - dest: "{{ nginx_ssl_key_file }}" - notify: Reload nginx +- name: Copy server certificates from cache if the nginx cert doesn't exist + ansible.builtin.include_tasks: copy_certificates.yml + vars: + items: + - src: "{{ nginx_server_cert_cache }}" + dest: "{{ nginx_ssl_cert_file }}" + - src: "{{ nginx_server_key_cache }}" + dest: "{{ nginx_ssl_key_file }}" + when: not current_cert.stat.exists and cached_cert.stat.exists + +- name: Copy server certificates to cache if the cache cert doesn't exist + ansible.builtin.include_tasks: copy_certificates.yml + vars: + items: + - src: "{{ nginx_ssl_cert_file }}" + dest: "{{ nginx_server_cert_cache }}" + - src: "{{ nginx_ssl_key_file }}" + dest: "{{ nginx_server_key_cache }}" + when: current_cert.stat.exists and not cached_cert.stat.exists + +- name: Copy server certificates from cache if the nginx cert expires sooner + ansible.builtin.include_tasks: copy_certificates.yml + vars: + items: + - src: "{{ nginx_server_cert_cache }}" + dest: "{{ nginx_ssl_cert_file }}" + - src: "{{ nginx_server_key_cache }}" + dest: "{{ nginx_ssl_key_file }}" when: - - current_cert_info.failed or (cached_cert_info.cert.not_after | to_datetime - > current_cert_info.cert.not_after | to_datetime) + - current_cert.stat.exists + - cached_cert.stat.exists + - current_cert_info.not_after | to_datetime('%Y%m%d%H%M%SZ') < + cached_cert_info.not_after | to_datetime('%Y%m%d%H%M%SZ') -- name: - Copy server certificates from nginx (if it has a later expiry) back to cache - ansible.builtin.copy: - remote_src: true - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ nginx_owner }}" - group: "{{ nginx_group }}" - mode: "0600" - backup: true # Preserve overwritten certificates and keys for rollback - with_items: - - src: "{{ nginx_ssl_cert_file }}" - dest: "{{ nginx_server_cert_cache }}" - - src: "{{ nginx_ssl_key_file }}" - dest: "{{ nginx_server_key_cache }}" - notify: Reload nginx +- name: Copy server certificates to cache if the cache cert expires sooner + ansible.builtin.include_tasks: copy_certificates.yml + vars: + items: + - src: "{{ nginx_ssl_cert_file }}" + dest: "{{ nginx_server_cert_cache }}" + - src: "{{ nginx_ssl_key_file }}" + dest: "{{ nginx_server_key_cache }}" when: - - (cached_cert_info.cert.not_after | to_datetime < - current_cert_info.cert.not_after | to_datetime) + - not current_cert.stat.exists + - cached_cert.stat.exists + - current_cert_info.not_after | to_datetime('%Y%m%d%H%M%SZ') > + cached_cert_info.not_after | to_datetime('%Y%m%d%H%M%SZ') - name: Generate Diffie-Hellman (DH) parameters. Number of {{ From 2677ba4adfac4cb872fa29d473a79823605cf006 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 3 Dec 2024 15:20:17 +0000 Subject: [PATCH 09/14] Add tasks to copy certs between cache and nginx --- roles/nginx/tasks/copy_certificates.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 roles/nginx/tasks/copy_certificates.yml diff --git a/roles/nginx/tasks/copy_certificates.yml b/roles/nginx/tasks/copy_certificates.yml new file mode 100644 index 00000000..11027a30 --- /dev/null +++ b/roles/nginx/tasks/copy_certificates.yml @@ -0,0 +1,11 @@ +--- +- name: Copy server certificate to new location + ansible.builtin.copy: + remote_src: true + src: "{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ nginx_owner }}" + group: "{{ nginx_group }}" + mode: "0600" + backup: true # Preserve overwritten certificates and keys for rollback + with_items: "{{ items }}" From 04b5203278e201f49c4280270f0a23bc31ed716a Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 3 Dec 2024 16:06:11 +0000 Subject: [PATCH 10/14] Use https in verify stage of molecule tests for nginx role --- roles/nginx/molecule/centos7/molecule.yml | 2 +- roles/nginx/molecule/resources/verify.yml | 2 +- roles/nginx/molecule/rocky9/molecule.yml | 2 +- roles/nginx/tasks/copy_certificates.yml | 2 +- roles/nginx/tasks/ssl_enabled.yml | 10 +++++++--- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/roles/nginx/molecule/centos7/molecule.yml b/roles/nginx/molecule/centos7/molecule.yml index 0279dcbd..15b4ec4b 100644 --- a/roles/nginx/molecule/centos7/molecule.yml +++ b/roles/nginx/molecule/centos7/molecule.yml @@ -30,6 +30,6 @@ platforms: - 443 - 8000 published_ports: - - 127.0.0.1:8080:80 + - 127.0.0.1:8080:443 etc_hosts: molecule.instance.local: 192.168.56.2 diff --git a/roles/nginx/molecule/resources/verify.yml b/roles/nginx/molecule/resources/verify.yml index 267189cd..d2c6fcc5 100644 --- a/roles/nginx/molecule/resources/verify.yml +++ b/roles/nginx/molecule/resources/verify.yml @@ -4,7 +4,7 @@ tasks: - name: Get server status ansible.builtin.uri: - url: http://localhost:8080 + url: https://localhost:8080 method: GET headers: Host: molecule.instance.local diff --git a/roles/nginx/molecule/rocky9/molecule.yml b/roles/nginx/molecule/rocky9/molecule.yml index 8142a715..e33a343f 100644 --- a/roles/nginx/molecule/rocky9/molecule.yml +++ b/roles/nginx/molecule/rocky9/molecule.yml @@ -31,4 +31,4 @@ platforms: - 443 - 8000 published_ports: - - 127.0.0.1:8080:80 + - 127.0.0.1:8080:443 diff --git a/roles/nginx/tasks/copy_certificates.yml b/roles/nginx/tasks/copy_certificates.yml index 11027a30..9f6b8c9b 100644 --- a/roles/nginx/tasks/copy_certificates.yml +++ b/roles/nginx/tasks/copy_certificates.yml @@ -1,5 +1,5 @@ --- -- name: Copy server certificate to new location +- name: Copy certificate to new location ansible.builtin.copy: remote_src: true src: "{{ item.src }}" diff --git a/roles/nginx/tasks/ssl_enabled.yml b/roles/nginx/tasks/ssl_enabled.yml index a8d5aa53..5cae1270 100644 --- a/roles/nginx/tasks/ssl_enabled.yml +++ b/roles/nginx/tasks/ssl_enabled.yml @@ -46,7 +46,9 @@ dest: "{{ nginx_ssl_cert_file }}" - src: "{{ nginx_server_key_cache }}" dest: "{{ nginx_ssl_key_file }}" - when: not current_cert.stat.exists and cached_cert.stat.exists + when: + - not current_cert.stat.exists + - cached_cert.stat.exists - name: Copy server certificates to cache if the cache cert doesn't exist ansible.builtin.include_tasks: copy_certificates.yml @@ -56,7 +58,9 @@ dest: "{{ nginx_server_cert_cache }}" - src: "{{ nginx_ssl_key_file }}" dest: "{{ nginx_server_key_cache }}" - when: current_cert.stat.exists and not cached_cert.stat.exists + when: + - current_cert.stat.exists + - not cached_cert.stat.exists - name: Copy server certificates from cache if the nginx cert expires sooner ansible.builtin.include_tasks: copy_certificates.yml @@ -81,7 +85,7 @@ - src: "{{ nginx_ssl_key_file }}" dest: "{{ nginx_server_key_cache }}" when: - - not current_cert.stat.exists + - current_cert.stat.exists - cached_cert.stat.exists - current_cert_info.not_after | to_datetime('%Y%m%d%H%M%SZ') > cached_cert_info.not_after | to_datetime('%Y%m%d%H%M%SZ') From e79aae69ee38dd36cf634977cf926ff3dfe201a0 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Wed, 4 Dec 2024 10:20:39 +0000 Subject: [PATCH 11/14] update tomcat version --- playbooks/group_vars/xnat.yml | 2 +- roles/tomcat/defaults/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/playbooks/group_vars/xnat.yml b/playbooks/group_vars/xnat.yml index 82a74a94..555d6eee 100644 --- a/playbooks/group_vars/xnat.yml +++ b/playbooks/group_vars/xnat.yml @@ -21,7 +21,7 @@ xnat_source: context_file_location: /usr/share/tomcat/webapps/ROOT/META-INF/context.xml # mirsg.infrastructure.tomcat -tomcat_version: 9.0.82 +tomcat_version: 9.0.97 tomcat_owner: tomcat tomcat_group: tomcat diff --git a/roles/tomcat/defaults/main.yml b/roles/tomcat/defaults/main.yml index e31ae382..d9fe1814 100644 --- a/roles/tomcat/defaults/main.yml +++ b/roles/tomcat/defaults/main.yml @@ -7,7 +7,7 @@ java_home: /usr/lib/jvm/jre java_profile_d: /etc/profile.d # mirsg.tomcat -tomcat_version: 9.0.82 +tomcat_version: 9.0.97 tomcat_owner: tomcat tomcat_group: tomcat From 94f469c77ec6338e4f1c0ca7edb597cc698f9282 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Wed, 4 Dec 2024 13:23:52 +0000 Subject: [PATCH 12/14] make linters happy --- playbooks/group_vars/db.yml | 2 +- playbooks/group_vars/omero.yml | 2 +- playbooks/group_vars/xnat.yml | 2 +- .../resources/monitoring/inventory/host_vars/mserv.yml | 2 +- roles/nginx/README.md | 4 ++-- .../nginx/molecule/resources/inventory/group_vars/all.yml | 4 ++-- roles/nginx/molecule/resources/prepare.yml | 7 +++++-- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/playbooks/group_vars/db.yml b/playbooks/group_vars/db.yml index f465adb0..8fa48d6b 100644 --- a/playbooks/group_vars/db.yml +++ b/playbooks/group_vars/db.yml @@ -37,7 +37,7 @@ postgresql_ssl_certificate: csr_common_name: "{{ db_server.host }}" certificate_filename: "{{ postgresql.base_directory }}/certs/server.crt" provider: selfsigned - selfsigned_not_after: "+3650d" + selfsigned_not_after: +3650d cache_filename: "{{ database_server_certificate_cache_filename }}" # where to store the server certificate in cache firewalld_rich_rules: diff --git a/playbooks/group_vars/omero.yml b/playbooks/group_vars/omero.yml index d676bfdc..6b533d21 100644 --- a/playbooks/group_vars/omero.yml +++ b/playbooks/group_vars/omero.yml @@ -14,7 +14,7 @@ postgresql_client_ssl_certificate: csr_common_name: "{{ web_server.host }}" certificate_filename: /opt/omero/server/.postgresql/postgresql.crt provider: selfsigned - selfsigned_not_after: "+3650d" + selfsigned_not_after: +3650d cache_filename: "{{ database_client_certificate_cache_filename }}" # where to store the client certificate in cache # firewalld diff --git a/playbooks/group_vars/xnat.yml b/playbooks/group_vars/xnat.yml index 555d6eee..8ecca5b5 100644 --- a/playbooks/group_vars/xnat.yml +++ b/playbooks/group_vars/xnat.yml @@ -60,7 +60,7 @@ postgresql_client_ssl_certificate: csr_common_name: "{{ web_server.host }}" certificate_filename: /usr/share/tomcat/.postgresql/postgresql.crt provider: selfsigned - selfsigned_not_after: "+3650d" + selfsigned_not_after: +3650d cache_filename: "{{ database_client_certificate_cache_filename }}" # where to store the client certificate in cache java: diff --git a/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml b/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml index e6d7d469..986a87f4 100644 --- a/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml +++ b/playbooks/molecule/resources/monitoring/inventory/host_vars/mserv.yml @@ -9,4 +9,4 @@ monitoring_server_ssl_certificate: csr_common_name: "{{ hostvars['mserv']['hostname'] }}" certificate_filename: /etc/ssl/certs/{{ hostvars['mserv']['hostname'] }}.cert provider: selfsigned - selfsigned_not_after: "+3650d" + selfsigned_not_after: +3650d diff --git a/roles/nginx/README.md b/roles/nginx/README.md index 5d2b9d9c..0f881619 100644 --- a/roles/nginx/README.md +++ b/roles/nginx/README.md @@ -32,8 +32,8 @@ variables: | ------------------------------- | ----------------------------------------------------------------------------------------- | | `nginx_use_ssl` | Whether to use SSL. Defaults to `true` | | `nginx_certs_dir` | Where to store the certificates. Defaults to `/etc/nginx/ssl` | -| `nginx_server_cert_cache` | Path to SSL certificates on the Ansible host. Required if using SSL; no default | -| `nginx_server_key_cache` | Path to SSL certificate on the Ansible host. Required if using SSL; no default | +| `nginx_server_cert_cache` | Path to SSL certificates on the Ansible host. Required if using SSL; no default | +| `nginx_server_key_cache` | Path to SSL certificate on the Ansible host. Required if using SSL; no default | | `nginx_ssl_cert_file` | Path to copy the SSL certificate to. Defaults to `/etc/nginx/ssl/server.cert` | | `nginx_ssl_key_file` | Path to copy the SSL key to. Defaults to `/etc/nginx/ssl/server.key` | | `nginx_diffie_helman_size_bits` | Bit size for OpenSSL Diffie-Hellman Parameters. Defaults to `4096` | diff --git a/roles/nginx/molecule/resources/inventory/group_vars/all.yml b/roles/nginx/molecule/resources/inventory/group_vars/all.yml index 585a1fa2..a2343cf5 100644 --- a/roles/nginx/molecule/resources/inventory/group_vars/all.yml +++ b/roles/nginx/molecule/resources/inventory/group_vars/all.yml @@ -24,7 +24,7 @@ nginx_old_ssl_certificate: csr_common_name: "{{ nginx_server_name }}" certificate_filename: "{{ nginx_server_cert_cache }}" provider: selfsigned - selfsigned_not_after: "+365d" + selfsigned_not_after: +365d nginx_new_ssl_certificate: owner: "{{ nginx_owner }}" @@ -36,4 +36,4 @@ nginx_new_ssl_certificate: csr_common_name: "{{ nginx_server_name }}" certificate_filename: "{{ nginx_ssl_cert_file }}" provider: selfsigned - selfsigned_not_after: "+3650d" + selfsigned_not_after: +3650d diff --git a/roles/nginx/molecule/resources/prepare.yml b/roles/nginx/molecule/resources/prepare.yml index 279191e4..b0542b2e 100644 --- a/roles/nginx/molecule/resources/prepare.yml +++ b/roles/nginx/molecule/resources/prepare.yml @@ -49,12 +49,15 @@ hosts: all gather_facts: true tasks: - - name: Create SSL certificate that expires in 1 year and store in server cache + - name: + Create SSL certificate that expires in 1 year and store in server cache ansible.builtin.include_role: name: mirsg.infrastructure.ssl_certificates vars: ssl_certificate: "{{ nginx_old_ssl_certificate }}" # noqa: var-naming[no-role-prefix] - - name: Create SSL certificate that expires in 10 years and store in nginx certificate directory + - name: + Create SSL certificate that expires in 10 years and store in nginx + certificate directory ansible.builtin.include_role: name: mirsg.infrastructure.ssl_certificates vars: From 836075754fcc2b906cd887454e2164e402f07474 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Wed, 4 Dec 2024 15:10:42 +0000 Subject: [PATCH 13/14] remove unnecessary double quotes from code block Co-authored-by: Daniel Matthews --- roles/ssl_certificates/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/roles/ssl_certificates/README.md b/roles/ssl_certificates/README.md index 4db6e0c4..8bdd85e9 100644 --- a/roles/ssl_certificates/README.md +++ b/roles/ssl_certificates/README.md @@ -92,10 +92,10 @@ ssl_certificate: privatekey_filename: "/var/lib/pgsql/certs/server.key" use_pk8: false csr_filename: "/var/lib/pgsql/server.csr" - csr_common_name: "db" - certificate_filename: "/var/lib/pgsql/server.crt" - provider: "selfsigned" - selfsigned_not_after: "+3650d" + csr_common_name: db + certificate_filename: /var/lib/pgsql/server.crt + provider: selfsigned + selfsigned_not_after: +3650d cache_filename: "{{ lookup('env', 'HOME') }}/ansible_persistent_files/pg_certificates/db.postgresql_server.crt" @@ -117,9 +117,9 @@ ssl_certificate: pk8_filename: "/usr/share/tomcat/.postgresql/postgresql.pk8" csr_filename: "/usr/share/tomcat/.postgresql/postgresql.csr" csr_common_name: "{{ web_hostname }}" - certificate_filename: "/usr/share/tomcat/.postgresql/postgresql.crt" - provider: "selfsigned" - selfsigned_not_after: "+3650d" + certificate_filename: /usr/share/tomcat/.postgresql/postgresql.crt + provider: selfsigned + selfsigned_not_after: +3650d cache_filename: "{{ lookup('env', 'HOME') }}/ansible_persistent_files/pg_certificates/db.postgresql_client.crt" From 8218f162986312d219e4e129dc6d4c8a8bf2a1ce Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Wed, 4 Dec 2024 15:23:23 +0000 Subject: [PATCH 14/14] remove remaining redundant quotes from yaml block in readme --- roles/ssl_certificates/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/roles/ssl_certificates/README.md b/roles/ssl_certificates/README.md index 8bdd85e9..780f0514 100644 --- a/roles/ssl_certificates/README.md +++ b/roles/ssl_certificates/README.md @@ -86,12 +86,12 @@ First define variables for the server: ```yaml # Variables for creating a SSL certificate for a postgresql server ssl_certificate: - owner: "root" - group: "root" - certificate_directory: "/var/lib/pgsql/certs" - privatekey_filename: "/var/lib/pgsql/certs/server.key" + owner: root + group: root + certificate_directory: /var/lib/pgsql/certs + privatekey_filename: /var/lib/pgsql/certs/server.key use_pk8: false - csr_filename: "/var/lib/pgsql/server.csr" + csr_filename: /var/lib/pgsql/server.csr csr_common_name: db certificate_filename: /var/lib/pgsql/server.crt provider: selfsigned @@ -109,13 +109,13 @@ client is a tomcat server: ```yaml # Variables for creating a SSL certificate for a postgresql client ssl_certificate: - owner: "root" - group: "root" - certificate_directory: "/usr/share/tomcat/.postgresql" - privatekey_filename: "/usr/share/tomcat/.postgresql/postgresql.key" + owner: root + group: root + certificate_directory: /usr/share/tomcat/.postgresql + privatekey_filename: /usr/share/tomcat/.postgresql/postgresql.key use_pk8: true - pk8_filename: "/usr/share/tomcat/.postgresql/postgresql.pk8" - csr_filename: "/usr/share/tomcat/.postgresql/postgresql.csr" + pk8_filename: /usr/share/tomcat/.postgresql/postgresql.pk8 + csr_filename: /usr/share/tomcat/.postgresql/postgresql.csr csr_common_name: "{{ web_hostname }}" certificate_filename: /usr/share/tomcat/.postgresql/postgresql.crt provider: selfsigned