From 2f7492a0b1f2a72f9943b44af8e54356ae9e900f Mon Sep 17 00:00:00 2001 From: Alex Figueiredo Date: Fri, 21 Mar 2025 10:51:37 -0300 Subject: [PATCH] [horizon] fix https login When the stx-openstack is deployed with https enabled (certificate and domain_name setup), the horizon login is failing and the following message is displayed: "Cookies may be turned off. Make sure cookies are enabled and try again". Checking horizon log, it's possible to see that auth request is failing with "Origin checking failed". This is hapenning because Django version used by horizon was upversioned from Django 3.2 to Django 4.2 for stx-opentack caracal [1]. After version 4.0, CSFR protection implemented by Django consults the Origin header and requires the CSRF_TRUSTED_ORIGINS config to be defined [2]. To fix this issue, this change cherry-picks the changes [3] and [4] already merged to the openstack-helm repos, and updates the horizon plugin to dynamically set the CSRF_TRUSTED_ORIGINS config based on the current definitions for endpoint_domain and serviceEndpointPattern [5]. [1]https://review.opendev.org/c/starlingx/root/+/940739 [2]https://docs.djangoproject.com/en/4.2/releases/4.0/#csrf [3]https://review.opendev.org/c/openstack/openstack-helm/+/922755 [4]https://review.opendev.org/c/openstack/openstack-helm/+/922973 [5]https://review.opendev.org/c/starlingx/openstack-armada-app/+/931836 Test Plan: [PASS] build stx-openstack tarball HTTPS Test Case: [PASS] install openstack with certificate and domain_name setup [PASS] Access horizon via fqdn (e.g.: https://horizon-.com/) HTTP Test Case: [PASS] install openstack without certificate and domain_name setup [PASS] Access horizon via ip:port (e.g.: http://:/) Closes-Bug: #2103799 Change-Id: Icd4820e16c1faa9247dd675b1dc24f6e5a343a25 Signed-off-by: Alex Figueiredo --- ...etting-Django-s-CSRF_TRUSTED_ORIGINS.patch | 42 +++++++++++++++++++ ...lating-of-list-of-strings-for-CSRF_T.patch | 35 ++++++++++++++++ .../debian/deb_folder/patches/series | 2 + .../k8sapp_openstack/helm/horizon.py | 25 +++++++++++ .../horizon/horizon-static-overrides.yaml | 5 +++ 5 files changed, 109 insertions(+) create mode 100644 openstack-helm/debian/deb_folder/patches/0021-horizon-Allows-setting-Django-s-CSRF_TRUSTED_ORIGINS.patch create mode 100644 openstack-helm/debian/deb_folder/patches/0022-horizon-fix-templating-of-list-of-strings-for-CSRF_T.patch diff --git a/openstack-helm/debian/deb_folder/patches/0021-horizon-Allows-setting-Django-s-CSRF_TRUSTED_ORIGINS.patch b/openstack-helm/debian/deb_folder/patches/0021-horizon-Allows-setting-Django-s-CSRF_TRUSTED_ORIGINS.patch new file mode 100644 index 00000000..bba23761 --- /dev/null +++ b/openstack-helm/debian/deb_folder/patches/0021-horizon-Allows-setting-Django-s-CSRF_TRUSTED_ORIGINS.patch @@ -0,0 +1,42 @@ +From 776b29a26da2fae6f2aa575f401f3f4da873ab1c Mon Sep 17 00:00:00 2001 +From: Nicholas Kuechler +Date: Tue, 25 Jun 2024 11:53:09 -0500 +Subject: [PATCH 21/22] horizon: Allows setting Django's CSRF_TRUSTED_ORIGINS + in helm values file + +Change-Id: I8930b8df7c068c63ee19a7f3a29c66ef2b3ee820 + +[ Cherry-picked to stx-openstack caracal ] +Test Plan: +[PASS] build stx-openstack tarball +Related-Bug: #2103799 +Signed-off-by: Alex Figueiredo +--- + horizon/values.yaml | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/horizon/values.yaml b/horizon/values.yaml +index 98f8ede2..6362ad87 100644 +--- a/horizon/values.yaml ++++ b/horizon/values.yaml +@@ -217,6 +217,7 @@ conf: + show_openrc_file: "True" + csrf_cookie_secure: "False" + csrf_cookie_httponly: "False" ++ csrf_trusted_origins: [] + enforce_password_check: "True" + # Set enable_pwd_validator to true to enforce password validator settings. + enable_pwd_validator: false +@@ -312,6 +313,9 @@ conf: + + SESSION_COOKIE_HTTPONLY = {{ .Values.conf.horizon.local_settings.config.session_cookie_httponly }} + ++ # https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins ++ CSRF_TRUSTED_ORIGINS = {{ .Values.conf.horizon.local_settings.config.csrf_trusted_origins }} ++ + # Overrides for OpenStack API versions. Use this setting to force the + # OpenStack dashboard to use a specific API version for a given service API. + # Versions specified here should be integers or floats, not strings. +-- +2.34.1 + diff --git a/openstack-helm/debian/deb_folder/patches/0022-horizon-fix-templating-of-list-of-strings-for-CSRF_T.patch b/openstack-helm/debian/deb_folder/patches/0022-horizon-fix-templating-of-list-of-strings-for-CSRF_T.patch new file mode 100644 index 00000000..45e54f65 --- /dev/null +++ b/openstack-helm/debian/deb_folder/patches/0022-horizon-fix-templating-of-list-of-strings-for-CSRF_T.patch @@ -0,0 +1,35 @@ +From b49bc7619031cd35eb3b90484b7f8716eba91887 Mon Sep 17 00:00:00 2001 +From: Nicholas Kuechler +Date: Thu, 27 Jun 2024 13:57:29 -0500 +Subject: [PATCH 22/22] horizon: fix templating of list of strings for + CSRF_TRUSTED_ORIGINS + +Change-Id: I740cd48103950e1599e77db46c7e4d9e65677177 + +[ Cherry-picked to stx-openstack caracal ] +Test Plan: +[PASS] build stx-openstack tarball +[PASS] install openstack with certificate and domain_name setup, enabling HTTPs +[PASS] Access horizon via fqdn (ex: https://horizon-.com/) +Related-Bug: #2103799 +Signed-off-by: Alex Figueiredo +--- + horizon/values.yaml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/horizon/values.yaml b/horizon/values.yaml +index 6362ad87..fbf465f5 100644 +--- a/horizon/values.yaml ++++ b/horizon/values.yaml +@@ -314,7 +314,7 @@ conf: + SESSION_COOKIE_HTTPONLY = {{ .Values.conf.horizon.local_settings.config.session_cookie_httponly }} + + # https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins +- CSRF_TRUSTED_ORIGINS = {{ .Values.conf.horizon.local_settings.config.csrf_trusted_origins }} ++ CSRF_TRUSTED_ORIGINS = [{{ include "helm-toolkit.utils.joinListWithCommaAndSingleQuotes" .Values.conf.horizon.local_settings.config.csrf_trusted_origins }}] + + # Overrides for OpenStack API versions. Use this setting to force the + # OpenStack dashboard to use a specific API version for a given service API. +-- +2.34.1 + diff --git a/openstack-helm/debian/deb_folder/patches/series b/openstack-helm/debian/deb_folder/patches/series index 8286ec7d..8552acc6 100644 --- a/openstack-helm/debian/deb_folder/patches/series +++ b/openstack-helm/debian/deb_folder/patches/series @@ -18,3 +18,5 @@ 0018-Define-values-for-NetApp-volume-backend.patch 0019-Add-cluster-host-ip-env-var-to-nova.patch 0020-Add-service-role-to-neutron-policy.patch +0021-horizon-Allows-setting-Django-s-CSRF_TRUSTED_ORIGINS.patch +0022-horizon-fix-templating-of-list-of-strings-for-CSRF_T.patch diff --git a/python3-k8sapp-openstack/k8sapp_openstack/k8sapp_openstack/helm/horizon.py b/python3-k8sapp-openstack/k8sapp_openstack/k8sapp_openstack/helm/horizon.py index 4055e1cb..ef4bc439 100644 --- a/python3-k8sapp-openstack/k8sapp_openstack/k8sapp_openstack/helm/horizon.py +++ b/python3-k8sapp-openstack/k8sapp_openstack/k8sapp_openstack/helm/horizon.py @@ -10,6 +10,7 @@ from sysinv.helm import common from k8sapp_openstack.common import constants as app_constants from k8sapp_openstack.helm import openstack +from k8sapp_openstack.utils import get_services_fqdn_pattern class HorizonHelm(openstack.OpenstackBaseHelm): @@ -116,6 +117,30 @@ class HorizonHelm(openstack.OpenstackBaseHelm): 'https_enabled': 'True', }) + # After version 4.0, CSFR protection implemented by Django consults + # the Origin header and requires the CSRF_TRUSTED_ORIGINS config to be + # defined. + # Ref.: https://docs.djangoproject.com/en/4.2/releases/4.0/#csrf + csrf_trusted_origins = [] + # Get the openstack endpoint public domain name + endpoint_domain = self._get_service_parameter( + constants.SERVICE_TYPE_OPENSTACK, + constants.SERVICE_PARAM_SECTION_OPENSTACK_HELM, + constants.SERVICE_PARAM_NAME_ENDPOINT_DOMAIN) + if endpoint_domain is not None: + # Define endpoint domain based on pattern + fqdn_pattern = get_services_fqdn_pattern() + service_endpoint = fqdn_pattern.format( + service_name=self.SERVICE_NAME, + endpoint_domain=str(endpoint_domain.value), + ).lower() + csrf_trusted_origins.append("%s://%s" % + (self._get_public_protocol(), + service_endpoint)) + local_settings_config.update({ + 'csrf_trusted_origins': csrf_trusted_origins, + }) + lockout_retries = self._get_service_parameter('horizon', 'auth', 'lockout_retries') lockout_seconds = self._get_service_parameter('horizon', 'auth', 'lockout_seconds') if lockout_retries is not None and lockout_seconds is not None: diff --git a/stx-openstack-helm-fluxcd/stx-openstack-helm-fluxcd/manifests/horizon/horizon-static-overrides.yaml b/stx-openstack-helm-fluxcd/stx-openstack-helm-fluxcd/manifests/horizon/horizon-static-overrides.yaml index f8dc2f23..7eaedac8 100644 --- a/stx-openstack-helm-fluxcd/stx-openstack-helm-fluxcd/manifests/horizon/horizon-static-overrides.yaml +++ b/stx-openstack-helm-fluxcd/stx-openstack-helm-fluxcd/manifests/horizon/horizon-static-overrides.yaml @@ -122,6 +122,8 @@ conf: keystone_multidomain_support: 'False' # OpenStack Help Documentation URL help_url: 'http://docs.openstack.org/2024.1/' + # https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins + csrf_trusted_origins: [] # Pass any settings to the end of local_settings.py raw: { } template: | @@ -169,6 +171,9 @@ conf: #CSRF_COOKIE_SECURE = True #SESSION_COOKIE_SECURE = True + # https://docs.djangoproject.com/en/dev/ref/settings/#csrf-trusted-origins + CSRF_TRUSTED_ORIGINS = [{{ include "helm-toolkit.utils.joinListWithCommaAndSingleQuotes" .Values.conf.horizon.local_settings.config.csrf_trusted_origins }}] + # Overrides for OpenStack API versions. Use this setting to force the # OpenStack dashboard to use a specific API version for a given service API. # Versions specified here should be integers or floats, not strings.