Andrew Bogott has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/334141 )

Change subject: Horizon:  update our custom auth hacks for mitaka
......................................................................

Horizon:  update our custom auth hacks for mitaka

Change-Id: I124ee747752a0bf60d8bffb6b8b265b0a40d88e2
---
M modules/openstack/files/mitaka/horizon/openstack_auth/backend.py
M modules/openstack/files/mitaka/horizon/openstack_auth/forms.py
2 files changed, 70 insertions(+), 11 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/operations/puppet 
refs/changes/41/334141/1

diff --git a/modules/openstack/files/mitaka/horizon/openstack_auth/backend.py 
b/modules/openstack/files/mitaka/horizon/openstack_auth/backend.py
index 10f5da4..d8f8346 100644
--- a/modules/openstack/files/mitaka/horizon/openstack_auth/backend.py
+++ b/modules/openstack/files/mitaka/horizon/openstack_auth/backend.py
@@ -20,7 +20,7 @@
 from django.conf import settings
 from django.utils.module_loading import import_string  # noqa
 from django.utils.translation import ugettext_lazy as _
-from keystoneclient import exceptions as keystone_exceptions
+from keystoneauth1 import exceptions as keystone_exceptions
 
 from openstack_auth import exceptions
 from openstack_auth import user as auth_user
@@ -110,7 +110,7 @@
 
         try:
             unscoped_auth_ref = unscoped_auth.get_access(session)
-        except keystone_exceptions.ConnectionRefused as exc:
+        except keystone_exceptions.ConnectFailure as exc:
             LOG.error(str(exc))
             msg = _('Unable to establish connection to keystone endpoint.')
             raise exceptions.KeystoneAuthException(msg)
@@ -129,15 +129,47 @@
         # Check expiry for our unscoped auth ref.
         self.check_auth_expiry(unscoped_auth_ref)
 
+        # domain support can require domain scoped tokens to perform
+        # identity operations depending on the policy files being used
+        # for keystone.
+        domain_auth = None
+        domain_auth_ref = None
+        if utils.get_keystone_version() >= 3 and 'user_domain_name' in kwargs:
+            try:
+                token = unscoped_auth_ref.auth_token
+                domain_auth = utils.get_token_auth_plugin(
+                    auth_url,
+                    token,
+                    domain_name=kwargs['user_domain_name'])
+                domain_auth_ref = domain_auth.get_access(session)
+            except Exception:
+                LOG.debug('Error getting domain scoped token.', exc_info=True)
+
         projects = plugin.list_projects(session,
                                         unscoped_auth,
                                         unscoped_auth_ref)
         # Attempt to scope only to enabled projects
         projects = [project for project in projects if project.enabled]
 
-        # Abort if there are no projects for this user
-        if not projects:
+        # Abort if there are no projects for this user and a valid domain
+        # token has not been obtained
+        #
+        # The valid use cases for a user login are:
+        #    Keystone v2: user must have a role on a project and be able
+        #                 to obtain a project scoped token
+        #    Keystone v3: 1) user can obtain a domain scoped token (user
+        #                    has a role on the domain they authenticated to),
+        #                    only, no roles on a project
+        #                 2) user can obtain a domain scoped token and has
+        #                    a role on a project in the domain they
+        #                    authenticated to (and can obtain a project scoped
+        #                    token)
+        #                 3) user cannot obtain a domain scoped token, but can
+        #                    obtain a project scoped token
+        if not projects and not domain_auth_ref:
             msg = _('You are not authorized for any projects.')
+            if utils.get_keystone_version() >= 3:
+                msg = _('You are not authorized for any projects or domains.')
             raise exceptions.KeystoneAuthException(msg)
 
         # the recent project id a user might have set in a cookie
@@ -172,8 +204,15 @@
             else:
                 break
         else:
