Merge ~rodrigo-barbieri2010/ubuntu/+source/horizon:lp1827120_yoga into ~ubuntu-openstack-dev/ubuntu/+source/horizon:stable/yoga

Proposed by Rodrigo Barbieri
Status: Merged
Merged at revision: 16ace3d272f5fde1d020df30650d67ae39b04245
Proposed branch: ~rodrigo-barbieri2010/ubuntu/+source/horizon:lp1827120_yoga
Merge into: ~ubuntu-openstack-dev/ubuntu/+source/horizon:stable/yoga
Diff against target: 153 lines (+131/-0)
3 files modified
debian/changelog (+7/-0)
debian/patches/lp1827120.patch (+123/-0)
debian/patches/series (+1/-0)
Reviewer Review Type Date Requested Status
Ubuntu OpenStack uploaders Pending
Review via email: mp+434095@code.launchpad.net
To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/changelog b/debian/changelog
2index 9390a98..a8000c0 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,10 @@
6+horizon (4:22.1.0-0ubuntu3) jammy; urgency=medium
7+
8+ * d/p/lp1827120.patch: Fix missing project_id in application credential
9+ create when user has both project+domain admin role (LP#1827120).
10+
11+ -- Rodrigo Barbieri <rodrigo.barbieri@canonical.com> Mon, 05 Dec 2022 13:51:11 +0000
12+
13 horizon (4:22.1.0-0ubuntu2.1) UNRELEASED; urgency=medium
14
15 * d/gbp.conf: Create stable/yoga branch.
16diff --git a/debian/patches/lp1827120.patch b/debian/patches/lp1827120.patch
17new file mode 100644
18index 0000000..a99e513
19--- /dev/null
20+++ b/debian/patches/lp1827120.patch
21@@ -0,0 +1,123 @@
22+From 13e821a079134a458b24593d9593e0e5318e6cd6 Mon Sep 17 00:00:00 2001
23+From: Rodrigo Barbieri <rodrigo.barbieri2010@gmail.com>
24+Date: Wed, 7 Sep 2022 10:52:48 -0300
25+Subject: [PATCH] Fix app cred create without project_id for domain admins
26+
27+Users with domain admin role that are not cloud admins are
28+not able to get scoped context and create an application
29+credential with project_id, so this change forces the
30+scoped context in that particular case.
31+
32+Closes-bug: #1827120
33+Change-Id: I076a97a6f943ab74a2db8bc5179a7db194009db4
34+(cherry picked from commit 6eeaf9852478e25ff77c21117664ac126c5357a4)
35+(cherry picked from commit 778a52e66aeab883b31db729e04944eeecfec6a2)
36+---
37+ openstack_dashboard/api/keystone.py | 17 +++++--
38+ .../test/unit/api/test_keystone.py | 44 +++++++++++++++++++
39+ 2 files changed, 58 insertions(+), 3 deletions(-)
40+
41+diff --git a/openstack_dashboard/api/keystone.py b/openstack_dashboard/api/keystone.py
42+index d248a223d..b25443251 100644
43+--- a/openstack_dashboard/api/keystone.py
44++++ b/openstack_dashboard/api/keystone.py
45+@@ -120,7 +120,7 @@ def _get_endpoint_url(request, endpoint_type, catalog=None):
46+ return url
47+
48+
49+-def keystoneclient(request, admin=False):
50++def keystoneclient(request, admin=False, force_scoped=False):
51+ """Returns a client connected to the Keystone backend.
52+
53+ Several forms of authentication are supported:
54+@@ -152,7 +152,8 @@ def keystoneclient(request, admin=False):
55+
56+ # If user is Cloud Admin, Domain Admin or Mixed Domain Admin and there
57+ # is no domain context specified, use domain scoped token
58+- if is_domain_admin(request) and not is_domain_context_specified:
59++ if (is_domain_admin(request) and not is_domain_context_specified and
60++ not force_scoped):
61+ domain_token = request.session.get('domain_token')
62+ if domain_token:
63+ token_id = getattr(domain_token, 'auth_token', None)
64+@@ -995,7 +996,17 @@ def application_credential_create(request, name, secret=None,
65+ roles=None, unrestricted=False,
66+ access_rules=None):
67+ user = request.user.id
68+- manager = keystoneclient(request).application_credentials
69++ # NOTE(ganso): users with domain admin role that are not cloud admins are
70++ # not able to get scoped context and create an application credential with
71++ # project_id, so only in this particular case we force a scoped context
72++ force_scoped = False
73++ if (request.user.project_id and request.session.get("domain_token") and
74++ not policy.check(
75++ (("identity", "identity:update_domain"),), request)):
76++ force_scoped = True
77++
78++ manager = keystoneclient(
79++ request, force_scoped=force_scoped).application_credentials
80+ try:
81+ return manager.create(name=name, user=user, secret=secret,
82+ description=description, expires_at=expires_at,
83+diff --git a/openstack_dashboard/test/unit/api/test_keystone.py b/openstack_dashboard/test/unit/api/test_keystone.py
84+index 4598c2d50..71e8a6314 100644
85+--- a/openstack_dashboard/test/unit/api/test_keystone.py
86++++ b/openstack_dashboard/test/unit/api/test_keystone.py
87+@@ -21,6 +21,7 @@ from unittest import mock
88+
89+ from django.test.utils import override_settings
90+ from openstack_dashboard import api
91++from openstack_dashboard import policy
92+ from openstack_dashboard.test import helpers as test
93+
94+
95+@@ -164,3 +165,46 @@ class APIVersionTests(test.APIMockTestCase):
96+ keystoneclient.session.get_endpoint_data.assert_called_once_with(
97+ service_type='identity')
98+ self.assertEqual((3, 10), api_version)
99++
100++
101++class ApplicationCredentialsAPITests(test.APIMockTestCase):
102++
103++ @mock.patch.object(policy, 'check')
104++ @mock.patch.object(api.keystone, 'keystoneclient')
105++ def test_application_credential_create_domain_token_removed(
106++ self, mock_keystoneclient, mock_policy):
107++ self.request.session['domain_token'] = 'some_token'
108++ mock_policy.return_value = False
109++ api.keystone.application_credential_create(self.request, None)
110++ mock_keystoneclient.assert_called_once_with(
111++ self.request, force_scoped=True)
112++
113++ @mock.patch.object(policy, 'check')
114++ @mock.patch.object(api.keystone, 'keystoneclient')
115++ def test_application_credential_create_domain_token_not_removed_policy_true(
116++ self, mock_keystoneclient, mock_policy):
117++ self.request.session['domain_token'] = 'some_token'
118++ mock_policy.return_value = True
119++ api.keystone.application_credential_create(self.request, None)
120++ mock_keystoneclient.assert_called_once_with(
121++ self.request, force_scoped=False)
122++
123++ @mock.patch.object(policy, 'check')
124++ @mock.patch.object(api.keystone, 'keystoneclient')
125++ def test_application_credential_create_domain_token_not_removed_no_token(
126++ self, mock_keystoneclient, mock_policy):
127++ mock_policy.return_value = True
128++ api.keystone.application_credential_create(self.request, None)
129++ mock_keystoneclient.assert_called_once_with(
130++ self.request, force_scoped=False)
131++
132++ @mock.patch.object(policy, 'check')
133++ @mock.patch.object(api.keystone, 'keystoneclient')
134++ def test_application_credential_create_domain_token_not_removed_no_project(
135++ self, mock_keystoneclient, mock_policy):
136++ self.request.session['domain_token'] = 'some_token'
137++ mock_policy.return_value = True
138++ self.request.user.project_id = None
139++ api.keystone.application_credential_create(self.request, None)
140++ mock_keystoneclient.assert_called_once_with(
141++ self.request, force_scoped=False)
142+--
143+2.34.1
144+
145diff --git a/debian/patches/series b/debian/patches/series
146index 88198a3..f7cdd35 100644
147--- a/debian/patches/series
148+++ b/debian/patches/series
149@@ -2,3 +2,4 @@ fix-horizon-test-settings.patch
150 fix-dashboard-manage.patch
151 ubuntu_settings.patch
152 embedded-xstatic.patch
153+lp1827120.patch

Subscribers

People subscribed via source and target branches