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