コード例 #1
0
ファイル: base.py プロジェクト: lacoski/django-openstack-auth
    def get_access_info(self, keystone_auth):
        """Get the access info from an unscoped auth

        This function provides the base functionality that the
        plugins will use to authenticate and get the access info object.

        :param keystone_auth: keystoneauth1 identity plugin
        :raises: exceptions.KeystoneAuthException on auth failure
        :returns: keystoneclient.access.AccessInfo
        """
        session = utils.get_session()

        try:
            unscoped_auth_ref = keystone_auth.get_access(session)
        except keystone_exceptions.ConnectFailure as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneAuthException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)
        return unscoped_auth_ref
コード例 #2
0
ファイル: base.py プロジェクト: CCI-MOC/horizon
    def get_access_info(self, keystone_auth):
        """Get the access info from an unscoped auth

        This function provides the base functionality that the
        plugins will use to authenticate and get the access info object.

        :param keystone_auth: keystoneauth1 identity plugin
        :raises: exceptions.KeystoneAuthException on auth failure
        :returns: keystoneclient.access.AccessInfo
        """
        session = utils.get_session()

        try:
            unscoped_auth_ref = keystone_auth.get_access(session)
        except keystone_exceptions.ConnectFailure as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneAuthException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)
        return unscoped_auth_ref
