Skip to content

Commit

Permalink
Ensure old ssl certs not copied in nginx role (#149)
Browse files Browse the repository at this point in the history
Fixes #145 

Checks if ssl certificates exist on server and in cache and copies ssl
certificates based on existence and expiry dates:

- Copy from cache to server if ssl cert doesn't exist on server
- Copy from server to cache if ssl cert doesn't exist in cache
- Copy from cache to server if ssl cert on server expires sooner
- Copy from server to cache if ssl cert in cache expires sooner

---------

Co-authored-by: ruaridhg <[email protected]>
Co-authored-by: Paul Smith <[email protected]>
Co-authored-by: Daniel Matthews <[email protected]>
  • Loading branch information
4 people authored Dec 4, 2024
1 parent 6142b32 commit f37d01f
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 56 deletions.
1 change: 1 addition & 0 deletions playbooks/group_vars/db.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions playbooks/group_vars/omero.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion playbooks/group_vars/xnat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions roles/nginx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` |
Expand Down
2 changes: 1 addition & 1 deletion roles/nginx/molecule/centos7/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
35 changes: 34 additions & 1 deletion roles/nginx/molecule/resources/inventory/group_vars/all.yml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ install_python:
- libselinux-python
- policycoreutils-python
pip_packages:
- cryptography
- gunicorn
- Flask

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ install_python:
- python3-libselinux
- policycoreutils-python-utils
pip_packages:
- cryptography
- gunicorn
- flask

Expand Down
18 changes: 18 additions & 0 deletions roles/nginx/molecule/resources/prepare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,21 @@
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]
2 changes: 1 addition & 1 deletion roles/nginx/molecule/resources/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion roles/nginx/molecule/rocky9/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ platforms:
- 443
- 8000
published_ports:
- 127.0.0.1:8080:80
- 127.0.0.1:8080:443
11 changes: 11 additions & 0 deletions roles/nginx/tasks/copy_certificates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
- name: Copy 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 }}"
34 changes: 2 additions & 32 deletions roles/nginx/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +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: Copy server certificates to nginx
ansible.builtin.copy:
remote_src: true
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ nginx_owner }}"
group: "{{ nginx_group }}"
mode: "0600"
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

- 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
Expand Down
99 changes: 99 additions & 0 deletions roles/nginx/tasks/ssl_enabled.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
---
- name: Ensure nginx certs directory exists
ansible.builtin.file:
path: "{{ nginx_certs_dir }}"
owner: "{{ nginx_owner }}"
group: "{{ nginx_group }}"
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

- 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 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
- 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
- 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.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 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:
- 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 {{
nginx_diffie_helman_size_bits }}.
community.crypto.openssl_dhparam:
path: "{{ nginx_dh_params_file }}"
size: "{{ nginx_diffie_helman_size_bits }}"
notify: Reload nginx
34 changes: 18 additions & 16 deletions roles/ssl_certificates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,16 @@ 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_common_name: "db"
certificate_filename: "/var/lib/pgsql/server.crt"
provider: "selfsigned"
csr_filename: /var/lib/pgsql/server.csr
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"
Expand All @@ -108,16 +109,17 @@ 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"
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"
Expand Down
1 change: 1 addition & 0 deletions roles/ssl_certificates/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}"
Expand Down
2 changes: 1 addition & 1 deletion roles/tomcat/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit f37d01f

Please sign in to comment.