Files
python-keystoneclient/keystoneclient/auth/identity/v3/federated.py
Brant Knudson a8d2bd2934 Mark abstractmethod bodies with nocover
abstractmethod bodies aren't going to be called by unit tests, so
there's no way to get coverage. The code in an abstractmethod body
should be marked with "# pragma: no cover" so that they don't show
up as missed in the coverage report.

Change-Id: I88a7481ab22f2ce1abfd62badc5f5048acc6929f
2015-10-21 13:35:53 -05:00

120 lines
4.3 KiB
Python

# 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.
import abc
from oslo_config import cfg
import six
from keystoneclient.auth.identity.v3 import base
from keystoneclient.auth.identity.v3 import token
__all__ = ('FederatedBaseAuth',)
@six.add_metaclass(abc.ABCMeta)
class FederatedBaseAuth(base.BaseAuth):
rescoping_plugin = token.Token
def __init__(self, auth_url, identity_provider, protocol, **kwargs):
"""Class constructor accepting following parameters:
:param auth_url: URL of the Identity Service
:type auth_url: string
:param identity_provider: Name of the Identity Provider the client
will authenticate against. This parameter
will be used to build a dynamic URL used to
obtain unscoped OpenStack token.
:type identity_provider: string
:param protocol: Protocol name configured on the keystone service
provider side
:type protocol: string
"""
super(FederatedBaseAuth, self).__init__(auth_url=auth_url, **kwargs)
self.identity_provider = identity_provider
self.protocol = protocol
@classmethod
def get_options(cls):
options = super(FederatedBaseAuth, cls).get_options()
options.extend([
cfg.StrOpt('identity-provider',
help="Identity Provider's name"),
cfg.StrOpt('protocol', help="Name of the federated protocol used "
"for federated authentication. Must "
"match its counterpart name "
"configured at the keystone service "
"provider. Typically values would be "
"'saml2' or 'oidc'.")
])
return options
@property
def federated_token_url(self):
"""Full URL where authorization data is sent."""
values = {
'host': self.auth_url.rstrip('/'),
'identity_provider': self.identity_provider,
'protocol': self.protocol
}
url = ("%(host)s/OS-FEDERATION/identity_providers/"
"%(identity_provider)s/protocols/%(protocol)s/auth")
url = url % values
return url
def _get_scoping_data(self):
return {'trust_id': self.trust_id,
'domain_id': self.domain_id,
'domain_name': self.domain_name,
'project_id': self.project_id,
'project_name': self.project_name,
'project_domain_id': self.project_domain_id,
'project_domain_name': self.project_domain_name}
def get_auth_ref(self, session, **kwargs):
"""Authenticate retrieve token information.
This is a multi-step process where a client does federated authn
receives an unscoped token.
If an unscoped token is successfully received and scoping information
is present then the token is rescoped to that target.
:param session: a session object to send out HTTP requests.
:type session: keystoneclient.session.Session
:returns: a token data representation
:rtype: :py:class:`keystoneclient.access.AccessInfo`
"""
auth_ref = self.get_unscoped_auth_ref(session)
scoping = self._get_scoping_data()
if any(scoping.values()):
token_plugin = self.rescoping_plugin(self.auth_url,
token=auth_ref.auth_token,
**scoping)
auth_ref = token_plugin.get_auth_ref(session)
return auth_ref
@abc.abstractmethod
def get_unscoped_auth_ref(self, session, **kwargs):
"""Fetch unscoped federated token."""
pass # pragma: no cover