コード例 #3
0
    def clean(self):
        region_id = self.cleaned_data.get('region')
        try:
            region = get_region_endpoint(region_id)
        except (ValueError, IndexError, TypeError):
            raise forms.ValidationError("Invalid region %r" % region_id)
        self.cleaned_data['region'] = region

        password = self.cleaned_data.get('password')
        original_password = self.cleaned_data.get('original_password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if password != confirm_password:
            raise forms.ValidationError(_('Passwords do not match.'))
        if password == original_password:
            raise forms.ValidationError(
                _('Old password and new password must be different.'))

        # Doing it here, to be able to raise ValidationError on failure.
        user_id = self.initial['user_id']
        session = utils.get_session(auth=DummyAuth(user_id))
        Client = utils.get_keystone_client().Client
        client = Client(session=session,
                        user_id=user_id,
                        auth_url=region,
                        endpoint=region)
        # This is needed so that keystoneclient doesn't try to authenticate.
        client.users.client.endpoint_override = region
        try:
            client.users.update_password(original_password, password)
        except Exception:
            raise forms.ValidationError(
                _("Unable to update the user password."))
        return self.cleaned_data
コード例 #4
0
ファイル: k2k.py プロジェクト: bopopescu/OpenStack-Ocata
    def get_plugin(self,
                   service_provider=None,
                   auth_url=None,
                   plugins=[],
                   **kwargs):
        """Authenticate using keystone to keystone federation.

        This plugin uses other v3 plugins to authenticate a user to a
        identity provider in order to authenticate the user to a service
        provider

        :param service_provider: service provider ID
        :param auth_url: Keystone auth url
        :param plugins: list of openstack_auth plugins to check
        :returns Keystone2Keystone keystone auth plugin
        """

        # service_provider being None prevents infinite recursion
        if utils.get_keystone_version() < 3 or not service_provider:
            return None

        keystone_idp_id = getattr(settings, 'KEYSTONE_PROVIDER_IDP_ID',
                                  'localkeystone')
        if service_provider == keystone_idp_id:
            return None

        for plugin in plugins:
            unscoped_idp_auth = plugin.get_plugin(plugins=plugins,
                                                  auth_url=auth_url,
                                                  **kwargs)
            if unscoped_idp_auth:
                break
        else:
            LOG.debug('Could not find base authentication backend for '
                      'K2K plugin with the provided credentials.')
            return None

        idp_exception = None
        scoped_idp_auth = None
        unscoped_auth_ref = base.BasePlugin.get_access_info(
            self, unscoped_idp_auth)
        try:
            scoped_idp_auth, __ = self.get_project_scoped_auth(
                unscoped_idp_auth, unscoped_auth_ref)
        except exceptions.KeystoneAuthException as idp_excp:
            idp_exception = idp_excp

        if not scoped_idp_auth or idp_exception:
            msg = 'Identity provider authentication Failed.'
            raise exceptions.KeystoneAuthException(msg)

        session = utils.get_session()

        if scoped_idp_auth.get_sp_auth_url(session, service_provider) is None:
            msg = _('Could not find service provider ID on Keystone.')
            raise exceptions.KeystoneAuthException(msg)

        unscoped_auth = v3_auth.Keystone2Keystone(
            base_plugin=scoped_idp_auth, service_provider=service_provider)
        return unscoped_auth
コード例 #5
0
ファイル: k2k.py プロジェクト: amotoki/horizon
    def get_plugin(self, service_provider=None, auth_url=None, plugins=None,
                   **kwargs):
        """Authenticate using keystone to keystone federation.

        This plugin uses other v3 plugins to authenticate a user to a
        identity provider in order to authenticate the user to a service
        provider

        :param service_provider: service provider ID
        :param auth_url: Keystone auth url
        :param plugins: list of openstack_auth plugins to check
        :returns Keystone2Keystone keystone auth plugin
        """

        # Avoid mutable default arg for plugins
        plugins = plugins or []

        # service_provider being None prevents infinite recursion
        if utils.get_keystone_version() < 3 or not service_provider:
            return None

        keystone_idp_id = getattr(settings, 'KEYSTONE_PROVIDER_IDP_ID',
                                  'localkeystone')
        if service_provider == keystone_idp_id:
            return None

        for plugin in plugins:
            unscoped_idp_auth = plugin.get_plugin(plugins=plugins,
                                                  auth_url=auth_url, **kwargs)
            if unscoped_idp_auth:
                break
        else:
            LOG.debug('Could not find base authentication backend for '
                      'K2K plugin with the provided credentials.')
            return None

        idp_exception = None
        scoped_idp_auth = None
        unscoped_auth_ref = base.BasePlugin.get_access_info(
            self, unscoped_idp_auth)
        try:
            scoped_idp_auth, __ = self.get_project_scoped_auth(
                unscoped_idp_auth, unscoped_auth_ref)
        except exceptions.KeystoneAuthException as idp_excp:
            idp_exception = idp_excp

        if not scoped_idp_auth or idp_exception:
            msg = 'Identity provider authentication Failed.'
            raise exceptions.KeystoneAuthException(msg)

        session = utils.get_session()

        if scoped_idp_auth.get_sp_auth_url(session, service_provider) is None:
            msg = _('Could not find service provider ID on Keystone.')
            raise exceptions.KeystoneAuthException(msg)

        unscoped_auth = v3_auth.Keystone2Keystone(
            base_plugin=scoped_idp_auth,
            service_provider=service_provider)
        return unscoped_auth
コード例 #6
0
def designateclient(request):
    session = utils.get_session()

    session.auth = token_endpoint.Token(
        base.url_for(request, 'dns') + "/v2",
        request.user.token.id)
    c = designate_client.Client(session=session)
    return c
コード例 #7
0
def login(request, **kwargs):
    '''
    Logs a user in using the :class:`~openstack_auth.forms.Login` form.
    Referenced from openstack_auth.views.login
    '''
    if not request.is_ajax():
        # If the user is already authenticated, redirect them to the
        # dashboard straight away, unless the 'next' parameter is set as it
        # usually indicates requesting access to a page that requires different
        # permissions.
        if request.user.is_authenticated():
            return HttpResponseRedirect('/')

    # Get our initial region for the form.
    form = functional.curry(openstack_auth_form)
    template_name = 'auth/login.html'
    res = django_auth_views.login(request,
                                  template_name=template_name,
                                  authentication_form=form,
                                  **kwargs)

    # Save the region in the cookie, this is used as the default
    # selected region next time the Login form loads.
    if request.method == "POST":
        openstack_auth_utils.set_response_cookie(
            res, 'login_region', request.POST.get('region', ''))
        openstack_auth_utils.set_response_cookie(
            res, 'login_domain', request.POST.get('domain', ''))

    # Set the session data here because django's session key rotation
    # will erase it if we set it earlier.
    print request.user.is_authenticated()
    if request.user.is_authenticated():
        openstack_auth_user.set_session_from_user(request, request.user)
        session = openstack_auth_utils.get_session()
        user_endpoint = settings.OPENSTACK_KEYSTONE_URL
        auth = openstack_auth_utils.get_token_auth_plugin(
            auth_url=user_endpoint,
            token=request.user.unscoped_token,
            project_id=settings.ADMIN_TENANT_ID)

        try:
            auth_ref = auth.get_access(session)
        except keystone_client_exceptions.ClientException as e:
            auth_ref = None

        if auth_ref:
            new_user = openstack_auth_user.create_user_from_token(
                request,
                openstack_auth_user.Token(auth_ref),
                endpoint=request.user.endpoint)
            openstack_auth_user.set_session_from_user(request, new_user)

    return res
コード例 #8
0
def login(request, **kwargs):
    '''
    Logs a user in using the :class:`~openstack_auth.forms.Login` form.
    Referenced from openstack_auth.views.login
    '''
    if not request.is_ajax():
        # If the user is already authenticated, redirect them to the
        # dashboard straight away, unless the 'next' parameter is set as it
        # usually indicates requesting access to a page that requires different
        # permissions.
        if request.user.is_authenticated():
            return HttpResponseRedirect('/')

    # Get our initial region for the form.
    form = functional.curry(openstack_auth_form)
    template_name = 'auth/login.html'
    res = django_auth_views.login(request,
                                  template_name=template_name,
                                  authentication_form=form,
                                  **kwargs)

    # Save the region in the cookie, this is used as the default
    # selected region next time the Login form loads.
    if request.method == "POST":
        openstack_auth_utils.set_response_cookie(res, 'login_region',
                                                 request.POST.get('region', ''))
        openstack_auth_utils.set_response_cookie(res, 'login_domain',
                                                 request.POST.get('domain', ''))

    # Set the session data here because django's session key rotation
    # will erase it if we set it earlier.
    print request.user.is_authenticated()
    if request.user.is_authenticated():
        openstack_auth_user.set_session_from_user(request, request.user)
        session = openstack_auth_utils.get_session()
        user_endpoint = settings.OPENSTACK_KEYSTONE_URL
        auth = openstack_auth_utils.get_token_auth_plugin(auth_url=user_endpoint,
                                       token=request.user.unscoped_token,
                                       project_id=settings.ADMIN_TENANT_ID)

        try:
            auth_ref = auth.get_access(session)
        except keystone_client_exceptions.ClientException as e:
            auth_ref = None

        if auth_ref:
            new_user = openstack_auth_user.create_user_from_token(request,
                                                                  openstack_auth_user.Token(auth_ref),
                                                                  endpoint=request.user.endpoint)
            openstack_auth_user.set_session_from_user(request, new_user)

    return res
コード例 #9
0
ファイル: base.py プロジェクト: lacoski/django-openstack-auth
    def get_domain_scoped_auth(self,
                               unscoped_auth,
                               unscoped_auth_ref,
                               domain_name=None):
        """Get the domain scoped keystone auth and access info

        This function returns a domain scoped keystone token plugin
        and AccessInfo object.

        :param unscoped_auth: keystone auth plugin
        :param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
        :param domain_name: domain that we should try to scope to
        :return: keystone token auth plugin, AccessInfo object
        """
        session = utils.get_session()
        auth_url = unscoped_auth.auth_url

        if utils.get_keystone_version() < 3:
            return None, None
        if domain_name:
            domains = [domain_name]
        else:
            domains = self.list_domains(session, unscoped_auth,
                                        unscoped_auth_ref)
            domains = [domain.name for domain in domains if domain.enabled]

        # 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
        for domain_name in domains:
            token = unscoped_auth_ref.auth_token
            domain_auth = utils.get_token_auth_plugin(auth_url,
                                                      token,
                                                      domain_name=domain_name)
            try:
                domain_auth_ref = domain_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                LOG.info(
                    'Attempted scope to domain %s failed, will attempt '
                    'to scope to another domain.', domain_name)
                pass
            else:
                if len(domains) > 1:
                    LOG.info(
                        "More than one valid domain found for user %s,"
                        " scoping to %s",
                        (unscoped_auth_ref.user_id, domain_name))
                break
        return domain_auth, domain_auth_ref
コード例 #10
0
def switch(request, tenant_id, redirect_field_name=auth.REDIRECT_FIELD_NAME):
    """Switches an authenticated user from one project to another."""
    LOG.debug('Switching to tenant %s for user "%s".'
              % (tenant_id, request.user.username))

    endpoint = utils.fix_auth_url_version(request.user.endpoint)
    session = utils.get_session()
    # Keystone can be configured to prevent exchanging a scoped token for
    # another token. Always use the unscoped token for requesting a
    # scoped token.
    unscoped_token = request.user.unscoped_token
    auth = utils.get_token_auth_plugin(auth_url=endpoint,
                                       token=unscoped_token,
                                       project_id=tenant_id)

    try:
        auth_ref = auth.get_access(session)
        msg = 'Project switch successful for user "%(username)s".' % \
            {'username': request.user.username}
        LOG.info(msg)
    except keystone_exceptions.ClientException:
        msg = (
            _('Project switch failed for user "%(username)s".') %
            {'username': request.user.username})
        messages.error(request, msg)
        auth_ref = None
        LOG.exception('An error occurred while switching sessions.')

    # Ensure the user-originating redirection url is safe.
    # Taken from django.contrib.auth.views.login()
    redirect_to = request.REQUEST.get(redirect_field_name, '')
    if not is_safe_url(url=redirect_to, host=request.get_host()):
        redirect_to = settings.LOGIN_REDIRECT_URL

    if auth_ref:
        old_endpoint = request.session.get('region_endpoint')
        old_token = request.session.get('token')
        if old_token and old_endpoint and old_token.id != auth_ref.auth_token:
            delete_token(endpoint=old_endpoint, token_id=old_token.id)
        user = auth_user.create_user_from_token(
            request,
            auth_user.Token(auth_ref, unscoped_token=unscoped_token),
            endpoint)
        auth_user.set_session_from_user(request, user)
        message = (
            _('Switch to project "%(project_name)s" successful.') %
            {'project_name': request.user.project_name})
        messages.success(request, message)
    response = shortcuts.redirect(redirect_to)
    utils.set_response_cookie(response, 'recent_project',
                              request.user.project_id)
    return response
コード例 #11
0
def switch(request, project_id=None):
    if not project_id:
        data = json.loads(request.body)
        tenant_id = data['project_id']
    else:
        tenant_id = project_id
    LOG.debug('Switching to tenant %s for user "%s".', tenant_id,
              request.user.username)

    endpoint, __ = utils.fix_auth_url_version_prefix(request.user.endpoint)
    session = utils.get_session()

    unscoped_token = request.user.unscoped_token
    auth = utils.get_token_auth_plugin(auth_url=endpoint,
                                       token=unscoped_token,
                                       project_id=tenant_id)

    try:
        auth_ref = auth.get_access(session)
        msg = 'Project switch successful for user "%(username)s".' % \
            {'username': request.user.username}
        LOG.info(msg)
    except keystone_exceptions.ClientException:
        msg = (_('Project switch failed for user "%(username)s".') % {
            'username': request.user.username
        })
        messages.error(request, msg)
        auth_ref = None
        LOG.exception('An error occurred while switching sessions.')

    if auth_ref:
        user = auth_user.create_user_from_token(
            request, auth_user.Token(auth_ref, unscoped_token=unscoped_token),
            endpoint)
        auth_user.set_session_from_user(request, user)
        message = (_('Switch to project "%(project_name)s" successful.') % {
            'project_name': request.user.project_name
        })
        messages.success(request, message)
        # utils.set_response_cookie(response, 'recent_project',
        #                           request.user.project_id)

        print({
            "tenant_id": request.user.tenant_id,
            "tenant_name": request.user.tenant_name,
            "username": request.user.username
        })
        return JsonResponse("success", safe=False)

    else:
        return JsonResponse("failed", status=400, safe=False)
コード例 #12
0
ファイル: base.py プロジェクト: deponian/horizon
    def get_domain_scoped_auth(self, unscoped_auth, unscoped_auth_ref,
                               domain_name=None):
        """Get the domain scoped keystone auth and access info

        This function returns a domain scoped keystone token plugin
        and AccessInfo object.

        :param unscoped_auth: keystone auth plugin
        :param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
        :param domain_name: domain that we should try to scope to
        :return: keystone token auth plugin, AccessInfo object
        """
        session = utils.get_session()
        auth_url = unscoped_auth.auth_url

        if utils.get_keystone_version() < 3:
            return None, None
        if domain_name:
            domains = [domain_name]
        else:
            domains = self.list_domains(session,
                                        unscoped_auth,
                                        unscoped_auth_ref)
            domains = [domain.name for domain in domains if domain.enabled]

        # 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
        for domain_name in domains:
            token = unscoped_auth_ref.auth_token
            domain_auth = utils.get_token_auth_plugin(
                auth_url,
                token,
                domain_name=domain_name)
            try:
                domain_auth_ref = domain_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                LOG.info('Attempted scope to domain %s failed, will attempt '
                         'to scope to another domain.', domain_name)
                pass
            else:
                if len(domains) > 1:
                    LOG.info("More than one valid domain found for user %s,"
                             " scoping to %s",
                             (unscoped_auth_ref.user_id, domain_name))
                break
        return domain_auth, domain_auth_ref
コード例 #13
0
ファイル: base.py プロジェクト: lacoski/django-openstack-auth
    def get_project_scoped_auth(self,
                                unscoped_auth,
                                unscoped_auth_ref,
                                recent_project=None):
        """Get the project scoped keystone auth and access info

        This function returns a project scoped keystone token plugin
        and AccessInfo object.

        :param unscoped_auth: keystone auth plugin
        :param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
        :param recent_project: project that we should try to scope to
        :return: keystone token auth plugin, AccessInfo object
        """
        auth_url = unscoped_auth.auth_url
        session = utils.get_session()

        projects = self.list_projects(session, unscoped_auth,
                                      unscoped_auth_ref)
        # Attempt to scope only to enabled projects
        projects = [project for project in projects if project.enabled]

        # if a most recent project was found, try using it first
        if recent_project:
            for pos, project in enumerate(projects):
                if project.id == recent_project:
                    # move recent project to the beginning
                    projects.pop(pos)
                    projects.insert(0, project)
                    break

        scoped_auth = None
        scoped_auth_ref = None
        for project in projects:
            token = unscoped_auth_ref.auth_token
            scoped_auth = utils.get_token_auth_plugin(auth_url,
                                                      token=token,
                                                      project_id=project.id)
            try:
                scoped_auth_ref = scoped_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                LOG.info(
                    'Attempted scope to project %s failed, will attempt '
                    'to scope to another project.', project.name)
                pass
            else:
                break

        return scoped_auth, scoped_auth_ref
コード例 #14
0
ファイル: heat.py プロジェクト: tliu88/stx-horizon
def get_new_user_token_from(request):
    """Generate new token for the given request to use in the context"""
    tenant_id = request.user.project_id

    endpoint = auth_utils.fix_auth_url_version(request.user.endpoint)
    session = auth_utils.get_session()
    # Keystone can be configured to prevent exchanging a scoped token for
    # another token. Always use the unscoped token for requesting a
    # scoped token.
    unscoped_token = request.user.unscoped_token
    auth = auth_utils.get_token_auth_plugin(auth_url=endpoint,
                                            token=unscoped_token,
                                            project_id=tenant_id)
    auth_ref = auth.get_access(session)
    return auth_ref.auth_token
コード例 #15
0
ファイル: base.py プロジェクト: deponian/horizon
    def get_project_scoped_auth(self, unscoped_auth, unscoped_auth_ref,
                                recent_project=None):
        """Get the project scoped keystone auth and access info

        This function returns a project scoped keystone token plugin
        and AccessInfo object.

        :param unscoped_auth: keystone auth plugin
        :param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
        :param recent_project: project that we should try to scope to
        :return: keystone token auth plugin, AccessInfo object
        """
        auth_url = unscoped_auth.auth_url
        session = utils.get_session()

        projects = self.list_projects(
            session, unscoped_auth, unscoped_auth_ref)
        # Attempt to scope only to enabled projects
        projects = [project for project in projects if project.enabled]

        # if a most recent project was found, try using it first
        if recent_project:
            for pos, project in enumerate(projects):
                if project.id == recent_project:
                    # move recent project to the beginning
                    projects.pop(pos)
                    projects.insert(0, project)
                    break

        scoped_auth = None
        scoped_auth_ref = None
        for project in projects:
            token = unscoped_auth_ref.auth_token
            scoped_auth = utils.get_token_auth_plugin(auth_url,
                                                      token=token,
                                                      project_id=project.id)
            try:
                scoped_auth_ref = scoped_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                LOG.info('Attempted scope to project %s failed, will attempt '
                         'to scope to another project.', project.name)
                pass
            else:
                break

        return scoped_auth, scoped_auth_ref
コード例 #16
0
ファイル: views.py プロジェクト: 571451370/devstack_mitaka
def delete_token(endpoint, token_id):
    """Delete a token."""
    try:
        endpoint = utils.fix_auth_url_version(endpoint)

        session = utils.get_session()
        auth_plugin = token_endpoint.Token(endpoint=endpoint, token=token_id)
        client = utils.get_keystone_client().Client(session=session,
                                                    auth=auth_plugin)
        if utils.get_keystone_version() >= 3:
            client.tokens.revoke_token(token=token_id)
        else:
            client.tokens.delete(token=token_id)

        LOG.info('Deleted token %s' % token_id)
    except keystone_exceptions.ClientException:
        LOG.info('Could not delete token')
コード例 #17
0
def switch_system_scope(request, redirect_field_name=auth.REDIRECT_FIELD_NAME):
    """Switches an authenticated user from one system to another."""
    LOG.debug('Switching to system scope for user "%s".',
              request.user.username)

    endpoint, __ = utils.fix_auth_url_version_prefix(request.user.endpoint)
    session = utils.get_session()
    # Keystone can be configured to prevent exchanging a scoped token for
    # another token. Always use the unscoped token for requesting a
    # scoped token.
    unscoped_token = request.user.unscoped_token
    auth = utils.get_token_auth_plugin(auth_url=endpoint,
                                       token=unscoped_token,
                                       system_scope='all')

    try:
        auth_ref = auth.get_access(session)
    except keystone_exceptions.ClientException:
        msg = (_('System switch failed for user "%(username)s".') % {
            'username': request.user.username
        })
        messages.error(request, msg)
        auth_ref = None
        LOG.exception('An error occurred while switching sessions.')
    else:
        msg = 'System switch successful for user "%(username)s".' % \
            {'username': request.user.username}
        LOG.info(msg)

    # Ensure the user-originating redirection url is safe.
    # Taken from django.contrib.auth.views.login()
    redirect_to = request.GET.get(redirect_field_name, '')
    if not http.is_safe_url(url=redirect_to,
                            allowed_hosts=[request.get_host()]):
        redirect_to = settings.LOGIN_REDIRECT_URL

    if auth_ref:
        user = auth_user.create_user_from_token(
            request, auth_user.Token(auth_ref, unscoped_token=unscoped_token),
            endpoint)
        auth_user.set_session_from_user(request, user)
        message = _('Switch to system scope successful.')
        messages.success(request, message)
    response = shortcuts.redirect(redirect_to)
    return response
コード例 #18
0
def delete_token(endpoint, token_id):
    """Delete a token."""
    try:
        endpoint = utils.fix_auth_url_version(endpoint)

        session = utils.get_session()
        auth_plugin = token_endpoint.Token(endpoint=endpoint,
                                           token=token_id)
        client = utils.get_keystone_client().Client(session=session,
                                                    auth=auth_plugin)
        if utils.get_keystone_version() >= 3:
            client.tokens.revoke_token(token=token_id)
        else:
            client.tokens.delete(token=token_id)

        LOG.info('Deleted token %s' % token_id)
    except keystone_exceptions.ClientException:
        LOG.info('Could not delete token')
コード例 #19
0
ファイル: base.py プロジェクト: lostmap/horizon-prod
    def get_access_info(self, keystone_auth):
        """Get the access info from an unscoped auth

        This function provides the base functionality that the
        plugins will use to authenticate and get the access info object.

        :param keystone_auth: keystoneauth1 identity plugin
        :raises: exceptions.KeystoneAuthException on auth failure
        :returns: keystoneclient.access.AccessInfo
        """
        session = utils.get_session()

        try:
            unscoped_auth_ref = keystone_auth.get_access(session)
        except keystone_exceptions.ConnectFailure as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneConnectionException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            msg = str(exc)
            LOG.debug(msg)
            match = re.match(
                r"The password is expired and needs to be changed"
                r" for user: ([^.]*)[.].*", msg)
            if match:
                exc = exceptions.KeystonePassExpiredException(
                    _('Password expired.'))
                exc.user_id = match.group(1)
                raise exc
            msg = _('Invalid credentials.')
            raise exceptions.KeystoneCredentialsException(msg)
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)
        return unscoped_auth_ref
