5581a28253
Add support for automatic provisioning and renewal of HTTPS certificates via LetsEncrypt. Spec is available at: https://etherpad.opendev.org/p/kolla-ansible-letsencrypt-https Depends-On: https://review.opendev.org/c/openstack/kolla/+/887347 Co-Authored-By: Michal Arbet <michal.arbet@ultimum.io> Implements: blueprint letsencrypt-https Change-Id: I35317ea0343f0db74ddc0e587862e95408e9e106
162 lines
8.2 KiB
Django/Jinja
162 lines
8.2 KiB
Django/Jinja
#jinja2: lstrip_blocks: True
|
|
{%- set external_tls_bind_info = 'ssl crt /etc/haproxy/certificates/haproxy.pem' if kolla_enable_tls_external|bool else '' %}
|
|
{%- set external_tls_bind_info = "%s %s" % (external_tls_bind_info, haproxy_http2_protocol) if kolla_enable_tls_external|bool and haproxy_enable_http2|bool else external_tls_bind_info %}
|
|
{%- set internal_tls_bind_info = 'ssl crt /etc/haproxy/certificates/haproxy-internal.pem' if kolla_enable_tls_internal|bool else '' %}
|
|
{%- set internal_tls_bind_info = "%s %s" % (internal_tls_bind_info, haproxy_http2_protocol) if kolla_enable_tls_internal|bool and haproxy_enable_http2|bool else internal_tls_bind_info %}
|
|
|
|
{%- macro userlist_macro(service_name, auth_user, auth_pass) %}
|
|
userlist {{ service_name }}-user
|
|
user {{ auth_user }} insecure-password {{ auth_pass }}
|
|
{% endmacro %}
|
|
|
|
{%- macro frontend_macro(service_name, service_port, service_mode, external,
|
|
frontend_http_extra, frontend_redirect_extra, frontend_tcp_extra) %}
|
|
frontend {{ service_name }}_front
|
|
{% if service_mode == 'redirect' %}
|
|
mode http
|
|
{% else %}
|
|
mode {{ service_mode }}
|
|
{% endif %}
|
|
{% if service_mode == 'http' %}
|
|
{% if external|bool %}
|
|
http-request deny if { path -i -m beg /server-status }
|
|
{% endif %}
|
|
{# Delete any pre-populated XFP header #}
|
|
http-request del-header X-Forwarded-Proto
|
|
{% for http_option in frontend_http_extra %}
|
|
{{ http_option }}
|
|
{% endfor %}
|
|
{% elif service_mode == 'tcp' %}
|
|
{% for tcp_option in frontend_tcp_extra %}
|
|
{{ tcp_option }}
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% set tls_option = '' %}
|
|
{% if external|bool %}
|
|
{% set vip_address = kolla_external_vip_address %}
|
|
{% if service_mode == 'http' %}
|
|
{% set tls_option = external_tls_bind_info %}
|
|
{# Replace the XFP header for external https requests #}
|
|
http-request set-header X-Forwarded-Proto https if { ssl_fc }
|
|
{% endif %}
|
|
{% else %}
|
|
{% set vip_address = kolla_internal_vip_address %}
|
|
{% if service_mode == 'http' %}
|
|
{% set tls_option = internal_tls_bind_info %}
|
|
{# Replace the XFP header for internal https requests #}
|
|
http-request set-header X-Forwarded-Proto https if { ssl_fc }
|
|
{% endif %}
|
|
{% endif %}
|
|
{{ "bind %s:%s %s"|e|format(vip_address, service_port, tls_option)|trim() }}
|
|
{# Redirect mode sets a redirect scheme instead of a backend #}
|
|
{% if service_mode == 'redirect' %}
|
|
redirect scheme https code 301 if !{ ssl_fc } !{ path_reg ^/.well-known/acme-challenge/.+ }
|
|
{% for redirect_option in frontend_redirect_extra %}
|
|
{{ redirect_option }}
|
|
{% endfor %}
|
|
{% else %}
|
|
default_backend {{ service_name }}_back
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{%- macro backend_macro(service_name, listen_port, service_mode, host_group,
|
|
active_passive, custom_member_list, backend_http_extra,
|
|
backend_tcp_extra, auth_user, auth_pass, tls_backend) %}
|
|
backend {{ service_name }}_back
|
|
{% if service_mode == 'redirect' %}
|
|
mode http
|
|
{% else %}
|
|
mode {{ service_mode }}
|
|
{% endif %}
|
|
{% if service_mode == 'http' %}
|
|
{# Set up auth if required #}
|
|
{% if auth_user and auth_pass %}
|
|
acl auth_acl http_auth({{ service_name }}-user)
|
|
http-request auth realm basicauth unless auth_acl
|
|
{% endif %}
|
|
{% for http_option in backend_http_extra %}
|
|
{{ http_option }}
|
|
{% endfor %}
|
|
{% elif service_mode == 'tcp' %}
|
|
{% for tcp_option in backend_tcp_extra %}
|
|
{{ tcp_option }}
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% if custom_member_list is not none %}
|
|
{% for custom_member in custom_member_list %}
|
|
{{ custom_member }}
|
|
{% endfor %}
|
|
{% else %}
|
|
{% set backend_tls_info = '' %}
|
|
{% if tls_backend|bool %}
|
|
{% set haproxy_health_check_final = haproxy_health_check_ssl %}
|
|
{% if kolla_verify_tls_backend|bool %}
|
|
{% set backend_tls_info = 'ssl verify required ca-file %s'|format(haproxy_backend_cacert) %}
|
|
{% else %}
|
|
{% set backend_tls_info = 'ssl verify none' %}
|
|
{% endif %}
|
|
{% else %}
|
|
{% set haproxy_health_check_final = haproxy_health_check %}
|
|
{% endif %}
|
|
{% for host in groups[host_group] %}
|
|
{% set host_name = hostvars[host].ansible_facts.hostname %}
|
|
{% set host_ip = 'api' | kolla_address(host) %}
|
|
{% set service_weight = 'haproxy_' + service_name + '_weight' %}
|
|
{% set backend_weight_info = '' %}
|
|
{% if hostvars[host][service_weight] is defined and hostvars[host][service_weight] | int != 0 and hostvars[host][service_weight] | int <= 256 %}
|
|
{% set backend_weight_info = 'weight %s'|format(hostvars[host][service_weight]) %}
|
|
{% endif %}
|
|
server {{ host_name }} {{ host_ip }}:{{ listen_port }} {{ haproxy_health_check_final }}{% if active_passive and not loop.first %} backup{% endif %} {{ backend_tls_info }} {{ backend_weight_info }}
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endmacro %}
|
|
|
|
{%- set haproxy = service.haproxy|default({}) %}
|
|
{%- for haproxy_name, haproxy_service in haproxy.items() %}
|
|
{# External defaults to false #}
|
|
{% set external = haproxy_service.external|default(false)|bool %}
|
|
{# Active/passive defaults to false #}
|
|
{% set active_passive = haproxy_service.active_passive|default(false)|bool %}
|
|
{# Skip anything that is external when the external vip is not enabled #}
|
|
{% if haproxy_service.enabled|bool and (not external or haproxy_enable_external_vip|bool)%}
|
|
{# Here we define variables and their defaults #}
|
|
{# services can be listening on a different port than haproxy #}
|
|
{% set listen_port = haproxy_service.listen_port|default(haproxy_service.port) %}
|
|
{# Custom member list can use jinja to generate a semicolon separated list #}
|
|
{% set custom_member_list = haproxy_service.custom_member_list|default(none) %}
|
|
{# Mode defaults to http #}
|
|
{% set mode = haproxy_service.mode|default('http') %}
|
|
{# By default each service has its own frontend (hence with_frontend is true by default) #}
|
|
{% set with_frontend = haproxy_service.with_frontend|default(true)|bool %}
|
|
{# By default each service has its own backend (hence with_backend is true by default) #}
|
|
{% set with_backend = haproxy_service.with_backend|default(true)|bool %}
|
|
{# Use the parent host group but allow it to be overridden #}
|
|
{% set host_group = haproxy_service.host_group|default(service.group) %}
|
|
{# Additional options can be defined in config, and are additive to the global extras #}
|
|
{% set frontend_tcp_extra = haproxy_service.frontend_tcp_extra|default([]) + haproxy_frontend_tcp_extra %}
|
|
{% set backend_tcp_extra = haproxy_service.backend_tcp_extra|default([]) %}
|
|
{% set frontend_http_extra = haproxy_service.frontend_http_extra|default([]) + haproxy_frontend_http_extra %}
|
|
{% set frontend_redirect_extra = haproxy_service.frontend_redirect_extra|default([]) + haproxy_frontend_redirect_extra %}
|
|
{% set backend_http_extra = haproxy_service.backend_http_extra|default([]) %}
|
|
{% set tls_backend = haproxy_service.tls_backend|default(false) %}
|
|
{# Allow for basic auth #}
|
|
{% set auth_user = haproxy_service.auth_user|default() %}
|
|
{% set auth_pass = haproxy_service.auth_pass|default() %}
|
|
{% if auth_user and auth_pass %}
|
|
{{ userlist_macro(haproxy_name, auth_user, auth_pass) }}
|
|
{% endif %}
|
|
{% if with_frontend %}
|
|
{% if not (external|bool and haproxy_single_external_frontend|bool and mode == 'http') %}
|
|
{{ frontend_macro(haproxy_name, haproxy_service.port, mode, external,
|
|
frontend_http_extra, frontend_redirect_extra, frontend_tcp_extra) }}
|
|
{% endif %}
|
|
{% endif %}
|
|
{# Redirect (to https) is a special case, as it does not include a backend #}
|
|
{% if with_backend and mode != 'redirect' %}
|
|
{{ backend_macro(haproxy_name, listen_port, mode, host_group, active_passive,
|
|
custom_member_list, backend_http_extra, backend_tcp_extra,
|
|
auth_user, auth_pass, tls_backend) }}
|
|
{% endif %}
|
|
{% endif %}
|
|
{%- endfor -%}
|