-            msg = _("Unable to authenticate to any available projects.")
-            raise exceptions.KeystoneAuthException(msg)
+            # if the user can't obtain a project scoped token, set the scoped
+            # token to be the domain token, if valid
+            if domain_auth_ref:
+                scoped_auth = domain_auth
+                scoped_auth_ref = domain_auth_ref
+            else:
+                # if no domain or project token for user, abort
+                msg = _("Unable to authenticate to any available projects.")
+                raise exceptions.KeystoneAuthException(msg)
 
         # Check expiry for our new scoped token.
         self.check_auth_expiry(scoped_auth_ref)
@@ -185,19 +224,37 @@
         user = auth_user.create_user_from_token(
             request,
             auth_user.Token(scoped_auth_ref, unscoped_token=unscoped_token),
-            scoped_auth_ref.service_catalog.url_for(endpoint_type=interface))
+            scoped_auth_ref.service_catalog.url_for(service_type='identity',
+                                                    interface=interface))
 
         if request is not None:
             request.session['unscoped_token'] = unscoped_token
+            if domain_auth_ref:
+                # check django session engine, if using cookies, this will not
+                # work, as it will overflow the cookie so don't add domain
+                # scoped token to the session and put error in the log
+                if utils.using_cookie_backed_sessions():
+                    LOG.error('Using signed cookies as SESSION_ENGINE with '
+                              'OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT is '
+                              'enabled. This disables the ability to '
+                              'perform identity operations due to cookie size '
+                              'constraints.')
+                else:
+                    request.session['domain_token'] = domain_auth_ref
+
             request.user = user
+
+            # Custom hack for WMF:
             if 'extended_session' in kwargs and kwargs['extended_session']:
                 timeout = getattr(settings, "SESSION_TIMEOUT", 86400)
             else:
                 timeout = getattr(settings, "SESSION_SHORT_TIMEOUT", 1800)
+
             token_life = user.token.expires - datetime.datetime.now(pytz.utc)
 
             # Fix for 
https://bugs.launchpad.net/django-openstack-auth/+bug/1562452:
             session_time = min(timeout, int(token_life.total_seconds()))
+
             request.session.set_expiry(session_time)
 
             scoped_client = keystone_client_class(session=session,
@@ -228,8 +285,8 @@
             return set()
         # TODO(gabrielhurley): Integrate policy-driven RBAC
         #                      when supported by Keystone.
-        role_perms = set(["openstack.roles.%s" % role['name'].lower()
-                          for role in user.roles])
+        role_perms = {"openstack.roles.%s" % role['name'].lower()
+                      for role in user.roles}
 
         services = []
         for service in user.service_catalog:
@@ -241,8 +298,8 @@
                                in service.get('endpoints', [])]
             if user.services_region in service_regions:
                 services.append(service_type.lower())
-        service_perms = set(["openstack.services.%s" % service
-                             for service in services])
+        service_perms = {"openstack.services.%s" % service
+                         for service in services}
         return role_perms | service_perms
 
     def has_perm(self, user, perm, obj=None):
diff --git a/modules/openstack/files/mitaka/horizon/openstack_auth/forms.py 
b/modules/openstack/files/mitaka/horizon/openstack_auth/forms.py
index baee55c..af9c0da 100644
--- a/modules/openstack/files/mitaka/horizon/openstack_auth/forms.py
+++ b/modules/openstack/files/mitaka/horizon/openstack_auth/forms.py
@@ -73,7 +73,9 @@
         if getattr(settings,
                    'OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT',
                    False):
+            last_domain = self.request.COOKIES.get('login_domain', None)
             self.fields['domain'] = forms.CharField(
+                initial=last_domain,
                 label=_("Domain"),
                 required=True,
                 widget=forms.TextInput(attrs={"autofocus": "autofocus"}))

-- 
To view, visit https://gerrit.wikimedia.org/r/334141
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I124ee747752a0bf60d8bffb6b8b265b0a40d88e2
Gerrit-PatchSet: 1
Gerrit-Project: operations/puppet
Gerrit-Branch: production
Gerrit-Owner: Andrew Bogott <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to