From 3f55994bb7a7515628f81a47346aae230e88a513 Mon Sep 17 00:00:00 2001 From: Michal Arbet Date: Wed, 11 Sep 2024 16:36:58 +0200 Subject: [PATCH] Fix TLS settings when letsencrypt turned on - Introduced `letsencrypt_managed_certs` variable to handle whether letsencrypt will generate internal, external or both certificates. - Updated certificate generation logic to use `letsencrypt_managed_certs` conditionally, replacing the previous `enable_letsencrypt` boolean. - Adjusted tasks and templates to support internal/external certificate management based on the new variable. - Enhanced Let's Encrypt script (`letsencrypt-lego-run.sh.j2`) to handle both internal and external certificates depending on VIP configurations. - Refined HAProxy configuration templates to correctly map certificates based on TLS settings and new management logic. Closes-bug: #2076331 Change-Id: Id80c7823fcc5d934b7369c7c0722cd78188e2ccf Co-Authored-By: Michal Arbet --- ansible/group_vars/all.yml | 4 + ansible/roles/certificates/tasks/generate.yml | 73 +++++++++++------ ansible/roles/certificates/tasks/main.yml | 2 +- ansible/roles/letsencrypt/defaults/main.yml | 1 - .../roles/letsencrypt/templates/crontab.j2 | 10 ++- .../templates/letsencrypt-lego-run.sh.j2 | 10 ++- ansible/roles/loadbalancer/defaults/main.yml | 1 + ansible/roles/loadbalancer/tasks/config.yml | 38 +-------- .../roles/loadbalancer/tasks/copy-certs.yml | 82 +++++++++++++++---- ansible/roles/loadbalancer/tasks/precheck.yml | 64 +++++++-------- .../templates/haproxy/haproxy.json.j2 | 7 +- ansible/roles/rabbitmq/defaults/main.yml | 5 ++ .../roles/service-cert-copy/defaults/main.yml | 1 + .../roles/service-cert-copy/tasks/main.yml | 4 +- doc/source/admin/tls.rst | 15 ++++ .../notes/bug-2076331-f4ef64ad0a12aa85.yaml | 21 +++++ tests/templates/globals-default.j2 | 7 +- 17 files changed, 214 insertions(+), 131 deletions(-) create mode 100644 releasenotes/notes/bug-2076331-f4ef64ad0a12aa85.yaml diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index 4c6a321070..c3176fbc4a 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -501,6 +501,9 @@ keystone_ssh_port: "8023" kuryr_port: "23750" letsencrypt_webserver_port: "8081" +letsencrypt_managed_certs: "{{ '' if not enable_letsencrypt | bool else ('internal' if letsencrypt_internal_cert_server != '' and kolla_same_external_internal_vip | bool else ('internal,external' if letsencrypt_internal_cert_server != '' and letsencrypt_external_cert_server != '' else ('internal' if letsencrypt_internal_cert_server != '' else ('external' if letsencrypt_external_cert_server != '' and not kolla_same_external_internal_vip | bool else '')))) }}" +letsencrypt_external_cert_server: "" +letsencrypt_internal_cert_server: "" magnum_internal_fqdn: "{{ kolla_internal_fqdn }}" magnum_external_fqdn: "{{ kolla_external_fqdn }}" @@ -523,6 +526,7 @@ mariadb_wsrep_port: "4567" mariadb_ist_port: "4568" mariadb_sst_port: "4444" mariadb_clustercheck_port: "4569" +mariadb_enable_tls_backend: "{{ database_enable_tls_backend }}" mariadb_monitor_user: "{{ 'monitor' if enable_proxysql | bool else 'haproxy' }}" mariadb_monitor_connect_interval: "2000" diff --git a/ansible/roles/certificates/tasks/generate.yml b/ansible/roles/certificates/tasks/generate.yml index 511df27d0f..ec24316efa 100644 --- a/ansible/roles/certificates/tasks/generate.yml +++ b/ansible/roles/certificates/tasks/generate.yml @@ -59,16 +59,35 @@ path: "{{ external_dir }}/external.key" mode: "0660" state: file + when: + - letsencrypt_managed_certs == 'internal' or letsencrypt_managed_certs == '' or database_enable_tls_internal | bool + - kolla_enable_tls_external | bool or database_enable_tls_internal | bool - - name: Creating external Server PEM File - assemble: - regexp: \.(crt|key)$ - src: "{{ external_dir }}" - dest: "{{ kolla_external_fqdn_cert }}" +- name: Creating external Server PEM File + assemble: + regexp: \.(crt|key)$ + src: "{{ external_dir }}" + dest: "{{ kolla_external_fqdn_cert }}" + mode: "0660" + when: + - letsencrypt_managed_certs == 'internal' or letsencrypt_managed_certs == '' + - kolla_enable_tls_external | bool + +- block: + - name: Copy Certificate for ProxySQL + copy: + src: "{{ external_dir }}/external.crt" + dest: "{{ kolla_certificates_dir }}/proxysql-cert.pem" + mode: "0660" + + - name: Copy Key for ProxySQL + copy: + src: "{{ external_dir }}/external.key" + dest: "{{ kolla_certificates_dir }}/proxysql-key.pem" mode: "0660" when: - - not enable_letsencrypt | bool - - kolla_enable_tls_external | bool + - database_enable_tls_internal | bool + - kolla_same_external_internal_vip | bool - block: - name: Copy the external PEM file to be the internal when internal + external are same network @@ -78,7 +97,7 @@ remote_src: yes mode: "0660" when: - - not enable_letsencrypt | bool + - letsencrypt_managed_certs == 'external' or letsencrypt_managed_certs == '' - kolla_enable_tls_external | bool - kolla_enable_tls_internal | bool - kolla_same_external_internal_vip | bool @@ -131,26 +150,34 @@ path: "{{ internal_dir }}/internal.key" mode: "0660" state: file - - - name: Creating internal Server PEM File - assemble: - regexp: \.(crt|key)$ - src: "{{ internal_dir }}" - dest: "{{ kolla_internal_fqdn_cert }}" - mode: "0660" when: - - not enable_letsencrypt | bool + - letsencrypt_managed_certs == 'external' or letsencrypt_managed_certs == '' or database_enable_tls_internal | bool + - kolla_enable_tls_internal | bool or database_enable_tls_internal | bool + - not kolla_same_external_internal_vip | bool + +- name: Creating internal Server PEM File + assemble: + regexp: \.(crt|key)$ + src: "{{ internal_dir }}" + dest: "{{ kolla_internal_fqdn_cert }}" + mode: "0660" + when: + - letsencrypt_managed_certs == 'external' or letsencrypt_managed_certs == '' - kolla_enable_tls_internal | bool - not kolla_same_external_internal_vip | bool + - block: - - name: Copy Certificate and Key for ProxySQL + - name: Copy Certificate for ProxySQL copy: - src: "{{ external_dir if kolla_same_external_internal_vip | bool else internal_dir }}/{{ 'external' if kolla_same_external_internal_vip | bool else 'internal' }}.{{item}}" - dest: "{{ kolla_certificates_dir }}/proxysql-{{ 'cert' if item == 'crt' else item }}.pem" + src: "{{ internal_dir }}/internal.crt" + dest: "{{ kolla_certificates_dir }}/proxysql-cert.pem" + mode: "0660" + + - name: Copy Key for ProxySQL + copy: + src: "{{ internal_dir }}/internal.key" + dest: "{{ kolla_certificates_dir }}/proxysql-key.pem" mode: "0660" - with_items: - - "crt" - - "key" when: - database_enable_tls_internal | bool - - kolla_enable_tls_internal | bool + - not kolla_same_external_internal_vip | bool diff --git a/ansible/roles/certificates/tasks/main.yml b/ansible/roles/certificates/tasks/main.yml index eccd6d668d..e0aa890982 100644 --- a/ansible/roles/certificates/tasks/main.yml +++ b/ansible/roles/certificates/tasks/main.yml @@ -3,6 +3,6 @@ - include_tasks: generate.yml - include_tasks: generate-backend.yml when: - - kolla_enable_tls_backend | bool or rabbitmq_enable_tls | bool + - kolla_enable_tls_backend | bool or rabbitmq_enable_tls | bool or database_enable_tls_backend | bool - include_tasks: generate-libvirt.yml when: certificates_generate_libvirt | bool diff --git a/ansible/roles/letsencrypt/defaults/main.yml b/ansible/roles/letsencrypt/defaults/main.yml index bd2d5a3d06..c839b747b1 100644 --- a/ansible/roles/letsencrypt/defaults/main.yml +++ b/ansible/roles/letsencrypt/defaults/main.yml @@ -47,7 +47,6 @@ letsencrypt_webserver_default_volumes: - "kolla_logs:/var/log/kolla/" letsencrypt_webserver_extra_volumes: "{{ default_extra_volumes }}" -letsencrypt_cert_server: "https://acme-v02.api.letsencrypt.org/directory" # attempt to renew Let's Encrypt certificate every 4 hours letsencrypt_cron_renew_schedule: "0 */4 * * *" # The email used for certificate registration and recovery contact. Required. diff --git a/ansible/roles/letsencrypt/templates/crontab.j2 b/ansible/roles/letsencrypt/templates/crontab.j2 index 83209f5b46..521d19b9b7 100644 --- a/ansible/roles/letsencrypt/templates/crontab.j2 +++ b/ansible/roles/letsencrypt/templates/crontab.j2 @@ -1,8 +1,10 @@ PATH=/usr/local/bin:/usr/bin:/bin -{% if kolla_external_vip_address != kolla_internal_vip_address and kolla_external_fqdn != kolla_external_vip_address %} -{{ letsencrypt_cron_renew_schedule }} /usr/bin/letsencrypt-certificates --external --fqdns {% for fqdn in letsencrypt_external_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log +{% if 'external' in letsencrypt_managed_certs and kolla_external_fqdn != kolla_external_vip_address %} +# External Certificates +{{ letsencrypt_cron_renew_schedule }} /usr/bin/letsencrypt-certificates --external --fqdns {% for fqdn in letsencrypt_external_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_external_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log {% endif %} -{% if kolla_external_vip_address == kolla_internal_vip_address and kolla_internal_fqdn != kolla_internal_vip_address %} -{{ letsencrypt_cron_renew_schedule }} /usr/bin/letsencrypt-certificates --internal --fqdns {% for fqdn in letsencrypt_internal_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log +{% if 'internal' in letsencrypt_managed_certs and kolla_internal_fqdn != kolla_internal_vip_address %} +# Internal Certificates +{{ letsencrypt_cron_renew_schedule }} /usr/bin/letsencrypt-certificates --internal --fqdns {% for fqdn in letsencrypt_internal_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_internal_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log {% endif %} diff --git a/ansible/roles/letsencrypt/templates/letsencrypt-lego-run.sh.j2 b/ansible/roles/letsencrypt/templates/letsencrypt-lego-run.sh.j2 index 3f1282f80c..5c472f706b 100644 --- a/ansible/roles/letsencrypt/templates/letsencrypt-lego-run.sh.j2 +++ b/ansible/roles/letsencrypt/templates/letsencrypt-lego-run.sh.j2 @@ -2,11 +2,13 @@ {% set cron_cmd = 'cron -f' if kolla_base_distro in ['ubuntu', 'debian'] else 'crond -s -n' %} -{% if kolla_external_vip_address != kolla_internal_vip_address and kolla_external_fqdn != kolla_external_vip_address %} -/usr/bin/letsencrypt-certificates --external --fqdns {% for fqdn in letsencrypt_external_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log +{% if 'external' in letsencrypt_managed_certs and kolla_external_fqdn != kolla_external_vip_address %} +# External Certificates +/usr/bin/letsencrypt-certificates --external --fqdns {% for fqdn in letsencrypt_external_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_external_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log {% endif %} -{% if kolla_external_vip_address == kolla_internal_vip_address and kolla_internal_fqdn != kolla_internal_vip_address %} -/usr/bin/letsencrypt-certificates --internal --fqdns {% for fqdn in letsencrypt_internal_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log +{% if 'internal' in letsencrypt_managed_certs and kolla_internal_fqdn != kolla_internal_vip_address %} +# Internal Certificates +/usr/bin/letsencrypt-certificates --internal --fqdns {% for fqdn in letsencrypt_internal_fqdns %}{{ fqdn }}{% if not loop.last %},{% endif %}{% endfor %} --days {{ letsencrypt_cert_valid_days }} --port {{ letsencrypt_webserver_port }} --mail {{ letsencrypt_email }} --acme {{ letsencrypt_internal_cert_server }} --vips {% if not kolla_same_external_internal_vip %}{{ kolla_external_vip_address }},{% endif %}{{ kolla_internal_vip_address }} --haproxies-ssh {% for host in groups['loadbalancer'] %}{{ 'api' | kolla_address(host) | put_address_in_context('url') }}:{{ haproxy_ssh_port }}{% if not loop.last %},{% endif %}{% endfor %} 2>&1 | tee -a /var/log/kolla/letsencrypt/letsencrypt-lego.log {% endif %} {{ cron_cmd }} diff --git a/ansible/roles/loadbalancer/defaults/main.yml b/ansible/roles/loadbalancer/defaults/main.yml index bf6024511d..c081a1d033 100644 --- a/ansible/roles/loadbalancer/defaults/main.yml +++ b/ansible/roles/loadbalancer/defaults/main.yml @@ -200,3 +200,4 @@ haproxy_external_single_frontend_options: - "timeout client {{ haproxy_glance_api_client_timeout }}" haproxy_glance_api_client_timeout: "6h" +loadbalancer_copy_certs: "{{ kolla_copy_ca_into_containers | bool or kolla_enable_tls_external | bool or kolla_enable_tls_internal | bool or kolla_enable_tls_backend | bool or database_enable_tls_internal | bool or database_enable_tls_backend | bool }}" diff --git a/ansible/roles/loadbalancer/tasks/config.yml b/ansible/roles/loadbalancer/tasks/config.yml index b5488b306c..e240555474 100644 --- a/ansible/roles/loadbalancer/tasks/config.yml +++ b/ansible/roles/loadbalancer/tasks/config.yml @@ -184,43 +184,9 @@ notify: - Restart keepalived container -- name: Copying over haproxy.pem - vars: - service: "{{ loadbalancer_services['haproxy'] }}" - copy: - src: "{{ kolla_external_fqdn_cert }}" - dest: "{{ node_config_directory }}/haproxy/{{ item }}" - mode: "0660" - become: true - when: - - not enable_letsencrypt | bool - - kolla_enable_tls_external | bool - - not kolla_externally_managed_cert | bool - - service | service_enabled_and_mapped_to_host - with_items: - - "haproxy.pem" - notify: - - Restart haproxy container - -- name: Copying over haproxy-internal.pem - vars: - service: "{{ loadbalancer_services['haproxy'] }}" - copy: - src: "{{ kolla_internal_fqdn_cert }}" - dest: "{{ node_config_directory }}/haproxy/{{ item }}" - mode: "0660" - become: true - when: - - not enable_letsencrypt | bool - - kolla_enable_tls_internal | bool - - not kolla_externally_managed_cert | bool - - service | service_enabled_and_mapped_to_host - with_items: - - "haproxy-internal.pem" - notify: - - Restart haproxy container - - include_tasks: copy-certs.yml + when: + - loadbalancer_copy_certs - name: Copying over haproxy start script vars: diff --git a/ansible/roles/loadbalancer/tasks/copy-certs.yml b/ansible/roles/loadbalancer/tasks/copy-certs.yml index 95cd80afda..b158978dc2 100644 --- a/ansible/roles/loadbalancer/tasks/copy-certs.yml +++ b/ansible/roles/loadbalancer/tasks/copy-certs.yml @@ -1,25 +1,71 @@ --- +- name: Copying over haproxy.pem + vars: + service: "{{ loadbalancer_services['haproxy'] }}" + copy: + src: "{{ kolla_external_fqdn_cert }}" + dest: "{{ node_config_directory }}/haproxy/{{ item }}" + mode: "0660" + become: true + when: + - letsencrypt_managed_certs == 'internal' or letsencrypt_managed_certs == '' + - kolla_enable_tls_external | bool + - not kolla_externally_managed_cert | bool + - service | service_enabled_and_mapped_to_host + with_items: + - "haproxy.pem" + notify: + - Restart haproxy container + +- name: Copying over haproxy-internal.pem + vars: + service: "{{ loadbalancer_services['haproxy'] }}" + copy: + src: "{{ kolla_internal_fqdn_cert }}" + dest: "{{ node_config_directory }}/haproxy/{{ item }}" + mode: "0660" + become: true + when: + - letsencrypt_managed_certs == 'external' or letsencrypt_managed_certs == '' + - kolla_enable_tls_internal | bool + - not kolla_externally_managed_cert | bool + - service | service_enabled_and_mapped_to_host + with_items: + - "haproxy-internal.pem" + notify: + - Restart haproxy container + +- name: Copying over proxysql-cert.pem + vars: + service: "{{ loadbalancer_services['proxysql'] }}" + copy: + src: "{{ kolla_certificates_dir }}/proxysql-cert.pem" + dest: "{{ node_config_directory }}/proxysql/proxysql-cert.pem" + mode: "0660" + become: true + when: + - database_enable_tls_internal | bool + - service | service_enabled_and_mapped_to_host + notify: + - Restart proxysql container + +- name: Copying over proxysql-key.pem + vars: + service: "{{ loadbalancer_services['proxysql'] }}" + copy: + src: "{{ kolla_certificates_dir }}/proxysql-key.pem" + dest: "{{ node_config_directory }}/proxysql/proxysql-key.pem" + mode: "0660" + become: true + when: + - database_enable_tls_internal | bool + - service | service_enabled_and_mapped_to_host + notify: + - Restart proxysql container + - name: "Copy certificates and keys for {{ project_name }}" - import_role: - role: service-cert-copy - vars: - project_services: "{{ loadbalancer_services }}" - when: - - kolla_copy_ca_into_containers | bool - -- name: "Copy certificates and keys for MariaDB " import_role: role: service-cert-copy vars: project_services: "{{ loadbalancer_services }}" project_name: mariadb - when: database_enable_tls_backend | bool - - -- name: "Copy certificates and keys for Proxysql" - import_role: - role: service-cert-copy - vars: - project_services: "{{ loadbalancer_services }}" - project_name: "proxysql" - when: database_enable_tls_internal | bool diff --git a/ansible/roles/loadbalancer/tasks/precheck.yml b/ansible/roles/loadbalancer/tasks/precheck.yml index e29b5ef2f4..b499c086bb 100644 --- a/ansible/roles/loadbalancer/tasks/precheck.yml +++ b/ansible/roles/loadbalancer/tasks/precheck.yml @@ -55,48 +55,42 @@ haproxy_vip_prechecks: "{{ all_hosts_in_batch and groups['haproxy_running_True'] is not defined }}" proxysql_vip_prechecks: "{{ all_hosts_in_batch and groups['proxysql_running_True'] is not defined }}" -- name: Checking if external haproxy certificate exists - run_once: true - stat: - path: "{{ kolla_external_fqdn_cert }}" - delegate_to: localhost - register: haproxy_cert_file - changed_when: false +- block: + - name: Checking if external haproxy certificate exists + run_once: true + stat: + path: "{{ kolla_external_fqdn_cert }}" + delegate_to: localhost + register: haproxy_cert_file + changed_when: false + + - name: Assert that external haproxy certificate exists + run_once: true + assert: + that: haproxy_cert_file.stat.exists + fail_msg: "External haproxy certificate file is not found. It is configured via 'kolla_external_fqdn_cert'" when: - not kolla_externally_managed_cert | bool - - not enable_letsencrypt | bool + - letsencrypt_managed_certs == 'internal' or letsencrypt_managed_certs == '' - kolla_enable_tls_external | bool -- name: Assert that external haproxy certificate exists - run_once: true - assert: - that: haproxy_cert_file.stat.exists - fail_msg: "External haproxy certificate file is not found. It is configured via 'kolla_external_fqdn_cert'" - when: - - not kolla_externally_managed_cert | bool - - not enable_letsencrypt | bool - - kolla_enable_tls_external | bool +- block: + - name: Checking if internal haproxy certificate exists + run_once: true + stat: + path: "{{ kolla_internal_fqdn_cert }}" + delegate_to: localhost + register: haproxy_internal_cert_file + changed_when: false -- name: Checking if internal haproxy certificate exists - run_once: true - stat: - path: "{{ kolla_internal_fqdn_cert }}" - delegate_to: localhost - register: haproxy_internal_cert_file - changed_when: false + - name: Assert that internal haproxy certificate exists + run_once: true + assert: + that: haproxy_internal_cert_file.stat.exists + fail_msg: "Internal haproxy certificate file is not found. It is configured via 'kolla_internal_fqdn_cert'" when: - not kolla_externally_managed_cert | bool - - not enable_letsencrypt | bool - - kolla_enable_tls_internal | bool - -- name: Assert that internal haproxy certificate exists - run_once: true - assert: - that: haproxy_internal_cert_file.stat.exists - fail_msg: "Internal haproxy certificate file is not found. It is configured via 'kolla_internal_fqdn_cert'" - when: - - not kolla_externally_managed_cert | bool - - not enable_letsencrypt | bool + - letsencrypt_managed_certs == 'external' or letsencrypt_managed_certs == '' - kolla_enable_tls_internal | bool - name: Checking the kolla_external_vip_interface is present diff --git a/ansible/roles/loadbalancer/templates/haproxy/haproxy.json.j2 b/ansible/roles/loadbalancer/templates/haproxy/haproxy.json.j2 index adc7e343a8..5cc97e6637 100644 --- a/ansible/roles/loadbalancer/templates/haproxy/haproxy.json.j2 +++ b/ansible/roles/loadbalancer/templates/haproxy/haproxy.json.j2 @@ -18,22 +18,21 @@ "dest": "/etc/haproxy/services.d", "owner": "root", "perm": "0700" - }{% if kolla_enable_tls_external | bool and not enable_letsencrypt | bool %}, + }{% if kolla_enable_tls_external | bool %}, { "source": "{{ container_config_directory }}/external-frontend-map", "dest": "/etc/haproxy/external-frontend-map", "owner": "root", "perm": "0600", "optional": {{ (not haproxy_single_external_frontend | bool) | string | lower }} - }, + }{% endif %}{% if kolla_enable_tls_external and letsencrypt_managed_certs == 'internal' or letsencrypt_managed_certs == '' %}, { "source": "{{ container_config_directory }}/haproxy.pem", "dest": "/etc/haproxy/certificates/haproxy.pem", "owner": "haproxy", "perm": "0600", "optional": {{ (not kolla_enable_tls_external | bool) | string | lower }} - }{% endif %} - {% if kolla_enable_tls_internal | bool and not enable_letsencrypt | bool %}, + }{% endif %}{% if kolla_enable_tls_internal | bool and letsencrypt_managed_certs == 'external' or letsencrypt_managed_certs == '' %}, { "source": "{{ container_config_directory }}/haproxy-internal.pem", "dest": "/etc/haproxy/certificates/haproxy-internal.pem", diff --git a/ansible/roles/rabbitmq/defaults/main.yml b/ansible/roles/rabbitmq/defaults/main.yml index 37b015c7dd..71d92d7424 100644 --- a/ansible/roles/rabbitmq/defaults/main.yml +++ b/ansible/roles/rabbitmq/defaults/main.yml @@ -100,3 +100,8 @@ rabbitmq_enabled_plugins: "{{ rabbitmq_plugins | selectattr('enabled', 'equalto' kolla_externally_managed_cert: False rabbitmq_version_suffix: "" + +#################### +# TLS +#################### +rabbitmq_enable_tls_backend: "{{ rabbitmq_enable_tls }}" diff --git a/ansible/roles/service-cert-copy/defaults/main.yml b/ansible/roles/service-cert-copy/defaults/main.yml index 0238b3c8f4..24b97c760a 100644 --- a/ansible/roles/service-cert-copy/defaults/main.yml +++ b/ansible/roles/service-cert-copy/defaults/main.yml @@ -1,3 +1,4 @@ --- kolla_externally_managed_cert: False +kolla_copy_backend_tls_files: "{{ lookup('vars', (kolla_role_name | default(project_name)) + '_enable_tls_backend', default=false) }}" diff --git a/ansible/roles/service-cert-copy/tasks/main.yml b/ansible/roles/service-cert-copy/tasks/main.yml index 9b37fc92ee..9ae11a22d3 100644 --- a/ansible/roles/service-cert-copy/tasks/main.yml +++ b/ansible/roles/service-cert-copy/tasks/main.yml @@ -25,7 +25,7 @@ mode: "0644" become: true when: - - kolla_enable_tls_backend | bool + - kolla_copy_backend_tls_files | bool with_dict: "{{ project_services | select_services_enabled_and_mapped_to_host }}" notify: - "Restart {{ item.key }} container" @@ -44,7 +44,7 @@ mode: "0600" become: true when: - - kolla_enable_tls_backend | bool + - kolla_copy_backend_tls_files | bool with_dict: "{{ project_services | select_services_enabled_and_mapped_to_host }}" notify: - "Restart {{ item.key }} container" diff --git a/doc/source/admin/tls.rst b/doc/source/admin/tls.rst index d662d6c2e7..5a42d00489 100644 --- a/doc/source/admin/tls.rst +++ b/doc/source/admin/tls.rst @@ -317,6 +317,21 @@ to the HAProxy containers using SSH. admin access level. This is needed so Let's Encrypt can interact with HAProxy. +You can configure separate ACME servers for internal and external +certificate requests. + +.. code-block:: yaml + + letsencrypt_external_cert_server: "" + letsencrypt_internal_cert_server: "" + +.. note:: + + The ``letsencrypt_external_cert_server`` has a default value of + ``https://acme-v02.api.letsencrypt.org/directory``. Ensure that + ``letsencrypt_internal_cert_server`` is reachable from the controller + if you configure it for internal certificate requests. + Generating a Private Certificate Authority ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/releasenotes/notes/bug-2076331-f4ef64ad0a12aa85.yaml b/releasenotes/notes/bug-2076331-f4ef64ad0a12aa85.yaml new file mode 100644 index 0000000000..70523df363 --- /dev/null +++ b/releasenotes/notes/bug-2076331-f4ef64ad0a12aa85.yaml @@ -0,0 +1,21 @@ +--- +features: + - | + Adds new variables to be used by the letsencrypt role, + ``letsencrypt_external_cert_server`` and + ``letsencrypt_internal_cert_server``, It allows to + configure ACME server for internal, external + certificate generation. +upgrade: + - | + Users who have previously used the letsencrypt role for an + external certificate generation need to migrate their previous + default value (or their overridden value) of the variable + ``letsencrypt_cert_server`` and set it to + ``letsencrypt_external_cert_server``.The default value was + ``https://acme-v02.api.letsencrypt.org/directory`` +fixes: + - | + Fixes copying of custom certificates when Let's encrypt + is turned on. `LP#2076331 + `__ diff --git a/tests/templates/globals-default.j2 b/tests/templates/globals-default.j2 index 3fc1a447a1..bdafb7a6bc 100644 --- a/tests/templates/globals-default.j2 +++ b/tests/templates/globals-default.j2 @@ -242,13 +242,14 @@ placement_external_fqdn: "placement.external" {% endif %} {% if scenario == "lets-encrypt" %} +enable_horizon: "yes" enable_letsencrypt: "yes" -rabbitmq_enable_tls: "yes" letsencrypt_email: "usero@openstack.test" -letsencrypt_cert_server: "https://pebble:14000/dir" +letsencrypt_internal_cert_server: "https://pebble:14000/dir" kolla_internal_fqdn: "{{ kolla_internal_fqdn }}" -kolla_enable_tls_backend: "no" kolla_admin_openrc_cacert: "{% raw %}{{ kolla_certificates_dir }}{% endraw %}/ca/pebble.crt" +database_enable_tls_internal: "yes" +database_enable_tls_backend: "yes" {% endif %} {% if scenario == "skyline" %}