Add ability for HTTP access to horizon

Horizon has, since OSA's inception, been deployed with HTTPS
access enabled, and has had no way to turn it off. Some use-cases
may want to access via HTTP instead, so this patch enables
the following:

1. Listen via HTTPS on a load balancer, but via HTTP on the
   horizon host and have the load balancer forward the correct
   headers. It will do this by default in the integrated build
   due to the presence of the load balancer, so the current
   behaviour is retained.

2. Enable HTTPS on the horizon host without a load balancer.
   This is the role's default behaviour which matches what it
   always has been.

3. Disable HTTPS entirely by setting ``haproxy_ssl: no`` (which
   will also disable https on haproxy. This setting is inherited
   by the new ``horizon_enable_ssl`` variable by default. This
   is a new option.

Co-Authored-By: Jesse Pretorius <jesse.pretorius@rackspace.co.uk>
Change-Id: I823f2f949258157e306dbf80570abe53373da0c3
Closes-Bug: 1794337
This commit is contained in:
Amy Marrich (spotz) 2018-10-04 09:06:38 -05:00 committed by Jesse Pretorius (odyssey4me)
parent 4ba38f5184
commit 4283200534
6 changed files with 69 additions and 14 deletions

View File

@ -203,11 +203,21 @@ horizon_ssl_self_signed_subject: "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ horizo
# horizon_user_ssl_key: <path to cert on ansible deployment host>
# horizon_user_ssl_ca_cert: <path to cert on ansible deployment host>
# Set this to True if you do ssl termination on an external device, like the
# load balancer
horizon_external_ssl: false
# Toggle whether horizon should be served via SSL
horizon_enable_ssl: "{{ (haproxy_ssl | default(True)) | bool }}"
# Toggle whether horizon is served via an external device, like a load
# balancer. This enables the use of the horizon_secure_proxy_ssl_header
# in the web server configuration.
# Note (odyssey4me):
# This variable is actually badly named, as it applies
# settings which have nothing to do with SSL.
horizon_external_ssl: "{{ (openstack_external_ssl | default(False)) | bool }}"
# Set this to the header that your device sets when doing ssl termination
# Note (odyssey4me):
# This variable is actually badly named, as it applies
# settings which have nothing to do with SSL.
horizon_secure_proxy_ssl_header: "X-Forwarded-Proto"
horizon_secure_proxy_ssl_header_django: "HTTP_{{ horizon_secure_proxy_ssl_header | replace('-', '_') | upper }}"

View File

@ -0,0 +1,22 @@
---
features:
- |
Horizon has, since OSA's inception, been deployed with HTTPS
access enabled, and has had no way to turn it off. Some use-cases
may want to access via HTTP instead, so this patch enables
the following.
* Listen via HTTPS on a load balancer, but via HTTP on the
horizon host and have the load balancer forward the correct
headers. It will do this by default in the integrated build
due to the presence of the load balancer, so the current
behaviour is retained.
* Enable HTTPS on the horizon host without a load balancer.
This is the role's default behaviour which matches what it
always has been.
* Disable HTTPS entirely by setting ``haproxy_ssl: no`` (which
will also disable https on haproxy. This setting is inherited
by the new ``horizon_enable_ssl`` variable by default. This
is a new option.

View File

@ -58,21 +58,25 @@
- include_tasks: horizon_ssl_self_signed.yml
when:
- not horizon_external_ssl | bool
- horizon_enable_ssl | bool
- not (horizon_external_ssl | bool)
- horizon_user_ssl_cert is not defined or horizon_user_ssl_key is not defined
tags:
- horizon-config
- include_tasks: horizon_ssl_user_provided.yml
when: not horizon_external_ssl | bool
when:
- horizon_enable_ssl | bool
- not (horizon_external_ssl | bool)
tags:
- horizon-config
- name: Update the ca certificates
command: "update-ca-certificates -f"
when:
- not horizon_external_ssl | bool
- ansible_pkg_mgr == 'apt'
- horizon_enable_ssl | bool
- not (horizon_external_ssl | bool)
- ansible_pkg_mgr == 'apt'
tags:
- horizon-config
- horizon-ssl

View File

@ -37,7 +37,7 @@ WEBROOT = '{{ horizon_webroot }}'
# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = ['*']
{% if horizon_external_ssl | bool %}
{% if (horizon_enable_ssl | bool) and (horizon_external_ssl | bool) %}
# Set SSL proxy settings:
# For Django 1.4+ pass this header from the proxy after terminating the SSL,
# and don't forget to strip it from the client's request.
@ -46,10 +46,17 @@ ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('{{ horizon_secure_proxy_ssl_header_django }}', 'https')
{% endif %}
{% if horizon_enable_ssl | bool %}
# If Horizon is being served through SSL, then uncomment the following two
# settings to better secure the cookies from security exploits
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
{% else %}
# If Horizon is being served through SSL, then uncomment the following two
# settings to better secure the cookies from security exploits
CSRF_COOKIE_SECURE = False
SESSION_COOKIE_SECURE = False
{% endif %}
# Define the time after which a Horizon session expires
SESSION_TIMEOUT = {{ horizon_session_timeout }}

View File

@ -1,6 +1,8 @@
# {{ ansible_managed }}
{% if not horizon_external_ssl | bool %}
# If horizon is being served via SSL from this web server,
# then we must redirect HTTP requests to HTTPS.
{% if (horizon_enable_ssl | bool) and not (horizon_external_ssl | bool) %}
<VirtualHost *:80>
ServerName {{ horizon_server_name }}
RewriteEngine On
@ -9,14 +11,16 @@
</VirtualHost>
{% endif %}
<VirtualHost *:{% if not horizon_external_ssl | bool %}443{% else %}80{% endif %}>
# If horizon is being served via SSL via a load balancer, we
# need to listen via HTTP on this web server. If SSL is not
# enabled, then the same applies.
<VirtualHost *:{{ ((horizon_enable_ssl | bool) and not (horizon_external_ssl | bool)) | ternary('443', '80') }}>
ServerName {{ horizon_server_name }}
LogLevel {{ horizon_log_level }}
ErrorLog /var/log/horizon/horizon-error.log
CustomLog /var/log/horizon/ssl_access.log {{ horizon_apache_custom_log_format }}
Options +FollowSymLinks
{% if not horizon_external_ssl | bool %}
{% if (horizon_enable_ssl | bool) and not (horizon_external_ssl | bool) %}
SSLEngine on
SSLCertificateFile {{ horizon_ssl_cert }}
SSLCertificateKeyFile {{ horizon_ssl_key }}
@ -24,12 +28,15 @@
SSLCACertificateFile {{ horizon_ssl_ca_cert }}
{% endif -%}
SSLCompression Off
SSLProtocol {{ horizon_ssl_protocol }}
SSLProtocol {{ horizon_ssl_protocol }}
SSLHonorCipherOrder On
SSLCipherSuite {{ horizon_ssl_cipher_suite }}
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
{% else %}
{% endif %}
{% if (horizon_enable_ssl | bool) and (horizon_external_ssl | bool) %}
RequestHeader set {{ horizon_secure_proxy_ssl_header }} "https"
{% elif not (horizon_enable_ssl | bool) and (horizon_external_ssl | bool) %}
RequestHeader set {{ horizon_secure_proxy_ssl_header }} "http"
{% endif %}
WSGIScriptAlias / {{ horizon_lib_wsgi_file }}

View File

@ -37,3 +37,8 @@ tempest_tempest_conf_overrides:
horizon_config_overrides:
X_TEST_OPTION: True
# This has to be set here because the common test-vars
# has haproxy_ssl set to no.
horizon_enable_ssl: yes