2012-09-11 11:20:16 -05:00
|
|
|
# Copyright 2011 Nebula, Inc.
|
|
|
|
# All Rights Reserved.
|
|
|
|
#
|
|
|
|
# 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 json
|
|
|
|
import logging
|
|
|
|
|
2013-02-13 22:52:05 -06:00
|
|
|
from keystoneclient import exceptions
|
2012-09-11 11:20:16 -05:00
|
|
|
from keystoneclient.v2_0 import client
|
2012-09-11 15:42:38 -05:00
|
|
|
from keystoneclient.v3 import credentials
|
2012-09-11 12:32:01 -05:00
|
|
|
from keystoneclient.v3 import domains
|
2013-02-13 22:52:05 -06:00
|
|
|
from keystoneclient.v3 import endpoints
|
2012-12-07 16:47:56 +00:00
|
|
|
from keystoneclient.v3 import groups
|
2012-09-11 11:44:05 -05:00
|
|
|
from keystoneclient.v3 import policies
|
2012-09-11 15:38:22 -05:00
|
|
|
from keystoneclient.v3 import projects
|
2012-09-11 15:34:56 -05:00
|
|
|
from keystoneclient.v3 import roles
|
2012-09-11 11:22:30 -05:00
|
|
|
from keystoneclient.v3 import services
|
2012-09-11 15:40:37 -05:00
|
|
|
from keystoneclient.v3 import users
|
2012-09-11 11:20:16 -05:00
|
|
|
|
|
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class Client(client.Client):
|
|
|
|
"""Client for the OpenStack Identity API v3.
|
|
|
|
|
2013-02-13 22:52:05 -06:00
|
|
|
:param string user_id: User ID for authentication. (optional)
|
2012-09-11 11:20:16 -05:00
|
|
|
:param string username: Username for authentication. (optional)
|
2013-02-13 22:52:05 -06:00
|
|
|
:param string user_domain_id: User's domain ID for authentication.
|
|
|
|
(optional)
|
|
|
|
:param string user_domain_name: User's domain name for authentication.
|
|
|
|
(optional)
|
2012-09-11 11:20:16 -05:00
|
|
|
:param string password: Password for authentication. (optional)
|
|
|
|
:param string token: Token for authentication. (optional)
|
2013-02-13 22:52:05 -06:00
|
|
|
:param string domain_id: Domain ID for domain scoping. (optional)
|
|
|
|
:param string domain_name: Domain name for domain scoping. (optional)
|
|
|
|
:param string project_id: Project ID for project scoping. (optional)
|
|
|
|
:param string project_name: Project name for project scoping. (optional)
|
|
|
|
:param string project_domain_id: Project's domain ID for project
|
|
|
|
scoping. (optional)
|
|
|
|
:param string project_domain_name: Project's domain name for project
|
|
|
|
scoping. (optional)
|
|
|
|
:param string tenant_name: Tenant name. (optional)
|
|
|
|
The tenant_name keyword argument is deprecated,
|
|
|
|
use project_name instead.
|
|
|
|
:param string tenant_id: Tenant id. (optional)
|
|
|
|
The tenant_id keyword argument is deprecated,
|
|
|
|
use project_id instead.
|
|
|
|
:param string auth_url: Identity service endpoint for authorization.
|
2012-09-11 11:20:16 -05:00
|
|
|
:param string region_name: Name of a region to select when choosing an
|
|
|
|
endpoint from the service catalog.
|
2013-02-13 22:52:05 -06:00
|
|
|
:param string endpoint: A user-supplied endpoint URL for the identity
|
2012-09-11 11:20:16 -05:00
|
|
|
service. Lazy-authentication is possible for API
|
|
|
|
service calls if endpoint is set at
|
2013-02-13 22:52:05 -06:00
|
|
|
instantiation. (optional)
|
2012-09-11 11:20:16 -05:00
|
|
|
:param integer timeout: Allows customization of the timeout for client
|
|
|
|
http requests. (optional)
|
|
|
|
|
|
|
|
Example::
|
|
|
|
|
|
|
|
>>> from keystoneclient.v3 import client
|
2013-02-13 22:52:05 -06:00
|
|
|
>>> keystone = client.Client(user_domain_name=DOMAIN_NAME,
|
|
|
|
... username=USER,
|
2013-05-28 09:22:03 -05:00
|
|
|
... password=PASS,
|
2013-02-13 22:52:05 -06:00
|
|
|
... project_domain_name=PROJECT_DOMAIN_NAME,
|
|
|
|
... project_name=PROJECT_NAME,
|
2013-05-28 09:22:03 -05:00
|
|
|
... auth_url=KEYSTONE_URL)
|
|
|
|
...
|
2013-02-13 22:52:05 -06:00
|
|
|
>>> keystone.projects.list()
|
2012-09-11 11:20:16 -05:00
|
|
|
...
|
|
|
|
>>> user = keystone.users.get(USER_ID)
|
|
|
|
>>> user.delete()
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
2013-02-13 22:52:05 -06:00
|
|
|
def __init__(self, **kwargs):
|
2013-06-21 19:04:50 +02:00
|
|
|
"""Initialize a new client for the Keystone v3 API."""
|
2013-02-13 22:52:05 -06:00
|
|
|
super(Client, self).__init__(**kwargs)
|
2012-09-11 11:20:16 -05:00
|
|
|
|
2013-02-13 22:52:05 -06:00
|
|
|
self.version = 'v3'
|
2012-09-11 15:42:38 -05:00
|
|
|
self.credentials = credentials.CredentialManager(self)
|
2012-09-11 11:40:25 -05:00
|
|
|
self.endpoints = endpoints.EndpointManager(self)
|
2012-09-11 12:32:01 -05:00
|
|
|
self.domains = domains.DomainManager(self)
|
2012-12-07 16:47:56 +00:00
|
|
|
self.groups = groups.GroupManager(self)
|
2012-09-11 11:44:05 -05:00
|
|
|
self.policies = policies.PolicyManager(self)
|
2012-09-11 15:38:22 -05:00
|
|
|
self.projects = projects.ProjectManager(self)
|
2012-09-11 15:34:56 -05:00
|
|
|
self.roles = roles.RoleManager(self)
|
2012-09-11 11:22:30 -05:00
|
|
|
self.services = services.ServiceManager(self)
|
2012-09-11 15:40:37 -05:00
|
|
|
self.users = users.UserManager(self)
|
2012-09-11 11:22:30 -05:00
|
|
|
|
2012-09-11 11:20:16 -05:00
|
|
|
def serialize(self, entity):
|
|
|
|
return json.dumps(entity, sort_keys=True)
|
2013-02-13 22:52:05 -06:00
|
|
|
|
|
|
|
def process_token(self):
|
2013-06-21 19:04:50 +02:00
|
|
|
"""Extract and process information from the new auth_ref.
|
2013-02-13 22:52:05 -06:00
|
|
|
|
|
|
|
And set the relevant authentication information.
|
|
|
|
"""
|
|
|
|
super(Client, self).process_token()
|
|
|
|
if self.auth_ref.domain_scoped:
|
|
|
|
if not self.auth_ref.domain_id:
|
|
|
|
raise exceptions.AuthorizationFailure(
|
|
|
|
"Token didn't provide domain_id")
|
|
|
|
if self.management_url is None and self.auth_ref.management_url:
|
|
|
|
self.management_url = self.auth_ref.management_url[0]
|
|
|
|
self.domain_name = self.auth_ref.domain_name
|
|
|
|
self.domain_id = self.auth_ref.domain_id
|
|
|
|
|
|
|
|
def get_raw_token_from_identity_service(self, auth_url, user_id=None,
|
|
|
|
username=None,
|
|
|
|
user_domain_id=None,
|
|
|
|
user_domain_name=None,
|
|
|
|
password=None,
|
|
|
|
domain_id=None, domain_name=None,
|
|
|
|
project_id=None, project_name=None,
|
|
|
|
project_domain_id=None,
|
|
|
|
project_domain_name=None,
|
|
|
|
token=None, **kwargs):
|
2013-06-21 19:04:50 +02:00
|
|
|
"""Authenticate against the v3 Identity API.
|
2013-02-13 22:52:05 -06:00
|
|
|
|
|
|
|
:returns: (``resp``, ``body``) if authentication was successful.
|
|
|
|
:raises: AuthorizationFailure if unable to authenticate or validate
|
|
|
|
the existing authorization token
|
|
|
|
:raises: Unauthorized if authentication fails due to invalid token
|
|
|
|
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
return self._do_auth(
|
|
|
|
auth_url,
|
|
|
|
user_id=user_id,
|
|
|
|
username=username,
|
|
|
|
user_domain_id=user_domain_id,
|
|
|
|
user_domain_name=user_domain_name,
|
|
|
|
password=password,
|
|
|
|
domain_id=domain_id,
|
|
|
|
domain_name=domain_name,
|
|
|
|
project_id=project_id,
|
|
|
|
project_name=project_name,
|
|
|
|
project_domain_id=project_domain_id,
|
|
|
|
project_domain_name=project_domain_name,
|
|
|
|
token=token)
|
|
|
|
except (exceptions.AuthorizationFailure, exceptions.Unauthorized):
|
|
|
|
_logger.debug('Authorization failed.')
|
|
|
|
raise
|
|
|
|
except Exception as e:
|
|
|
|
raise exceptions.AuthorizationFailure('Authorization failed: '
|
|
|
|
'%s' % e)
|
|
|
|
|
|
|
|
def _do_auth(self, auth_url, user_id=None, username=None,
|
|
|
|
user_domain_id=None, user_domain_name=None, password=None,
|
|
|
|
domain_id=None, domain_name=None,
|
|
|
|
project_id=None, project_name=None, project_domain_id=None,
|
|
|
|
project_domain_name=None, token=None):
|
|
|
|
headers = {}
|
|
|
|
url = auth_url + "/auth/tokens"
|
|
|
|
body = {'auth': {'identity': {}}}
|
|
|
|
ident = body['auth']['identity']
|
|
|
|
|
|
|
|
if token:
|
|
|
|
headers['X-Auth-Token'] = token
|
|
|
|
|
|
|
|
ident['methods'] = ['token']
|
|
|
|
ident['token'] = {}
|
|
|
|
ident['token']['id'] = token
|
|
|
|
|
|
|
|
if password:
|
|
|
|
ident['methods'] = ['password']
|
|
|
|
ident['password'] = {}
|
|
|
|
ident['password']['user'] = {}
|
|
|
|
user = ident['password']['user']
|
|
|
|
user['password'] = password
|
|
|
|
|
|
|
|
if user_id:
|
|
|
|
user['id'] = user_id
|
|
|
|
elif username:
|
|
|
|
user['name'] = username
|
|
|
|
|
|
|
|
if user_domain_id or user_domain_name:
|
|
|
|
user['domain'] = {}
|
|
|
|
if user_domain_id:
|
|
|
|
user['domain']['id'] = user_domain_id
|
|
|
|
elif user_domain_name:
|
|
|
|
user['domain']['name'] = user_domain_name
|
|
|
|
|
|
|
|
if (domain_id or domain_name) and (project_id or project_name):
|
|
|
|
raise ValueError('Authentication cannot be scoped to both domain'
|
|
|
|
' and project.')
|
|
|
|
|
|
|
|
if domain_id or domain_name:
|
|
|
|
body['auth']['scope'] = {}
|
|
|
|
scope = body['auth']['scope']
|
|
|
|
scope['domain'] = {}
|
|
|
|
|
|
|
|
if domain_id:
|
|
|
|
scope['domain']['id'] = domain_id
|
|
|
|
elif domain_name:
|
|
|
|
scope['domain']['name'] = domain_name
|
|
|
|
|
|
|
|
if project_id or project_name:
|
|
|
|
body['auth']['scope'] = {}
|
|
|
|
scope = body['auth']['scope']
|
|
|
|
scope['project'] = {}
|
|
|
|
|
|
|
|
if project_id:
|
|
|
|
scope['project']['id'] = project_id
|
|
|
|
elif project_name:
|
|
|
|
scope['project']['name'] = project_name
|
|
|
|
|
|
|
|
if project_domain_id or project_domain_name:
|
|
|
|
scope['project']['domain'] = {}
|
|
|
|
if project_domain_id:
|
|
|
|
scope['project']['domain']['id'] = project_domain_id
|
|
|
|
elif project_domain_name:
|
|
|
|
scope['project']['domain']['name'] = project_domain_name
|
|
|
|
|
|
|
|
if not (ident or token):
|
|
|
|
raise ValueError('Authentication method required (e.g. password)')
|
|
|
|
|
|
|
|
resp, body = self.request(url, 'POST', body=body, headers=headers)
|
|
|
|
return resp, body
|