Merge "Add documentation of security improvements made to Openstack Ansible"
This commit is contained in:
commit
e2921e84a3
@ -11,4 +11,6 @@ For understanding security design, please see
|
||||
:ref:`security-design`.
|
||||
|
||||
.. include:: ssl-certificates.rst
|
||||
.. include:: security-headers.rst
|
||||
.. include:: security-txt.rst
|
||||
.. include:: hardening.rst
|
||||
|
127
doc/source/user/security/security-headers.rst
Normal file
127
doc/source/user/security/security-headers.rst
Normal file
@ -0,0 +1,127 @@
|
||||
Security Headers
|
||||
================
|
||||
|
||||
Security headers are HTTP headers that can be used to increase the security of
|
||||
a web application by restricting what modern browsers are able to run.
|
||||
|
||||
In OpenStack-Ansible, security headers are implemented in haproxy as all the
|
||||
public endpoints reside behind it.
|
||||
|
||||
The following headers are enabled by default on all the haproxy interfaces
|
||||
that implement TLS, but only for the Horizon service. The security headers can
|
||||
be implemented on other haproxy services, but only services used by
|
||||
browsers will make use of the headers.
|
||||
|
||||
HTTP Strict Transport Security
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The `OpenStack TLS Security Guide`_ recommends that all production deployments use
|
||||
HTTP strict transport security (HSTS).
|
||||
|
||||
.. _OpenStack TLS Security Guide: https://docs.openstack.org/security-guide/secure-communication/tls-proxies-and-http-services.html#http-strict-transport-security
|
||||
|
||||
By design, this header is difficult to disable once set. It is recommended that
|
||||
during testing you set a short time of 1 day and after testing increase the time
|
||||
to 1 year.
|
||||
|
||||
To change the default max age to 1 day, override the variable
|
||||
``haproxy_security_headers_max_age`` in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
haproxy_security_headers_max_age: 86400
|
||||
|
||||
If you would like your domain included in the HSTS preload list, which is built
|
||||
into browsers, before submitting your request to be added to the HSTS preload
|
||||
list you must add the ``preload`` token to your response header. The ``preload``
|
||||
token indicates to the maintainers of HSTS preload list that you are happy to
|
||||
have your site included.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- "http-response set-header Strict-Transport-Security \"max-age={{ haproxy_security_headers_max_age }}; includeSubDomains; preload;\""
|
||||
|
||||
X-Content-Type-Options
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``X-Content-Type-Options`` header prevents MIME type sniffing.
|
||||
|
||||
This functionality can be changed by overriding the list of headers in
|
||||
``haproxy_security_headers`` variable in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file.
|
||||
|
||||
Referrer Policy
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The ``Referrer-Policy`` header controls how much referrer information is sent
|
||||
with requests. It defaults to ``same-origin``, which does not send the origin
|
||||
path for cross-origin requests.
|
||||
|
||||
This functionality can be changed by overriding the list of headers in
|
||||
``haproxy_security_headers`` variable in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file.
|
||||
|
||||
Permission Policy
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``Permissions-Policy`` header allows you to selectively enable, disable or
|
||||
modify the use of browser features and APIs, previously known as Feature Policy.
|
||||
|
||||
By default this header is set to block access to all features apart from the
|
||||
following from the same origin; fullscreen, clipboard read, clipboard
|
||||
write and spatial navigation.
|
||||
|
||||
This functionality can be changed by overriding the list of headers in
|
||||
``haproxy_security_headers`` variable in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file.
|
||||
|
||||
|
||||
Content Security Policy (CSP)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``Content-Security-Policy`` header allows you to control what resources a
|
||||
browser is allowed to load for a given page, which helps to mitigate the risks
|
||||
from Cross-Site Scripting (XSS) and data injection attacks.
|
||||
|
||||
By default, the Content Security Policy (CSP) enables a minimum set of resources
|
||||
to allow Horizon to work, which includes access the Nova console. If you require
|
||||
access to other resources these can be set by overriding the
|
||||
``haproxy_security_headers_csp`` variable in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file.
|
||||
|
||||
Report Only
|
||||
-----------
|
||||
|
||||
Implementing CSP could lead to broken content if a browser is blocked from
|
||||
accessing certain resources, therefore it is recommended that when testing CSP
|
||||
you use the ``Content-Security-Policy-Report-Only`` header, instead of
|
||||
``Content-Security-Policy``, this reports CSP violations to the browser console,
|
||||
but does not enforce the policy.
|
||||
|
||||
To set the CSP policy to report only by overriding the
|
||||
``haproxy_security_headers_csp_report_only`` variable to ``True`` in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
haproxy_security_headers_csp_report_only: True
|
||||
|
||||
|
||||
Reporting Violations
|
||||
--------------------
|
||||
|
||||
It is recommended that you monitor attempted CSP violations in production, this
|
||||
is achieved by setting the ``report-uri`` and ``report-to`` tokens.
|
||||
|
||||
Federated Login
|
||||
---------------
|
||||
|
||||
When using federated login you will need to override the default Content
|
||||
Security Policy to allow access to your authorisation server by overriding the
|
||||
``haproxy_horizon_csp`` variable in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
haproxy_horizon_csp: "http-response set-header Content-Security-Policy \"default-src 'self'; frame-ancestors 'self'; form-action 'self' {{ external_lb_vip_address }}:5000 <YOUR-AUTHORISATION-SERVER-ORIGIN>; upgrade-insecure-requests; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self' {{ external_lb_vip_address }}:{{ nova_console_port }}; frame-src 'self' {{ external_lb_vip_address }}:{{ nova_console_port }};\""
|
54
doc/source/user/security/security-txt.rst
Normal file
54
doc/source/user/security/security-txt.rst
Normal file
@ -0,0 +1,54 @@
|
||||
Security.txt
|
||||
============
|
||||
|
||||
security.txt is a proposed `IETF standard`_ to allow independent security
|
||||
researchers to easily report vulnerabilities. The standard defines that a text
|
||||
file called ``security.txt`` should be found at "/.well-known/security.txt". For
|
||||
legacy compatibility reasons the file might also be placed at "/security.txt".
|
||||
|
||||
.. _IETF standard: https://datatracker.ietf.org/doc/html/draft-foudil-securitytxt
|
||||
|
||||
In OpenStack-Ansible, ``security.txt`` is implemented in haproxy as all public
|
||||
endpoints reside behind it and the text file is hosted by keystone. It defaults
|
||||
to directing any request paths that end with ``/security.txt`` to the text
|
||||
file using an ACL rule in haproxy.
|
||||
|
||||
Enabling security.txt
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Use the following process to add a ``security.txt`` file to your deployment
|
||||
using OpenStack-Ansible:
|
||||
|
||||
#. Write the contents of the ``security.txt`` file in accordance with the
|
||||
standard.
|
||||
#. Define the contents of ``security.txt`` in the variable
|
||||
``keystone_security_txt_content`` in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
keystone_security_txt_content: |
|
||||
# This is my example security.txt file
|
||||
# Please see https://securitytxt.org/ for details of the specification of this file
|
||||
|
||||
#. Update keystone
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
# openstack-ansible os-keystone-install.yml
|
||||
|
||||
#. Update haproxy
|
||||
|
||||
.. code-block:: shell-session
|
||||
|
||||
# openstack-ansible haproxy-install.yml
|
||||
|
||||
Advanced security.txt ACL
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In some cases you may need to change the haproxy ACL used to redirect requests
|
||||
to the ``security.txt`` file, such as adding extra domains.
|
||||
|
||||
The haproxy ACL is updated by overriding the variable
|
||||
``haproxy_security_txt_acl`` in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file.
|
@ -202,25 +202,34 @@ the preceding configuration variables with `horizon`, `haproxy`, or `keystone`,
|
||||
and then run the playbook for that service to deploy user-provided certificates
|
||||
to those services.
|
||||
|
||||
LetsEncrypt certificates
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Certbot certificates
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The HAProxy ansible role supports using LetsEncrypt to automatically deploy
|
||||
The HAProxy ansible role supports using certbot to automatically deploy
|
||||
trusted SSL certificates for the public endpoint. Each HAProxy server will
|
||||
individually request a LetsEncrypt certificate.
|
||||
individually request a SSL certificate using certbot.
|
||||
|
||||
Certbot defaults to using LetsEncrypt as the Certificate Authority, other
|
||||
Certificate Authorities can be used by setting the
|
||||
``haproxy_ssl_letsencrypt_certbot_server`` variable in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
haproxy_ssl_letsencrypt_certbot_server: "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
|
||||
The http-01 type challenge is used by certbot to deploy certificates so
|
||||
it is required that the public endpoint is accessible directly on the
|
||||
internet.
|
||||
it is required that the public endpoint is accessible directly by the
|
||||
Certificate Authority.
|
||||
|
||||
Deployment of certificates using LetsEncrypt has been validated for
|
||||
Deployment of certificates using certbot has been validated for
|
||||
openstack-ansible using Ubuntu Bionic. Other distributions should work
|
||||
but are not tested.
|
||||
|
||||
To deploy certificates with LetsEncrypt, add the following to
|
||||
To deploy certificates with certbot, add the following to
|
||||
``/etc/openstack_deploy/user_variables.yml`` to enable the
|
||||
letsencrypt function in the haproxy ansible role, and to
|
||||
create a new backend service called ``letsencrypt`` to service
|
||||
certbot function in the haproxy ansible role, and to
|
||||
create a new backend service called ``certbot`` to service
|
||||
http-01 challenge requests.
|
||||
|
||||
.. code-block:: shell-session
|
||||
@ -253,3 +262,107 @@ backend is certbot on the haproxy host:
|
||||
haproxy_backend_port: 80
|
||||
haproxy_backend_options:
|
||||
- "httpchk HEAD /" # request to use for health check for the example service
|
||||
|
||||
TLS for Haproxy Internal VIP
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As well as load balancing public endpoints, haproxy is also used to load balance
|
||||
internal connections.
|
||||
|
||||
By default, OpenStack-Ansible does not secure connections to the internal VIP.
|
||||
To enable this you must set the following variables in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
openstack_service_adminuri_proto: https
|
||||
openstack_service_internaluri_proto: https
|
||||
|
||||
haproxy_ssl_all_vips: true
|
||||
|
||||
Run all playbooks to configure haproxy and openstack services.
|
||||
|
||||
When enabled haproxy will use the same TLS certificate on all interfaces
|
||||
(internal and external). It is not currently possible in OpenStack-Ansible to
|
||||
use different self-signed or user-provided TLS certificates on different haproxy
|
||||
interfaces.
|
||||
|
||||
The only way to use a different TLS certificates on the internal and external
|
||||
VIP is to use certbot.
|
||||
|
||||
Enabling TLS on the internal VIP for existing deployments will cause some
|
||||
downtime, this is because haproxy only listens on a single well known port for
|
||||
each OpenStack service and OpenStack services are configured to use http or
|
||||
https. This means once haproxy is updated to only accept HTTPS connections, the
|
||||
OpenStack services will stop working until they are updated to use HTTPS.
|
||||
|
||||
For this reason it is recommended that TLS for haproxy internal VIP on existing
|
||||
deployments is deployed at the same time as enabling TLS for Haproxy backends,
|
||||
as this may also cause downtime. For new deployments this should be enabled from
|
||||
the start.
|
||||
|
||||
TLS for Haproxy Backends
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Securing the internal communications from haproxy to backend services is
|
||||
currently work in progress.
|
||||
|
||||
TLS for Live Migrations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Live migration of VM's using SSH is deprecated and the `OpenStack Nova Docs`_
|
||||
recommends using the more secure native TLS method supported by QEMU. The
|
||||
default live migration method used by OpenStack-Ansible has been updated to
|
||||
use TLS migrations.
|
||||
|
||||
.. _OpenStack Nova Docs: https://docs.openstack.org/nova/latest/admin/secure-live-migration-with-qemu-native-tls.html
|
||||
|
||||
QEMU-native TLS requires all compute hosts to accept TCP connections on
|
||||
port 16514 and port range 49152 to 49261.
|
||||
|
||||
It is not possible to have a mixed estate of some compute nodes using SSH and
|
||||
some using TLS for live migrations, as this would prevent live migrations
|
||||
between the compute nodes.
|
||||
|
||||
There are no issues enabling TLS live migration during an OpenStack upgrade, as
|
||||
long as you do not need to live migrate instances during the upgrade. If you
|
||||
you need to live migrate instances during an upgrade, enable TLS live migrations
|
||||
before or after the upgrade.
|
||||
|
||||
To force the use of SSH instead of TLS for live migrations you must set the
|
||||
``nova_libvirtd_listen_tls`` variable to ``0`` in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
nova_libvirtd_listen_tls: 0
|
||||
|
||||
TLS for VNC
|
||||
~~~~~~~~~~~
|
||||
|
||||
When using VNC for console access there are 3 connections to secure, client to
|
||||
haproxy, haproxy to noVNC Proxy and noVNC Proxy to Compute nodes. The `OpenStack
|
||||
Nova Docs for remote console access`_ cover console security in much more
|
||||
detail.
|
||||
|
||||
.. _OpenStack Nova Docs for remote console access: https://docs.openstack.org/nova/latest/admin/remote-console-access.html#vnc-proxy-security
|
||||
|
||||
In OpenStack-Ansible TLS to haproxy is configured in haproxy, TLS to noVNC is
|
||||
not currently enabled and TLS to Compute nodes is enabled by default.
|
||||
|
||||
To help with the transition from unencrypted VNC to VeNCrypt,
|
||||
initially noVNC proxy auth scheme allows for both encrypted and
|
||||
unencrypted sessions using the variable `nova_vencrypt_auth_scheme`. This will
|
||||
be restricted to VeNCrypt only in future versions of OpenStack-Ansible.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
nova_vencrypt_auth_scheme: "vencrypt,none"
|
||||
|
||||
To not encrypt data from noVNC proxy to Compute nodes you must set the
|
||||
``nova_qemu_vnc_tls`` variable to ``0`` in the
|
||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
nova_qemu_vnc_tls: 0
|
||||
|
@ -39,8 +39,10 @@ haproxy_security_txt_acl:
|
||||
|
||||
# Variables to set security headers used by browsers
|
||||
haproxy_security_headers_max_age: 31536000
|
||||
# Set CSP headers to report only for testing
|
||||
haproxy_security_headers_csp_report_only: False
|
||||
# To override the CSP used by a specific service define a variable haproxy_<service name>_csp
|
||||
haproxy_security_headers_csp: "http-response set-header Content-Security-Policy \"default-src 'self'; frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self' {{ external_lb_vip_address }}:{{ nova_console_port }}; frame-src 'self' {{ external_lb_vip_address }}:{{ nova_console_port }};\""
|
||||
haproxy_security_headers_csp: "http-response set-header {{ haproxy_security_headers_csp_report_only | ternary('Content-Security-Policy-Report-Only', 'Content-Security-Policy') }} \"default-src 'self'; frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; child-src 'self' {{ external_lb_vip_address }}:{{ nova_console_port }}; frame-src 'self' {{ external_lb_vip_address }}:{{ nova_console_port }};\""
|
||||
# To disable security headers set to []
|
||||
haproxy_security_headers:
|
||||
- "http-response set-header Strict-Transport-Security \"max-age={{ haproxy_security_headers_max_age }}; includeSubDomains;\""
|
||||
|
Loading…
Reference in New Issue
Block a user