コード例 #20
0
ファイル: base.py プロジェクト: stackhpc/horizon
    def get_system_scoped_auth(self, unscoped_auth, unscoped_auth_ref,
                               system_scope):
        """Get the system scoped keystone auth and access info

        This function returns a system scoped keystone token plugin
        and AccessInfo object.

        :param unscoped_auth: keystone auth plugin
        :param unscoped_auth_ref: keystoneclient.access.AccessInfo` or None.
        :param system_scope: system that we should try to scope to
        :return: keystone token auth plugin, AccessInfo object
        """
        session = utils.get_session()
        auth_url = unscoped_auth.auth_url

        system_auth = None
        system_auth_ref = None
        token = unscoped_auth_ref.auth_token
        system_auth = utils.get_token_auth_plugin(
            auth_url,
            token,
            system_scope=system_scope)
        system_auth_ref = system_auth.get_access(session)
        return system_auth, system_auth_ref
コード例 #21
0
ファイル: backend.py プロジェクト: tomascribb10/horizon
    def authenticate(self, request, 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.")

        plugin, unscoped_auth = self._get_auth_backend(auth_url, **kwargs)

        # the recent project id a user might have set in a cookie
        recent_project = None
        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 or domains.')
            raise exceptions.KeystoneNoProjectsException(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 id_endpoints['identity']:
            if auth_url in id_endpoint.values():
                region_name = id_endpoint['region']
                break

        interface = settings.OPENSTACK_ENDPOINT_TYPE

        endpoint = scoped_auth_ref.service_catalog.url_for(
            service_type='identity',
            interface=interface,
            region_name=region_name)

        # 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 = settings.SESSION_TIMEOUT
            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
コード例 #22
0
ファイル: backend.py プロジェクト: CCI-MOC/horizon
    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.")

        plugin, unscoped_auth = self._get_auth_backend(auth_url, **kwargs)

        # 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
コード例 #23
0
    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 = utils.fix_auth_url_version(auth_url)

        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.warn('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)

        session = utils.get_session()
        keystone_client_class = utils.get_keystone_client().Client

        try:
            unscoped_auth_ref = unscoped_auth.get_access(session)
        except keystone_exceptions.ConnectionRefused as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneAuthException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)

        # Check expiry for our unscoped auth ref.
        self.check_auth_expiry(unscoped_auth_ref)

        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:
            msg = _('You are not authorized for any projects.')
            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')

        # if a most recent project was found, try using it first
        if recent_project:
            for pos, project in enumerate(projects):
                if project.id == recent_project:
                    # move recent project to the beginning
                    projects.pop(pos)
                    projects.insert(0, project)
                    break

        for project in projects:
            token = unscoped_auth_ref.auth_token
            scoped_auth = utils.get_token_auth_plugin(auth_url,
                                                      token=token,
                                                      project_id=project.id)

            try:
                scoped_auth_ref = scoped_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                pass
            else:
                break
        else:
            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)

        interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'public')

        # 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),
            scoped_auth_ref.service_catalog.url_for(endpoint_type=interface))

        if request is not None:
            request.session['unscoped_token'] = unscoped_token
            request.user = user
            timeout = getattr(settings, "SESSION_TIMEOUT", 3600)
            token_life = user.token.expires - datetime.datetime.now(pytz.utc)
            session_time = min(timeout, token_life.seconds)
            request.session.set_expiry(session_time)

            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
