diff --git a/doc/source/install-guide/configure-haproxy.rst b/doc/source/install-guide/configure-haproxy.rst index 9d79b9e8b7..45a55b2e9d 100644 --- a/doc/source/install-guide/configure-haproxy.rst +++ b/doc/source/install-guide/configure-haproxy.rst @@ -3,10 +3,11 @@ Configuring HAProxy (optional) ------------------------------ -HAProxy provides load balancing for high availability architectures deployed by -OpenStack-Ansible. The default HAProxy configuration provides highly-available -load balancing services via keepalived if there are more than one hosts in the -``haproxy_hosts`` group. +HAProxy provides load balancing services and SSL termination when hardware +load balancers are not available for high availability architectures deployed +by OpenStack-Ansible. The default HAProxy configuration provides highly- +available load balancing services via keepalived if there is more than one +host in the ``haproxy_hosts`` group. .. note:: diff --git a/playbooks/haproxy-install.yml b/playbooks/haproxy-install.yml index 1f88bba12b..d838c8c940 100644 --- a/playbooks/haproxy-install.yml +++ b/playbooks/haproxy-install.yml @@ -97,20 +97,9 @@ tags: - haproxy-service-config roles: - - { role: "haproxy_server", tags: [ "haproxy-server" ] } - - role: haproxy_server - haproxy_service_configs: - - service: - haproxy_service_name: keystone_internal - haproxy_backend_nodes: "{{ groups['keystone_all'] }}" - haproxy_bind: "{{ internal_lb_vip_address }}" - haproxy_port: 5000 - haproxy_ssl: "{% if haproxy_ssl | bool and keystone_service_internaluri_proto == 'https' %}true{% else %}false{% endif %}" - haproxy_balance_type: "{{ (keystone_ssl_internal | bool) | ternary('tcp','http') }}" - haproxy_balance_alg: "{{ (keystone_ssl_internal | bool) | ternary('source', 'leastconn') }}" - haproxy_backend_options: "{{ (keystone_ssl_internal | bool) | ternary(haproxy_backend_options_https, haproxy_backend_options_http) }}" - when: internal_lb_vip_address != external_lb_vip_address - + - role: "haproxy_server" + tags: + - "haproxy-server" - role: "rsyslog_client" rsyslog_client_log_rotate_file: haproxy_log_rotate rsyslog_client_log_dir: "/var/log/haproxy" diff --git a/playbooks/inventory/group_vars/hosts.yml b/playbooks/inventory/group_vars/hosts.yml index 9657a6d942..8b60aea1a6 100644 --- a/playbooks/inventory/group_vars/hosts.yml +++ b/playbooks/inventory/group_vars/hosts.yml @@ -38,6 +38,11 @@ rsyslog_server_storage_directory: /var/log/log-storage openstack_repo_url: "http://{{ internal_lb_vip_address }}:{{ repo_server_port }}" openstack_repo_git_url: "http://{{ internal_lb_vip_address }}:{{ repo_server_port }}/openstackgit" +## Enable external SSL handling for general OpenStack services +openstack_external_ssl: true +nova_external_ssl: "{{ openstack_external_ssl }}" +keystone_external_ssl: "{{ openstack_external_ssl }}" +horizon_external_ssl: "{{ openstack_external_ssl }}" ## LXC options lxc_container_domain: "openstack.local" @@ -97,7 +102,7 @@ ssl_protocol: "ALL -SSLv2 -SSLv3" ssl_cipher_suite: "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS" ## OpenStack global Endpoint Protos -#openstack_service_publicuri_proto: http +openstack_service_publicuri_proto: https #openstack_service_adminuri_proto: http #openstack_service_internaluri_proto: http @@ -114,6 +119,8 @@ aodh_db_ip: localhost aodh_db_port: 27017 aodh_connection_string: "{{ aodh_db_type }}://{{ aodh_database_user }}:{{ aodh_container_db_password }}@{{ aodh_db_ip }}:{{ aodh_db_port }}/{{ aodh_database_name }}" aodh_service_in_ldap: "{{ service_ldap_backend_enabled }}" +aodh_service_proto: http +aodh_service_publicuri: "{{ openstack_service_publicuri_proto|default(aodh_service_proto) }}://{{ external_lb_vip_address }}:{{ aodh_service_port }}" ## Ceilometer @@ -121,6 +128,7 @@ ceilometer_service_port: 8777 ceilometer_service_proto: http ceilometer_service_user_name: ceilometer ceilometer_service_tenant_name: service +ceilometer_service_publicuri: "{{ openstack_service_publicuri_proto|default(ceilometer_service_proto) }}://{{ external_lb_vip_address }}:{{ ceilometer_service_port }}" ceilometer_service_adminuri: "{{ ceilometer_service_proto }}://{{ internal_lb_vip_address }}:{{ ceilometer_service_port }}" ceilometer_service_adminurl: "{{ ceilometer_service_adminuri }}/" ceilometer_service_region: "{{ service_region }}" @@ -132,6 +140,7 @@ ceilometer_service_in_ldap: "{{ service_ldap_backend_enabled }}" ## Nova nova_service_port: 8774 nova_service_proto: http +nova_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(nova_service_proto) }}" nova_service_adminuri_proto: "{{ openstack_service_adminuri_proto | default(nova_service_proto) }}" nova_service_user_name: nova nova_service_project_name: service @@ -154,6 +163,7 @@ nova_glance_api_servers: "{{ glance_api_servers }}" ## Neutron neutron_service_port: 9696 neutron_service_proto: http +neutron_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(neutron_service_proto) }}" neutron_service_adminuri_proto: "{{ openstack_service_adminuri_proto | default(neutron_service_proto) }}" neutron_service_user_name: neutron neutron_service_project_name: service @@ -171,6 +181,7 @@ neutron_rabbitmq_vhost: /neutron ## Glance glance_service_port: 9292 glance_service_proto: http +glance_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(glance_service_proto) }}" glance_service_adminuri_proto: "{{ openstack_service_adminuri_proto | default(glance_service_proto) }}" glance_service_user_name: glance glance_service_project_name: service @@ -190,9 +201,9 @@ keystone_admin_tenant_name: admin keystone_admin_port: 35357 keystone_service_port: 5000 keystone_service_proto: http +keystone_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(keystone_service_proto) }}" keystone_service_adminuri_proto: "{{ openstack_service_adminuri_proto | default(keystone_service_proto) }}" keystone_service_internaluri_proto: "{{ openstack_service_internaluri_proto | default(keystone_service_proto) }}" -keystone_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(keystone_service_proto) }}" keystone_service_user_name: keystone keystone_service_tenant_name: service keystone_service_region: "{{ service_region }}" @@ -232,6 +243,7 @@ heat_service_region: "{{ service_region }}" heat_service_in_ldap: "{{ service_ldap_backend_enabled }}" heat_rabbitmq_userid: heat heat_rabbitmq_vhost: /heat +heat_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(heat_service_proto) }}" ## Cinder @@ -258,6 +270,7 @@ cinder_rabbitmq_userid: cinder cinder_rabbitmq_vhost: /cinder cinder_glance_api_servers: "{{ glance_api_servers }}" cinder_glance_api_version: "{{ (cinder_backends_rbd_inuse|bool and glance_default_store == 'rbd') | ternary('2','1') }}" +cinder_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(cinder_service_proto) }}" ## Swift @@ -270,6 +283,7 @@ swift_service_region: "{{ service_region }}" swift_service_in_ldap: "{{ service_ldap_backend_enabled }}" swift_rabbitmq_userid: swift swift_rabbitmq_vhost: /swift +swift_service_publicuri_proto: "{{ openstack_service_publicuri_proto | default(swift_service_proto) }}" ## Ironic diff --git a/playbooks/roles/haproxy_server/defaults/main.yml b/playbooks/roles/haproxy_server/defaults/main.yml index e771157ef5..749dc05dab 100644 --- a/playbooks/roles/haproxy_server/defaults/main.yml +++ b/playbooks/roles/haproxy_server/defaults/main.yml @@ -75,12 +75,12 @@ galera_monitoring_user: monitoring haproxy_bind_on_non_local: False ## haproxy SSL -haproxy_ssl: no +haproxy_ssl: true haproxy_ssl_dh_param: 2048 haproxy_ssl_self_signed_regen: no haproxy_ssl_cert: /etc/ssl/certs/haproxy.cert haproxy_ssl_key: /etc/ssl/private/haproxy.key haproxy_ssl_pem: /etc/ssl/private/haproxy.pem haproxy_ssl_ca_cert: /etc/ssl/certs/haproxy-ca.pem -haproxy_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ internal_lb_vip_address }}/subjectAltName=IP.1={{ external_lb_vip_address }}" +haproxy_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ external_lb_vip_address }}/subjectAltName=IP.1={{ external_lb_vip_address }}" haproxy_ssl_cipher_suite: "{{ ssl_cipher_suite }}" diff --git a/playbooks/roles/haproxy_server/tasks/haproxy_service_config.yml b/playbooks/roles/haproxy_server/tasks/haproxy_service_config.yml index c0c8e7f338..204183853f 100644 --- a/playbooks/roles/haproxy_server/tasks/haproxy_service_config.yml +++ b/playbooks/roles/haproxy_server/tasks/haproxy_service_config.yml @@ -18,6 +18,11 @@ src: service.j2 dest: "/etc/haproxy/conf.d/{{ item.service.haproxy_service_name }}" with_items: haproxy_service_configs + when: > + (item.service.haproxy_backend_nodes is defined and + item.service.haproxy_backend_nodes | length > 0) or + (item.service.haproxy_backup_nodes is defined and + item.service.haproxy_backup_nodes | length > 0) notify: Restart haproxy tags: - haproxy-service-config diff --git a/playbooks/roles/haproxy_server/templates/service.j2 b/playbooks/roles/haproxy_server/templates/service.j2 index 46da61c2d5..86e5e3d542 100644 --- a/playbooks/roles/haproxy_server/templates/service.j2 +++ b/playbooks/roles/haproxy_server/templates/service.j2 @@ -1,56 +1,116 @@ # {{ ansible_managed }} -frontend {{ item.service.haproxy_service_name }}-front -bind {{ item.service.haproxy_bind|default('*') }}:{{ item.service.haproxy_port }} {% if item.service.haproxy_ssl is defined and item.service.haproxy_ssl | bool %}ssl crt {{ haproxy_ssl_pem }} ciphers {{ haproxy_ssl_cipher_suite }}{% endif %} - -{% if item.service.haproxy_balance_type == "http" %} - option httplog - option forwardfor except 127.0.0.0/8 - option http-server-close - - {%- set request_option = "http" %} -{% else %} - option tcplog - {%- set request_option = "tcp" %} -{% endif %} - -{% if item.service.haproxy_ssl is defined and item.service.haproxy_ssl | bool %} - reqadd X-Forwarded-Proto:\ https -{% endif %} - -{% if item.service.haproxy_timeout_client is defined %} - timeout client {{ item.service.haproxy_timeout_client }} -{% endif %} - -{% if item.service.haproxy_whitelist_hosts is defined and item.service.haproxy_whitelist_hosts == true %} - acl white_list src 127.0.0.1/8 10.0.3.0/24 {{ container_cidr }} - - {{ request_option }}-request content accept if white_list - {{ request_option }}-request content reject -{% endif %} - - mode {{ item.service.haproxy_balance_type }} - default_backend {{ item.service.haproxy_service_name }}-back - - +{% set request_option = item.service.haproxy_balance_type | default("http") -%} {% if item.service.haproxy_backend_port is not defined %} {% set haproxy_backend_port = item.service.haproxy_port %} {% else %} {% set haproxy_backend_port = item.service.haproxy_backend_port %} +{% endif -%} + +{% set vip_binds = [external_lb_vip_address] -%} +{%- if internal_lb_vip_address not in vip_binds %} + {% set _ = vip_binds.append(internal_lb_vip_address) %} +{% endif -%} + +{%- if extra_lb_vip_addresses is defined %} +{% for vip_address in extra_lb_vip_addresses %} + {% set _ = vip_binds.append(vip_address) %} +{% endfor %} +{% endif -%} + +{%- if item.service.haproxy_bind is defined %} + {% if item.service.haproxy_bind not in vip_binds %} + {% set _ = vip_binds.append(item.service.haproxy_bind) %} + {% endif %} +{% endif -%} + +{% for vip_bind in vip_binds %} +{% if item.service.haproxy_redirect_http_port is defined %} +{% if (loop.index == 1 or item.service.haproxy_ssl_all_vips | default(false) | bool) %} + +frontend {{ item.service.haproxy_service_name }}-redirect-front-{{ loop.index }} +bind {{ vip_bind }}:{{ item.service.haproxy_redirect_http_port }} + mode http + redirect scheme https if !{ ssl_fc } {% endif %} +{% endif %} + +frontend {{ item.service.haproxy_service_name }}-front-{{ loop.index }} + bind {{ vip_bind }}:{{ item.service.haproxy_port }} {% if (item.service.haproxy_ssl | default(false) | bool) and (loop.index == 1 or item.service.haproxy_ssl_all_vips | default(false) | bool) %}ssl crt {{ haproxy_ssl_pem }} ciphers {{ haproxy_ssl_cipher_suite }}{% endif %} + +{% if request_option == "http" %} + option httplog + option forwardfor except 127.0.0.0/8 + option http-server-close +{% elif request_option == "tcp" %} + option tcplog +{% endif %} +{% if item.service.haproxy_timeout_client is defined %} + timeout client {{ item.service.haproxy_timeout_client }} +{% endif %} +{% if item.service.haproxy_whitelist_networks is defined %} + acl white_list src 127.0.0.1/8 {{ item.service.haproxy_whitelist_networks | join(' ') }} + tcp-request content accept if white_list + tcp-request content reject +{% endif %} +{% if (item.service.haproxy_ssl | default(false) | bool) and request_option == 'http' and (loop.index == 1 or item.service.haproxy_ssl_all_vips | default(false) | bool) %} + reqadd X-Forwarded-Proto:\ https +{% endif %} + mode {{ item.service.haproxy_balance_type }} + default_backend {{ item.service.haproxy_service_name }}-back +{% endfor %} + +{% set backend_options = item.service.haproxy_backend_options|default([]) %} backend {{ item.service.haproxy_service_name }}-back mode {{ item.service.haproxy_balance_type }} balance {{ item.service.haproxy_balance_alg|default("leastconn") }} -{% for option in item.service.haproxy_backend_options|default([]) %} - option {{ option }} -{% endfor %} {% if item.service.haproxy_timeout_server is defined %} timeout server {{ item.service.haproxy_timeout_server }} {% endif %} + stick store-request src + stick-table type ip size 256k expire 30m +{% if request_option == "http" %} + option forwardfor + option httplog +{% elif request_option == "tcp" %} + option tcplog +{% endif %} +{% for option in backend_options %} + option {{ option }} +{% endfor %} + {% for host_name in item.service.haproxy_backend_nodes %} - server {{ host_name }} {{ hostvars[host_name]['ansible_ssh_host'] }}:{{ haproxy_backend_port }} check port {{ haproxy_backend_port }} inter {{ haproxy_interval }} rise {{ item.service.haproxy_backend_nodes|count }} fall {{ item.service.haproxy_backend_nodes|count }} +{% set entry = [] %} +{% set _ = entry.append("server") %} +{% set _ = entry.append(host_name | string) %} +{% set _ = entry.append(hostvars[host_name]['ansible_ssh_host'] + ":" + haproxy_backend_port | string) %} +{% set _ = entry.append("check") %} +{% set _ = entry.append("port") %} +{% set _ = entry.append(haproxy_backend_port | string) %} +{% set _ = entry.append("inter") %} +{% set _ = entry.append(haproxy_interval | string) %} +{% set _ = entry.append("rise") %} +{% set _ = entry.append(item.service.haproxy_backend_nodes | count | string) %} +{% set _ = entry.append("fall") %} +{% set _ = entry.append(item.service.haproxy_backend_nodes | count | string) %} + {{ entry | join(' ') }} {% endfor %} + {% for host_name in item.service.haproxy_backup_nodes|default([]) %} - server {{ host_name }} {{ hostvars[host_name]['ansible_ssh_host'] }}:{{ haproxy_backend_port }} check port {{ haproxy_backend_port }} inter {{ haproxy_interval }} rise {{ item.service.haproxy_backend_nodes|count }} fall {{ item.service.haproxy_backend_nodes|count }} backup +{% set entry = [] %} +{% set _ = entry.append("server") %} +{% set _ = entry.append(host_name | string) %} +{% set _ = entry.append(hostvars[host_name]['ansible_ssh_host'] + ":" + haproxy_backend_port | string) %} +{% set _ = entry.append("check") %} +{% set _ = entry.append("port") %} +{% set _ = entry.append(haproxy_backend_port | string) %} +{% set _ = entry.append("inter") %} +{% set _ = entry.append(haproxy_interval | string) %} +{% set _ = entry.append("rise") %} +{% set _ = entry.append(item.service.haproxy_backup_nodes | count | string) %} +{% set _ = entry.append("fall") %} +{% set _ = entry.append(item.service.haproxy_backup_nodes | count | string) %} +{% set _ = entry.append("backup") %} + {{ entry | join(' ') }} {% endfor %} diff --git a/playbooks/vars/configs/haproxy_config.yml b/playbooks/vars/configs/haproxy_config.yml index 968591fc89..a7ff1765d0 100644 --- a/playbooks/vars/configs/haproxy_config.yml +++ b/playbooks/vars/configs/haproxy_config.yml @@ -12,18 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -haproxy_backend_options_http: - - "forwardfor" - - "httpchk" - - "httplog" - -haproxy_backend_options_https: - - "ssl-hello-chk" - -keystone_ssl_admin: "{% if keystone_ssl is defined and keystone_ssl | bool and keystone_service_adminuri_proto == 'https' %}true{% else %}false{% endif %}" -keystone_ssl_internal: "{% if keystone_ssl is defined and keystone_ssl | bool and keystone_service_internaluri_proto == 'https' %}true{% else %}false{% endif %}" -keystone_ssl_public: "{% if keystone_ssl is defined and keystone_ssl | bool and keystone_service_publicuri_proto == 'https' %}true{% else %}false{% endif %}" - haproxy_service_configs: - service: haproxy_service_name: galera @@ -35,158 +23,181 @@ haproxy_service_configs: haproxy_timeout_server: 5000s haproxy_backend_options: - "mysql-check user {{ galera_monitoring_user }}" + haproxy_whitelist_networks: + - 192.168.0.0/16 + - 172.16.0.0/12 + - 10.0.0.0/8 + - service: + haproxy_service_name: repo_all + haproxy_backend_nodes: "{{ groups['repo_all'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" + haproxy_port: 8181 + haproxy_balance_type: http + haproxy_backend_options: + - "httpchk HEAD /" - service: haproxy_service_name: glance_api haproxy_backend_nodes: "{{ groups['glance_api'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 9292 haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk /versions" - - "httplog" + - "httpchk /healthcheck" - service: haproxy_service_name: glance_registry haproxy_backend_nodes: "{{ groups['glance_registry'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 9191 haproxy_balance_type: http + haproxy_backend_options: + - "httpchk /healthcheck" + haproxy_whitelist_networks: + - 192.168.0.0/16 + - 172.16.0.0/12 + - 10.0.0.0/8 - service: haproxy_service_name: heat_api_cfn haproxy_backend_nodes: "{{ groups['heat_api_cfn'] | default([]) }}" haproxy_port: 8000 + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" + - "httpchk HEAD /" - service: haproxy_service_name: heat_api_cloudwatch haproxy_backend_nodes: "{{ groups['heat_api_cloudwatch'] | default([]) }}" haproxy_port: 8003 + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" + - "httpchk HEAD /" - service: haproxy_service_name: heat_api haproxy_backend_nodes: "{{ groups['heat_api'] | default([]) }}" haproxy_port: 8004 + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" - - service: - haproxy_service_name: keystone_admin - haproxy_backend_nodes: "{{ groups['keystone_all'] | default([]) }}" - haproxy_port: 35357 - haproxy_ssl: "{% if haproxy_ssl | bool and keystone_service_adminuri_proto == 'https' %}true{% else %}false{% endif %}" - haproxy_balance_type: "{{ (keystone_ssl_admin | bool) | ternary('tcp', 'http') }}" - haproxy_balance_alg: "{{ (keystone_ssl_admin | bool) | ternary('source', 'leastconn') }}" - haproxy_backend_options: "{{ (keystone_ssl_admin | bool) | ternary(haproxy_backend_options_https, haproxy_backend_options_http) }}" + - "httpchk HEAD /" - service: haproxy_service_name: keystone_service haproxy_backend_nodes: "{{ groups['keystone_all'] | default([]) }}" - haproxy_bind: "{% if internal_lb_vip_address == external_lb_vip_address %}*{% else %}{{ external_lb_vip_address }}{% endif %}" haproxy_port: 5000 - haproxy_ssl: "{% if haproxy_ssl | bool and keystone_service_publicuri_proto == 'https' %}true{% else %}false{% endif %}" - haproxy_balance_type: "{{ (keystone_ssl_public | bool) | ternary('tcp','http') }}" - haproxy_balance_alg: "{{ (keystone_ssl_public | bool) | ternary('source', 'leastconn') }}" - haproxy_backend_options: "{{ (keystone_ssl_public | bool) | ternary(haproxy_backend_options_https, haproxy_backend_options_http) }}" + haproxy_ssl: "{{ haproxy_ssl }}" + haproxy_balance_type: "http" + haproxy_backend_options: + - "httpchk HEAD /" + - service: + haproxy_service_name: keystone_admin + haproxy_backend_nodes: "{{ groups['keystone_all'] | default([]) }}" + haproxy_port: 35357 + haproxy_balance_type: "http" + haproxy_backend_options: + - "httpchk HEAD /" + haproxy_whitelist_networks: + - 192.168.0.0/16 + - 172.16.0.0/12 + - 10.0.0.0/8 - service: haproxy_service_name: neutron_server haproxy_backend_nodes: "{{ groups['neutron_server'] | default([]) }}" haproxy_port: 9696 + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" + - "httpchk HEAD /" - service: haproxy_service_name: nova_api_metadata haproxy_backend_nodes: "{{ groups['nova_api_metadata'] | default([]) }}" haproxy_port: 8775 + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_balance_type: http haproxy_backend_options: - - "httpchk" - - "httplog" + - "httpchk HEAD /" + haproxy_whitelist_networks: + - 192.168.0.0/16 + - 172.16.0.0/12 + - 10.0.0.0/8 - service: haproxy_service_name: nova_api_os_compute haproxy_backend_nodes: "{{ groups['nova_api_os_compute'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 8774 haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" + - "httpchk HEAD /" - service: haproxy_service_name: nova_console haproxy_backend_nodes: "{{ groups['nova_console'] | default([]) }}" - haproxy_ssl: "{% if haproxy_ssl | bool and nova_spice_html5proxy_base_proto == 'https' %}true{% else %}false{% endif %}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 6082 haproxy_balance_type: tcp haproxy_timeout_client: 60m haproxy_timeout_server: 60m haproxy_balance_alg: source + haproxy_backend_options: + - tcp-check - service: haproxy_service_name: nova_console_novnc haproxy_backend_nodes: "{{ groups['nova_console'] | default([]) }}" - haproxy_ssl: "{% if haproxy_ssl | bool and nova_novncproxy_proto == 'https' %}true{% else %}false{% endif %}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 6080 haproxy_balance_type: tcp haproxy_timeout_client: 60m haproxy_timeout_server: 60m haproxy_balance_alg: source + haproxy_backend_options: + - tcp-check - service: haproxy_service_name: cinder_api haproxy_backend_nodes: "{{ groups['cinder_api'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 8776 haproxy_balance_type: http haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" + - "httpchk HEAD /" - service: haproxy_service_name: horizon haproxy_backend_nodes: "{{ groups['horizon_all'] | default([]) }}" - haproxy_port: 80 - haproxy_balance_type: http - haproxy_backend_options: - - "forwardfor" - - "httpchk" - - "httplog" - - service: - haproxy_service_name: horizon_ssl - haproxy_backend_nodes: "{{ groups['horizon_all'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" + haproxy_ssl_all_vips: true haproxy_port: 443 - haproxy_balance_type: tcp + haproxy_backend_port: 80 + haproxy_redirect_http_port: 80 + haproxy_balance_type: http haproxy_balance_alg: source haproxy_backend_options: - - "ssl-hello-chk" + - "httpchk HEAD /" - service: haproxy_service_name: swift_proxy haproxy_backend_nodes: "{{ groups['swift_proxy'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_balance_alg: source haproxy_port: 8080 haproxy_balance_type: http - - service: - haproxy_service_name: repo_all - haproxy_backend_nodes: "{{ groups['pkg_repo'] | default([]) }}" - haproxy_port: 8181 - haproxy_backend_port: 8181 - haproxy_balance_type: http + haproxy_backend_options: + - "httpchk /healthcheck" - service: haproxy_service_name: ceilometer_api haproxy_backend_nodes: "{{ groups['ceilometer_api_container'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 8777 - haproxy_balance_type: http + haproxy_balance_type: tcp + haproxy_backend_options: + - tcp-check - service: haproxy_service_name: aodh_api haproxy_backend_nodes: "{{ groups['aodh_api'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 8042 - haproxy_balance_type: http + haproxy_balance_type: tcp + haproxy_backend_options: + - tcp-check - service: haproxy_service_name: ironic_api haproxy_backend_nodes: "{{ groups['ironic_api'] | default([]) }}" + haproxy_ssl: "{{ haproxy_ssl }}" haproxy_port: 6385 haproxy_balance_type: http + haproxy_backend_options: + - "httpchk HEAD /" diff --git a/releasenotes/notes/haproxy_ssl_terminiation-cdf0092a5bfa34b5.yaml b/releasenotes/notes/haproxy_ssl_terminiation-cdf0092a5bfa34b5.yaml new file mode 100644 index 0000000000..ca31d2ad58 --- /dev/null +++ b/releasenotes/notes/haproxy_ssl_terminiation-cdf0092a5bfa34b5.yaml @@ -0,0 +1,31 @@ +--- +features: + - The HAProxy role provided by OpenStack-Ansible now terminates SSL + using a self-signed certificate by default. While this can be + disabled the inclusion of SSL services on all public endpoints as + a default will help make deployments more secure without any + additional user interaction. More information on SSL and certificate + generation can be `found here `_. +upgrade: + - SSL termination is assumed enabled for all public endpoints by default. + If this is not needed it can be disabled by setting + the ``openstack_external_ssl`` option to **false** and the + ``openstack_service_publicuri_proto`` to **http**. + - If HAProxy is used as the loadbalancer for a deployment it will generate + a self-signed certificate by default. If HAProxy is NOT used, an SSL + certificate should be installed on the external loadbalancer. The + installation of an SSL certificate on an external load balancer is not + covered by the deployment tooling. + - In previous releases connections to Horizon originally terminated SSL + at the Horizon container. While that is still an option, SSL is now + assumed to be terminated at the load balancer. If you wish to terminate + SSL at the horizon node change the ``horizon_external_ssl`` option to + **false**. + - Public endpoints will need to be updated using the Keystone admin API to + support secure endpoints. The Keystone ansible module will not recreate + the endpoints automatically. Documentation on the `Keystone service + catalog can be found here `_. +security: + - A self-signed certificate will now be generated by default when HAproxy + is used as a load balancer. This certificate is used to terminate the + public endpoint for Horizon and all OpenStack API services.