Skip to content

Commit

Permalink
Add ability for HTTP access to horizon
Browse files Browse the repository at this point in the history
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
(cherry picked from commit 4283200)
  • Loading branch information
spotz authored and Jesse Pretorius committed Oct 17, 2018
1 parent 2c36e2c commit 6903802
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 14 deletions.
16 changes: 13 additions & 3 deletions defaults/main.yml
Expand Up @@ -172,11 +172,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 }}"

Expand Down
22 changes: 22 additions & 0 deletions releasenotes/notes/http-access-horizon-94c27a0aadb9f1b4.yaml
@@ -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.
12 changes: 8 additions & 4 deletions tasks/main.yml
Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion templates/horizon_local_settings.py.j2
Expand Up @@ -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.
Expand All @@ -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 }}
Expand Down
19 changes: 13 additions & 6 deletions templates/openstack_dashboard.conf.j2
@@ -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
Expand All @@ -9,27 +11,32 @@
</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 }}
{% if horizon_user_ssl_ca_cert is defined -%}
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 }}
Expand Down
5 changes: 5 additions & 0 deletions tests/os_horizon-overrides.yml
Expand Up @@ -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

0 comments on commit 6903802

Please sign in to comment.