コード例 #24
0
    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 = utils.fix_auth_url_version(auth_url)

        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.warn('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)

        session = utils.get_session()
        keystone_client_class = utils.get_keystone_client().Client

        try:
            unscoped_auth_ref = unscoped_auth.get_access(session)
        except keystone_exceptions.ConnectFailure as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneAuthException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)

        # 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 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
        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')

        # if a most recent project was found, try using it first
        if recent_project:
            for pos, project in enumerate(projects):
                if project.id == recent_project:
                    # move recent project to the beginning
                    projects.pop(pos)
                    projects.insert(0, project)
                    break

        for project in projects:
            token = unscoped_auth_ref.auth_token
            scoped_auth = utils.get_token_auth_plugin(auth_url,
                                                      token=token,
                                                      project_id=project.id)

            try:
                scoped_auth_ref = scoped_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                pass
            else:
                break
        else:
            # 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)

        interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'public')

        # 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),
            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,
                                                  auth=scoped_auth)

            # Support client caching to save on auth calls.
            setattr(request, KEYSTONE_CLIENT_ATTR, scoped_client)

        LOG.debug('Authentication completed.')
        return user
コード例 #25
0
    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 = utils.fix_auth_url_version(auth_url)

        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)

        session = utils.get_session()
        keystone_client_class = utils.get_keystone_client().Client

        try:
            unscoped_auth_ref = unscoped_auth.get_access(session)
        except keystone_exceptions.ConnectFailure as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneAuthException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)

        # 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 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
        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')

        # if a most recent project was found, try using it first
        if recent_project:
            for pos, project in enumerate(projects):
                if project.id == recent_project:
                    # move recent project to the beginning
                    projects.pop(pos)
                    projects.insert(0, project)
                    break

        for project in projects:
            token = unscoped_auth_ref.auth_token
            scoped_auth = utils.get_token_auth_plugin(auth_url,
                                                      token=token,
                                                      project_id=project.id)

            try:
                scoped_auth_ref = scoped_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                pass
            else:
                break
        else:
            # 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)

        # 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 = utils.fix_auth_url_version(
            scoped_auth_ref.service_catalog.url_for(
                service_type='identity',
                interface=interface,
                region_name=region_name))

        # 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:
            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)

            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
