Serve security.txt directly from haproxy
Currently security.txt file is stored and served from keystone. It's not necessary as haproxy is able to serve static files[1]. This patch creates security_txt haproxy service responsible for serving security.txt static file using recently implemented maps feature. [1] https://sleeplessbeastie.eu/2020/05/11/how-to-serve-single-file-using-haproxy/ Depends-On: https://review.opendev.org/c/openstack/openstack-ansible-haproxy_server/+/880088 Change-Id: If0ec375055abedceb13a035b9c8f5107f4659f86
This commit is contained in:
@@ -9,9 +9,8 @@ legacy compatibility reasons the file might also be placed at "/security.txt".
|
|||||||
.. _IETF standard: https://datatracker.ietf.org/doc/html/draft-foudil-securitytxt
|
.. _IETF standard: https://datatracker.ietf.org/doc/html/draft-foudil-securitytxt
|
||||||
|
|
||||||
In OpenStack-Ansible, ``security.txt`` is implemented in haproxy as all public
|
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
|
endpoints reside behind it. It defaults to directing any request paths that
|
||||||
to directing any request paths that end with ``/security.txt`` to the text
|
end with ``/security.txt`` to the text file using an ACL rule in haproxy.
|
||||||
file using an ACL rule in haproxy.
|
|
||||||
|
|
||||||
Enabling security.txt
|
Enabling security.txt
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -22,21 +21,15 @@ using OpenStack-Ansible:
|
|||||||
#. Write the contents of the ``security.txt`` file in accordance with the
|
#. Write the contents of the ``security.txt`` file in accordance with the
|
||||||
standard.
|
standard.
|
||||||
#. Define the contents of ``security.txt`` in the variable
|
#. Define the contents of ``security.txt`` in the variable
|
||||||
``keystone_security_txt_content`` in the
|
``haproxy_security_txt_content`` in the
|
||||||
``/etc/openstack_deploy/user_variables.yml`` file:
|
``/etc/openstack_deploy/user_variables.yml`` file:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
keystone_security_txt_content: |
|
haproxy_security_txt_content: |
|
||||||
# This is my example security.txt file
|
# This is my example security.txt file
|
||||||
# Please see https://securitytxt.org/ for details of the specification of this 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
|
#. Update haproxy
|
||||||
|
|
||||||
.. code-block:: shell-session
|
.. code-block:: shell-session
|
||||||
@@ -50,5 +43,4 @@ 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.
|
to the ``security.txt`` file, such as adding extra domains.
|
||||||
|
|
||||||
The haproxy ACL is updated by overriding the variable
|
The haproxy ACL is updated by overriding the variable
|
||||||
``haproxy_security_txt_acl`` in the
|
``haproxy_map_entries`` inside ``haproxy_security_txt_service``.
|
||||||
``/etc/openstack_deploy/user_variables.yml`` file.
|
|
||||||
|
@@ -35,11 +35,6 @@ haproxy_stick_table_allowlist_networks: "{{ haproxy_allowlist_networks }}"
|
|||||||
haproxy_ironic_allowlist_networks: "{{ haproxy_allowlist_networks }}"
|
haproxy_ironic_allowlist_networks: "{{ haproxy_allowlist_networks }}"
|
||||||
haproxy_ironic_inspector_allowlist_networks: "{{ haproxy_allowlist_networks }}"
|
haproxy_ironic_inspector_allowlist_networks: "{{ haproxy_allowlist_networks }}"
|
||||||
|
|
||||||
haproxy_security_txt_acl:
|
|
||||||
keystone-security-txt-acl:
|
|
||||||
rule: "path_end /security.txt"
|
|
||||||
backend_name: keystone_service
|
|
||||||
|
|
||||||
# Variables to set security headers used by browsers
|
# Variables to set security headers used by browsers
|
||||||
haproxy_security_headers_max_age: 31536000
|
haproxy_security_headers_max_age: 31536000
|
||||||
# Set CSP headers to report only for testing
|
# Set CSP headers to report only for testing
|
||||||
@@ -88,6 +83,21 @@ openstack_haproxy_horizon_stick_table:
|
|||||||
- "http-request deny deny_status 429 if { sc_http_req_rate(0) gt 20 } { path_beg /auth } !{ src {{haproxy_stick_table_allowlist_networks | join(' } !{ src ') }} }"
|
- "http-request deny deny_status 429 if { sc_http_req_rate(0) gt 20 } { path_beg /auth } !{ src {{haproxy_stick_table_allowlist_networks | join(' } !{ src ') }} }"
|
||||||
- "http-request deny deny_status 429 if { sc_http_err_rate(0) gt 20 } !{ src {{haproxy_stick_table_allowlist_networks | join(' } !{ src ') }} }"
|
- "http-request deny deny_status 429 if { sc_http_err_rate(0) gt 20 } !{ src {{haproxy_stick_table_allowlist_networks | join(' } !{ src ') }} }"
|
||||||
|
|
||||||
|
|
||||||
|
haproxy_security_txt_service:
|
||||||
|
haproxy_backend_only: true
|
||||||
|
haproxy_service_name: security_txt
|
||||||
|
haproxy_backend_nodes: []
|
||||||
|
haproxy_balance_type: http
|
||||||
|
haproxy_service_enabled: "{{ haproxy_security_txt_content is truthy }}"
|
||||||
|
# https://sleeplessbeastie.eu/2020/05/11/how-to-serve-single-file-using-haproxy/
|
||||||
|
haproxy_backend_arguments:
|
||||||
|
- 'errorfile 503 /etc/haproxy/security.txt'
|
||||||
|
haproxy_map_entries:
|
||||||
|
- name: base_regex
|
||||||
|
entries:
|
||||||
|
- '.*/security.txt security_txt-back'
|
||||||
|
|
||||||
# haproxy 'base' frontend-only service that is used always deployed for port 80 redirect and 443
|
# haproxy 'base' frontend-only service that is used always deployed for port 80 redirect and 443
|
||||||
# this potentially supports horizon dashboard, security.txt and certbot
|
# this potentially supports horizon dashboard, security.txt and certbot
|
||||||
# plus any other user defined custom backend
|
# plus any other user defined custom backend
|
||||||
@@ -102,7 +112,6 @@ haproxy_base_service:
|
|||||||
haproxy_service_enabled: true
|
haproxy_service_enabled: true
|
||||||
haproxy_redirect_scheme: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary('https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }', 'https if !{ ssl_fc }') }}"
|
haproxy_redirect_scheme: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary('https if !{ ssl_fc } !{ path_beg /.well-known/acme-challenge/ }', 'https if !{ ssl_fc }') }}"
|
||||||
haproxy_frontend_acls: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary(haproxy_ssl_letsencrypt_acl, {}) }}"
|
haproxy_frontend_acls: "{{ (haproxy_ssl_letsencrypt_enable | bool and haproxy_ssl | bool) | ternary(haproxy_ssl_letsencrypt_acl, {}) }}"
|
||||||
haproxy_acls: "{{ keystone_security_txt_content is defined | ternary(haproxy_security_txt_acl, {}) }}"
|
|
||||||
haproxy_frontend_raw: "{{ (haproxy_ssl | bool and haproxy_security_headers is defined) | ternary( haproxy_security_headers + [ haproxy_horizon_csp | default(haproxy_security_headers_csp)], []) }}"
|
haproxy_frontend_raw: "{{ (haproxy_ssl | bool and haproxy_security_headers is defined) | ternary( haproxy_security_headers + [ haproxy_horizon_csp | default(haproxy_security_headers_csp)], []) }}"
|
||||||
haproxy_maps:
|
haproxy_maps:
|
||||||
- 'use_backend %[path,map_reg(/etc/haproxy/base_regex.map)]'
|
- 'use_backend %[path,map_reg(/etc/haproxy/base_regex.map)]'
|
||||||
@@ -634,6 +643,7 @@ haproxy_zun_console_service:
|
|||||||
haproxy_service_enabled: "{{ groups['zun_api'] is defined and groups['zun_api'] | length > 0 }}"
|
haproxy_service_enabled: "{{ groups['zun_api'] is defined and groups['zun_api'] | length > 0 }}"
|
||||||
|
|
||||||
haproxy_default_services:
|
haproxy_default_services:
|
||||||
|
- service: "{{ haproxy_security_txt_service | combine(haproxy_security_txt_service_overrides | default({})) }}"
|
||||||
- service: "{{ haproxy_base_service | combine(haproxy_base_service_overrides | default({})) }}"
|
- service: "{{ haproxy_base_service | combine(haproxy_base_service_overrides | default({})) }}"
|
||||||
- service: "{{ haproxy_adjutant_api_service | combine(haproxy_adjutant_api_service_overrides | default({})) }}"
|
- service: "{{ haproxy_adjutant_api_service | combine(haproxy_adjutant_api_service_overrides | default({})) }}"
|
||||||
- service: "{{ haproxy_aodh_api_service | combine(haproxy_aodh_api_service_overrides | default({})) }}"
|
- service: "{{ haproxy_aodh_api_service | combine(haproxy_aodh_api_service_overrides | default({})) }}"
|
||||||
|
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
``keystone_security_txt_content`` variable name has changed to
|
||||||
|
``haproxy_security_txt_content``. Security.txt file is now served
|
||||||
|
directly from haproxy.
|
Reference in New Issue
Block a user