summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColleen Murphy <colleen.murphy@suse.com>2017-06-21 10:45:22 +0200
committerColleen Murphy <colleen.murphy@suse.com>2017-07-03 10:37:41 +0200
commit35a2fb35a712633a88850211de11d78e7f39c343 (patch)
tree9b9b1e27f7b141d51a72fe1e015986d006601c51
parent08a56228538d55c0686c61964e8052b67f1334f8 (diff)
Add support for a domain dropdown menu at login
On clouds that use domain-specific Identity configuration[1], a user must provide both their username and domain in order to log into horizon. Without this patch, users must be aware of their domain's name and enter it into a text box at login. This is sensible on public clouds, because supplying potential domains to an unauthenticated user exposes too much information about other customers and makes potential attacks easier. On private clouds, however, it is a hinderance to usability. For example, when migrating from a single-domain configuration to a multi-domain configuration, users must now guess or be informed of their domain in order to enter it in the text box. As another example, when keystone domains are mapped to Active Directory domains, the user may not be used to having to know their AD domains and would prefer to select a likely one based on their geographical location or department from a dropdown menu. This patch adds support for a new config option, "OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN" for enabling a dropdown menu instead of a textbox when MULTIDOMAIN_SUPPORT is enabled. The dropdown is disabled by default. If enabled, choices for domains to display and submit are configured in "OPENSTACK_KEYSTONE_DOMAIN_CHOICES". It is not possible to dynamically generate a list of domains before the user has authenticated and this would be a huge security hole if this was possible. Requiring the admin to statically set the domain list allows them to hide private domains like the service users domain. [1] https://docs.openstack.org/developer/keystone/configuration.html#domain-specific-drivers Change-Id: Ie0a7e36b9975342fab81ddebb87880608d3ef187 Needed-By: I71d64182524d1f54745d9e42347b3a605fa2a920
Notes
Notes (review): Code-Review+1: Itxaka Serrano Garcia <igarcia@suse.com> Code-Review+2: Radomir Dopieralski <openstack@sheep.art.pl> Workflow+1: Radomir Dopieralski <openstack@sheep.art.pl> Verified+2: Jenkins Submitted-by: Jenkins Submitted-at: Mon, 03 Jul 2017 21:01:15 +0000 Reviewed-on: https://review.openstack.org/476064 Project: openstack/django_openstack_auth Branch: refs/heads/master
-rw-r--r--openstack_auth/forms.py21
-rw-r--r--openstack_auth/tests/tests.py26
2 files changed, 42 insertions, 5 deletions
diff --git a/openstack_auth/forms.py b/openstack_auth/forms.py
index 0acb290..bacc9c0 100644
--- a/openstack_auth/forms.py
+++ b/openstack_auth/forms.py
@@ -61,11 +61,22 @@ class Login(django_auth_forms.AuthenticationForm):
61 'OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT', 61 'OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT',
62 False): 62 False):
63 last_domain = self.request.COOKIES.get('login_domain', None) 63 last_domain = self.request.COOKIES.get('login_domain', None)
64 self.fields['domain'] = forms.CharField( 64 if getattr(settings,
65 initial=last_domain, 65 'OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN',
66 label=_("Domain"), 66 False):
67 required=True, 67 self.fields['domain'] = forms.ChoiceField(
68 widget=forms.TextInput(attrs={"autofocus": "autofocus"})) 68 label=_("Domain"),
69 initial=last_domain,
70 required=True,
71 choices=getattr(settings,
72 'OPENSTACK_KEYSTONE_DOMAIN_CHOICES',
73 ()))
74 else:
75 self.fields['domain'] = forms.CharField(
76 initial=last_domain,
77 label=_("Domain"),
78 required=True,
79 widget=forms.TextInput(attrs={"autofocus": "autofocus"}))
69 self.fields['username'].widget = forms.widgets.TextInput() 80 self.fields['username'].widget = forms.widgets.TextInput()
70 fields_ordering = ['domain', 'username', 'password', 'region'] 81 fields_ordering = ['domain', 'username', 'password', 'region']
71 self.fields['region'].choices = self.get_region_choices() 82 self.fields['region'].choices = self.get_region_choices()
diff --git a/openstack_auth/tests/tests.py b/openstack_auth/tests/tests.py
index 4790f73..80e5a88 100644
--- a/openstack_auth/tests/tests.py
+++ b/openstack_auth/tests/tests.py
@@ -1091,6 +1091,32 @@ class OpenStackAuthTestsV3(OpenStackAuthTestsMixin,
1091 token=unscoped.auth_token) 1091 token=unscoped.auth_token)
1092 self.assertEqual(project_list, expected_projects) 1092 self.assertEqual(project_list, expected_projects)
1093 1093
1094 def test_login_form_multidomain(self):
1095 override = self.settings(OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT=True)
1096 override.enable()
1097 self.addCleanup(override.disable)
1098
1099 url = reverse('login')
1100 response = self.client.get(url)
1101 self.assertEqual(response.status_code, 200)
1102 self.assertContains(response, 'name="domain" type="text"')
1103
1104 def test_login_form_multidomain_dropdown(self):
1105 override = self.settings(OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT=True,
1106 OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN=True,
1107 OPENSTACK_KEYSTONE_DOMAIN_CHOICES=(
1108 ('Default', 'Default'),)
1109 )
1110 override.enable()
1111 self.addCleanup(override.disable)
1112
1113 url = reverse('login')
1114 response = self.client.get(url)
1115 self.assertEqual(response.status_code, 200)
1116 self.assertContains(response, 'select id="id_domain" name="domain"')
1117 self.assertContains(response, 'option value="Default"')
1118 settings.OPENSTACK_KEYSTONE_DOMAIN_DROPDOWN = False
1119
1094 1120
1095class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin, 1121class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin,
1096 OpenStackAuthFederatedTestsMixin, 1122 OpenStackAuthFederatedTestsMixin,