summaryrefslogtreecommitdiff
path: root/openstack_auth/backend.py
diff options
context:
space:
mode:
Diffstat (limited to 'openstack_auth/backend.py')
-rw-r--r--openstack_auth/backend.py282
1 files changed, 0 insertions, 282 deletions
diff --git a/openstack_auth/backend.py b/openstack_auth/backend.py
deleted file mode 100644
index dae603a..0000000
--- a/openstack_auth/backend.py
+++ /dev/null
@@ -1,282 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-""" Module defining the Django auth backend class for the Keystone API. """
-
-import datetime
-import logging
-import pytz
-
-from django.conf import settings
-from django.utils.module_loading import import_string
-from django.utils.translation import ugettext_lazy as _
-
-from openstack_auth import exceptions
-from openstack_auth import user as auth_user
-from openstack_auth import utils
-
-
-LOG = logging.getLogger(__name__)
-
-
-KEYSTONE_CLIENT_ATTR = "_keystoneclient"
-
-
-class KeystoneBackend(object):
- """Django authentication backend for use with ``django.contrib.auth``."""
-
- def __init__(self):
- self._auth_plugins = None
-
- @property
- def auth_plugins(self):
- if self._auth_plugins is None:
- plugins = getattr(
- settings,
- 'AUTHENTICATION_PLUGINS',
- ['openstack_auth.plugin.password.PasswordPlugin',
- 'openstack_auth.plugin.token.TokenPlugin'])
-
- self._auth_plugins = [import_string(p)() for p in plugins]
-
- return self._auth_plugins
-
- def check_auth_expiry(self, auth_ref, margin=None):
- if not utils.is_token_valid(auth_ref, margin):
- msg = _("The authentication token issued by the Identity service "
- "has expired.")
- LOG.warning("The authentication token issued by the Identity "
- "service appears to have expired before it was "
- "issued. This may indicate a problem with either your "
- "server or client configuration.")
- raise exceptions.KeystoneAuthException(msg)
- return True
-
- def get_user(self, user_id):
- """Returns the current user from the session data.
-
- If authenticated, this return the user object based on the user ID
- and session data.
-
- .. note::
-
- This required monkey-patching the ``contrib.auth`` middleware
- to make the ``request`` object available to the auth backend class.
-
- """
- if (hasattr(self, 'request') and
- user_id == self.request.session["user_id"]):
- token = self.request.session['token']
- endpoint = self.request.session['region_endpoint']
- services_region = self.request.session['services_region']
- user = auth_user.create_user_from_token(self.request, token,
- endpoint, services_region)
- return user
- else:
- return None
-
- def authenticate(self, auth_url=None, **kwargs):
- """Authenticates a user via the Keystone Identity API."""
- LOG.debug('Beginning user authentication')
-
- if not auth_url:
- auth_url = settings.OPENSTACK_KEYSTONE_URL
-
- auth_url, url_fixed = utils.fix_auth_url_version_prefix(auth_url)
- if url_fixed:
- LOG.warning("The OPENSTACK_KEYSTONE_URL setting points to a v2.0 "
- "Keystone endpoint, but v3 is specified as the API "
- "version to use by Horizon. Using v3 endpoint for "
- "authentication.")
-
- for plugin in self.auth_plugins:
- unscoped_auth = plugin.get_plugin(auth_url=auth_url, **kwargs)
-
- if unscoped_auth:
- break
- else:
- msg = _('No authentication backend could be determined to '
- 'handle the provided credentials.')
- LOG.warning('No authentication backend could be determined to '
- 'handle the provided credentials. This is likely a '
- 'configuration error that should be addressed.')
- raise exceptions.KeystoneAuthException(msg)
-
- # the recent project id a user might have set in a cookie
- recent_project = None
- request = kwargs.get('request')
- if request:
- # Grab recent_project found in the cookie, try to scope
- # to the last project used.
- recent_project = request.COOKIES.get('recent_project')
- unscoped_auth_ref = plugin.get_access_info(unscoped_auth)
-
- # Check expiry for our unscoped auth ref.
- self.check_auth_expiry(unscoped_auth_ref)
-
- domain_name = kwargs.get('user_domain_name', None)
- domain_auth, domain_auth_ref = plugin.get_domain_scoped_auth(
- unscoped_auth, unscoped_auth_ref, domain_name)
- scoped_auth, scoped_auth_ref = plugin.get_project_scoped_auth(
- unscoped_auth, unscoped_auth_ref, recent_project=recent_project)
-
- # 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 scoped_auth_ref and domain_auth_ref:
- # if the user can't obtain a project scoped token, set the scoped
- # token to be the domain token, if valid
- scoped_auth = domain_auth
- scoped_auth_ref = domain_auth_ref
- elif not scoped_auth_ref 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)
-
- # Check expiry for our new scoped token.
- self.check_auth_expiry(scoped_auth_ref)
-
- # We want to try to use the same region we just logged into
- # which may or may not be the default depending upon the order
- # keystone uses
- region_name = None
- id_endpoints = scoped_auth_ref.service_catalog.\
- get_endpoints(service_type='identity')
- for id_endpoint in [cat for cat in id_endpoints['identity']]:
- if auth_url in id_endpoint.values():
- region_name = id_endpoint['region']
- break
-
- interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'public')
-
- endpoint, url_fixed = utils.fix_auth_url_version_prefix(
- scoped_auth_ref.service_catalog.url_for(
- service_type='identity',
- interface=interface,
- region_name=region_name))
- if url_fixed:
- LOG.warning("The Keystone URL in service catalog points to a v2.0 "
- "Keystone endpoint, but v3 is specified as the API "
- "version to use by Horizon. Using v3 endpoint for "
- "authentication.")
-
- # If we made it here we succeeded. Create our User!
- unscoped_token = unscoped_auth_ref.auth_token
-
- user = auth_user.create_user_from_token(
- request,
- auth_user.Token(scoped_auth_ref, unscoped_token=unscoped_token),
- endpoint,
- services_region=region_name)
-
- if request is not None:
- # if no k2k providers exist then the function returns quickly
- utils.store_initial_k2k_session(auth_url, request, scoped_auth_ref,
- unscoped_auth_ref)
- 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
- timeout = getattr(settings, "SESSION_TIMEOUT", 3600)
- token_life = user.token.expires - datetime.datetime.now(pytz.utc)
- session_time = min(timeout, int(token_life.total_seconds()))
- request.session.set_expiry(session_time)
-
- keystone_client_class = utils.get_keystone_client().Client
- session = utils.get_session()
- scoped_client = keystone_client_class(session=session,
- auth=scoped_auth)
-
- # Support client caching to save on auth calls.
- setattr(request, KEYSTONE_CLIENT_ATTR, scoped_client)
-
- LOG.debug('Authentication completed.')
- return user
-
- def get_group_permissions(self, user, obj=None):
- """Returns an empty set since Keystone doesn't support "groups"."""
- # Keystone V3 added "groups". The Auth token response includes the
- # roles from the user's Group assignment. It should be fine just
- # returning an empty set here.
- return set()
-
- def get_all_permissions(self, user, obj=None):
- """Returns a set of permission strings that the user has.
-
- This permission available to the user is derived from the user's
- Keystone "roles".
-
- The permissions are returned as ``"openstack.{{ role.name }}"``.
- """
- if user.is_anonymous() or obj is not None:
- return set()
- # TODO(gabrielhurley): Integrate policy-driven RBAC
- # when supported by Keystone.
- role_perms = {utils.get_role_permission(role['name'])
- for role in user.roles}
-
- services = []
- for service in user.service_catalog:
- try:
- service_type = service['type']
- except KeyError:
- continue
- service_regions = [utils.get_endpoint_region(endpoint) for endpoint
- in service.get('endpoints', [])]
- if user.services_region in service_regions:
- services.append(service_type.lower())
- service_perms = {"openstack.services.%s" % service
- for service in services}
- return role_perms | service_perms
-
- def has_perm(self, user, perm, obj=None):
- """Returns True if the given user has the specified permission."""
- if not user.is_active:
- return False
- return perm in self.get_all_permissions(user, obj)
-
- def has_module_perms(self, user, app_label):
- """Returns True if user has any permissions in the given app_label.
-
- Currently this matches for the app_label ``"openstack"``.
- """
- if not user.is_active:
- return False
- for perm in self.get_all_permissions(user):
- if perm[:perm.index('.')] == app_label:
- return True
- return False