コード例 #26
0
    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 = utils.fix_auth_url_version(auth_url)

        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.warn('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)

        session = utils.get_session()
        keystone_client_class = utils.get_keystone_client().Client

        try:
            unscoped_auth_ref = unscoped_auth.get_access(session)
        except keystone_exceptions.ConnectionRefused as exc:
            LOG.error(str(exc))
            msg = _('Unable to establish connection to keystone endpoint.')
            raise exceptions.KeystoneAuthException(msg)
        except (keystone_exceptions.Unauthorized,
                keystone_exceptions.Forbidden,
                keystone_exceptions.NotFound) as exc:
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(_('Invalid credentials.'))
        except (keystone_exceptions.ClientException,
                keystone_exceptions.AuthorizationFailure) as exc:
            msg = _("An error occurred authenticating. "
                    "Please try again later.")
            LOG.debug(str(exc))
            raise exceptions.KeystoneAuthException(msg)

        # Check expiry for our unscoped auth ref.
        self.check_auth_expiry(unscoped_auth_ref)

        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:
            msg = _('You are not authorized for any projects.')
            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:
            # Check if token is automatically scoped to default_project
            # grab the project from this token, to use as a default
            # if no recent_project is found in the cookie
            recent_project = request.COOKIES.get('recent_project',
                                                 unscoped_auth_ref.project_id)

        # if a most recent project was found, try using it first
        if recent_project:
            for pos, project in enumerate(projects):
                if project.id == recent_project:
                    # move recent project to the beginning
                    projects.pop(pos)
                    projects.insert(0, project)
                    break

        for project in projects:
            token = unscoped_auth_ref.auth_token
            scoped_auth = utils.get_token_auth_plugin(auth_url,
                                                      token=token,
                                                      project_id=project.id)

            try:
                scoped_auth_ref = scoped_auth.get_access(session)
            except (keystone_exceptions.ClientException,
                    keystone_exceptions.AuthorizationFailure):
                pass
            else:
                break
        else:
            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)

        interface = getattr(settings, 'OPENSTACK_ENDPOINT_TYPE', 'public')

        # 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),
            scoped_auth_ref.service_catalog.url_for(endpoint_type=interface))

        if request is not None:
            request.session['unscoped_token'] = unscoped_token
            request.user = user
            timeout = getattr(settings, "SESSION_TIMEOUT", 3600)
            token_life = user.token.expires - datetime.datetime.now(pytz.utc)
            session_time = min(timeout, token_life.seconds)
            request.session.set_expiry(session_time)

            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