Switch keystoneclient to keystoneauth
Implements blueprint: keystoneclient-to-keystoneauth Change-Id: Id66280e4da98302d1c5a40b8da0f72aa84f2e36a
This commit is contained in:
@@ -11,5 +11,5 @@ jsonschema!=2.5.0,<3.0.0,>=2.0.0 # MIT
|
|||||||
oslo.i18n>=2.1.0 # Apache-2.0
|
oslo.i18n>=2.1.0 # Apache-2.0
|
||||||
oslo.utils>=3.16.0 # Apache-2.0
|
oslo.utils>=3.16.0 # Apache-2.0
|
||||||
|
|
||||||
python-keystoneclient!=2.1.0,>=2.0.0 # Apache-2.0
|
keystoneauth1>=2.10.0 # Apache-2.0
|
||||||
osc-lib>=1.0.2 # Apache-2.0
|
osc-lib>=1.0.2 # Apache-2.0
|
||||||
|
@@ -13,14 +13,21 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from keystoneclient.v2_0 import client as ksclient
|
import six.moves.urllib.parse as urlparse
|
||||||
|
|
||||||
|
from keystoneauth1 import discover
|
||||||
|
from keystoneauth1 import exceptions as ka_exc
|
||||||
|
from keystoneauth1.identity import v2 as v2_auth
|
||||||
|
from keystoneauth1.identity import v3 as v3_auth
|
||||||
|
from keystoneauth1 import session
|
||||||
|
|
||||||
from zaqarclient.auth import base
|
from zaqarclient.auth import base
|
||||||
|
from zaqarclient import errors
|
||||||
|
|
||||||
|
|
||||||
# NOTE(flaper87): Some of the code below
|
# NOTE(flaper87): Some of the code below
|
||||||
# was brought to you by the very unique
|
# was brought to you by the very unique
|
||||||
# work of ceilometerclient.
|
# work of ceilometerclient and glanceclient.
|
||||||
class KeystoneAuth(base.AuthBackend):
|
class KeystoneAuth(base.AuthBackend):
|
||||||
"""Keystone Auth backend
|
"""Keystone Auth backend
|
||||||
|
|
||||||
@@ -38,24 +45,132 @@ class KeystoneAuth(base.AuthBackend):
|
|||||||
:type conf: `dict`
|
:type conf: `dict`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _get_ksclient(self, **kwargs):
|
def _get_keystone_session(self, **kwargs):
|
||||||
"""Get an endpoint and auth token from Keystone.
|
cacert = kwargs.pop('cacert', None)
|
||||||
|
cert = kwargs.pop('cert', None)
|
||||||
|
key = kwargs.pop('key', None)
|
||||||
|
insecure = kwargs.pop('insecure', False)
|
||||||
|
auth_url = kwargs.pop('auth_url', None)
|
||||||
|
project_id = kwargs.pop('project_id', None)
|
||||||
|
project_name = kwargs.pop('project_name', None)
|
||||||
|
token = kwargs.get('token')
|
||||||
|
|
||||||
:param kwargs: keyword args containing credentials:
|
if insecure:
|
||||||
* username: name of user
|
verify = False
|
||||||
* password: user's password
|
else:
|
||||||
* auth_url: endpoint to authenticate against
|
verify = cacert or True
|
||||||
* insecure: allow insecure SSL (no cert verification)
|
|
||||||
* project_{name|id}: name or ID of project
|
|
||||||
* region_name: Name of a region
|
|
||||||
* cacert:CA certificate
|
|
||||||
|
|
||||||
"""
|
if cert and key:
|
||||||
return ksclient.Client(**kwargs)
|
# passing cert and key together is deprecated in favour of the
|
||||||
|
# requests lib form of having the cert and key as a tuple
|
||||||
|
cert = (cert, key)
|
||||||
|
|
||||||
def _get_endpoint(self, client, **extra):
|
# create the keystone client session
|
||||||
"""Get an endpoint using the provided keystone client."""
|
ks_session = session.Session(verify=verify, cert=cert)
|
||||||
return client.service_catalog.url_for(**extra)
|
v2_auth_url, v3_auth_url = self._discover_auth_versions(ks_session,
|
||||||
|
auth_url)
|
||||||
|
|
||||||
|
username = kwargs.pop('username', None)
|
||||||
|
user_id = kwargs.pop('user_id', None)
|
||||||
|
user_domain_name = kwargs.pop('user_domain_name', None)
|
||||||
|
user_domain_id = kwargs.pop('user_domain_id', None)
|
||||||
|
project_domain_name = kwargs.pop('project_domain_name', None)
|
||||||
|
project_domain_id = kwargs.pop('project_domain_id', None)
|
||||||
|
auth = None
|
||||||
|
|
||||||
|
use_domain = (user_domain_id or user_domain_name or
|
||||||
|
project_domain_id or project_domain_name)
|
||||||
|
use_v3 = v3_auth_url and (use_domain or (not v2_auth_url))
|
||||||
|
use_v2 = v2_auth_url and not use_domain
|
||||||
|
|
||||||
|
if use_v3 and token:
|
||||||
|
auth = v3_auth.Token(
|
||||||
|
v3_auth_url,
|
||||||
|
token=token,
|
||||||
|
project_name=project_name,
|
||||||
|
project_id=project_id,
|
||||||
|
project_domain_name=project_domain_name,
|
||||||
|
project_domain_id=project_domain_id)
|
||||||
|
elif use_v2 and token:
|
||||||
|
auth = v2_auth.Token(
|
||||||
|
v2_auth_url,
|
||||||
|
token=token,
|
||||||
|
tenant_id=project_id,
|
||||||
|
tenant_name=project_name)
|
||||||
|
elif use_v3:
|
||||||
|
# The auth_url as v3 specified
|
||||||
|
# e.g. http://no.where:5000/v3
|
||||||
|
# Keystone will return only v3 as viable option
|
||||||
|
auth = v3_auth.Password(
|
||||||
|
v3_auth_url,
|
||||||
|
username=username,
|
||||||
|
password=kwargs.pop('password', None),
|
||||||
|
user_id=user_id,
|
||||||
|
user_domain_name=user_domain_name,
|
||||||
|
user_domain_id=user_domain_id,
|
||||||
|
project_name=project_name,
|
||||||
|
project_id=project_id,
|
||||||
|
project_domain_name=project_domain_name,
|
||||||
|
project_domain_id=project_domain_id)
|
||||||
|
elif use_v2:
|
||||||
|
# The auth_url as v2 specified
|
||||||
|
# e.g. http://no.where:5000/v2.0
|
||||||
|
# Keystone will return only v2 as viable option
|
||||||
|
auth = v2_auth.Password(
|
||||||
|
v2_auth_url,
|
||||||
|
username,
|
||||||
|
kwargs.pop('password', None),
|
||||||
|
tenant_id=project_id,
|
||||||
|
tenant_name=project_name)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise errors.ZaqarError('Unable to determine the Keystone version '
|
||||||
|
'to authenticate with using the given '
|
||||||
|
'auth_url.')
|
||||||
|
|
||||||
|
ks_session.auth = auth
|
||||||
|
return ks_session
|
||||||
|
|
||||||
|
def _discover_auth_versions(self, session, auth_url):
|
||||||
|
# Discover the API versions the server is supporting based on the
|
||||||
|
# given URL
|
||||||
|
v2_auth_url = None
|
||||||
|
v3_auth_url = None
|
||||||
|
try:
|
||||||
|
ks_discover = discover.Discover(session=session, url=auth_url)
|
||||||
|
v2_auth_url = ks_discover.url_for('2.0')
|
||||||
|
v3_auth_url = ks_discover.url_for('3.0')
|
||||||
|
except ka_exc.DiscoveryFailure:
|
||||||
|
raise
|
||||||
|
except ka_exc.ClientException:
|
||||||
|
# Identity service may not support discovery. In that case,
|
||||||
|
# try to determine version from auth_url
|
||||||
|
url_parts = urlparse.urlparse(auth_url)
|
||||||
|
(scheme, netloc, path, params, query, fragment) = url_parts
|
||||||
|
path = path.lower()
|
||||||
|
if path.startswith('/v3'):
|
||||||
|
v3_auth_url = auth_url
|
||||||
|
elif path.startswith('/v2'):
|
||||||
|
v2_auth_url = auth_url
|
||||||
|
else:
|
||||||
|
raise errors.ZaqarError('Unable to determine the Keystone '
|
||||||
|
'version to authenticate with '
|
||||||
|
'using the given auth_url.')
|
||||||
|
return v2_auth_url, v3_auth_url
|
||||||
|
|
||||||
|
def _get_endpoint(self, ks_session, **kwargs):
|
||||||
|
"""Get an endpoint using the provided keystone session."""
|
||||||
|
|
||||||
|
# Set service specific endpoint types
|
||||||
|
endpoint_type = kwargs.get('endpoint_type') or 'publicURL'
|
||||||
|
service_type = kwargs.get('service_type') or 'messaging'
|
||||||
|
region_name = kwargs.get('region_name')
|
||||||
|
|
||||||
|
endpoint = ks_session.get_endpoint(service_type=service_type,
|
||||||
|
interface=endpoint_type,
|
||||||
|
region_name=region_name)
|
||||||
|
|
||||||
|
return endpoint
|
||||||
|
|
||||||
def authenticate(self, api_version, request):
|
def authenticate(self, api_version, request):
|
||||||
"""Get an authtenticated client using credentials in the keyword args.
|
"""Get an authtenticated client using credentials in the keyword args.
|
||||||
@@ -70,30 +185,20 @@ class KeystoneAuth(base.AuthBackend):
|
|||||||
|
|
||||||
token = get_options('auth_token')
|
token = get_options('auth_token')
|
||||||
if not token or not request.endpoint:
|
if not token or not request.endpoint:
|
||||||
# NOTE(flaper87): Lets assume all the
|
|
||||||
# required information was provided
|
|
||||||
# either through env variables or CLI
|
|
||||||
# params. Let keystoneclient fail otherwise.
|
|
||||||
|
|
||||||
ks_kwargs = {}
|
ks_kwargs = {}
|
||||||
keys = ("username", "password", "project_id",
|
keys = ("username", "password", "project_id",
|
||||||
"project_name", "auth_url", "insecure",
|
"project_name", "auth_url", "insecure",
|
||||||
"cacert", "region_name")
|
"cacert", "region_name", "user_domain_name",
|
||||||
|
"user_domain_id", "project_domain_name",
|
||||||
|
"project_domain_id")
|
||||||
for k in keys:
|
for k in keys:
|
||||||
ks_kwargs.update({k: get_options(k)})
|
ks_kwargs.update({k: get_options(k)})
|
||||||
|
|
||||||
_ksclient = self._get_ksclient(**ks_kwargs)
|
ks_session = self._get_keystone_session(**ks_kwargs)
|
||||||
if not token:
|
if not token:
|
||||||
token = _ksclient.auth_token
|
token = ks_session.get_token()
|
||||||
|
|
||||||
if not request.endpoint:
|
if not request.endpoint:
|
||||||
extra = {
|
request.endpoint = self._get_endpoint(ks_session, **ks_kwargs)
|
||||||
'service_type': self.conf.get('os_service_type',
|
|
||||||
'messaging'),
|
|
||||||
'endpoint_type': self.conf.get('os_endpoint_type',
|
|
||||||
'publicURL'),
|
|
||||||
}
|
|
||||||
request.endpoint = self._get_endpoint(_ksclient, **extra)
|
|
||||||
|
|
||||||
# NOTE(flaper87): Update the request spec
|
# NOTE(flaper87): Update the request spec
|
||||||
# with the final token.
|
# with the final token.
|
||||||
|
Reference in New Issue
Block a user