
The docstring examples in the v2_0 and v3 Client classes showed passing username and password. Passing username and password is deprecated in favor of using keystoneauth session. The examples shouldn't use deprecated behavior otherwise we'll never get developers to stop using it. Change-Id: Ia79ed7a02a48553eba8eb83a654c3c75601fa07d
222 lines
9.7 KiB
Python
222 lines
9.7 KiB
Python
# 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 logging
|
|
import warnings
|
|
|
|
from keystoneclient.auth.identity import v2 as v2_auth
|
|
from keystoneclient import exceptions
|
|
from keystoneclient import httpclient
|
|
from keystoneclient.i18n import _
|
|
from keystoneclient.v2_0 import certificates
|
|
from keystoneclient.v2_0 import ec2
|
|
from keystoneclient.v2_0 import endpoints
|
|
from keystoneclient.v2_0 import extensions
|
|
from keystoneclient.v2_0 import roles
|
|
from keystoneclient.v2_0 import services
|
|
from keystoneclient.v2_0 import tenants
|
|
from keystoneclient.v2_0 import tokens
|
|
from keystoneclient.v2_0 import users
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Client(httpclient.HTTPClient):
|
|
"""Client for the OpenStack Keystone v2.0 API.
|
|
|
|
:param string username: Username for authentication. (optional)
|
|
:param string password: Password for authentication. (optional)
|
|
:param string token: Token for authentication. (optional)
|
|
:param string tenant_id: Tenant id. (optional)
|
|
:param string tenant_name: Tenant name. (optional)
|
|
:param string auth_url: Keystone service endpoint for authorization.
|
|
:param string region_name: Name of a region to select when choosing an
|
|
endpoint from the service catalog.
|
|
:param string endpoint: A user-supplied endpoint URL for the keystone
|
|
service. Lazy-authentication is possible for API
|
|
service calls if endpoint is set at
|
|
instantiation.(optional)
|
|
:param integer timeout: Allows customization of the timeout for client
|
|
http requests. (optional)
|
|
:param string original_ip: The original IP of the requesting user
|
|
which will be sent to Keystone in a
|
|
'Forwarded' header. (optional)
|
|
:param string cert: Path to the Privacy Enhanced Mail (PEM) file which
|
|
contains the corresponding X.509 client certificate
|
|
needed to established two-way SSL connection with
|
|
the identity service. (optional)
|
|
:param string key: Path to the Privacy Enhanced Mail (PEM) file which
|
|
contains the unencrypted client private key needed
|
|
to established two-way SSL connection with the
|
|
identity service. (optional)
|
|
:param string cacert: Path to the Privacy Enhanced Mail (PEM) file which
|
|
contains the trusted authority X.509 certificates
|
|
needed to established SSL connection with the
|
|
identity service. (optional)
|
|
:param boolean insecure: Does not perform X.509 certificate validation
|
|
when establishing SSL connection with identity
|
|
service. default: False (optional)
|
|
:param dict auth_ref: To allow for consumers of the client to manage their
|
|
own caching strategy, you may initialize a client
|
|
with a previously captured auth_reference (token)
|
|
:param boolean debug: Enables debug logging of all request and responses
|
|
to keystone. default False (option)
|
|
|
|
.. warning::
|
|
|
|
If debug is enabled, it may show passwords in plain text as a part of
|
|
its output.
|
|
|
|
.. warning::
|
|
|
|
Constructing an instance of this class without a session is
|
|
deprecated as of the 1.7.0 release and will be removed in the
|
|
2.0.0 release.
|
|
|
|
The client can be created and used like a user or in a strictly
|
|
bootstrap mode. Normal operation expects a username, password, auth_url,
|
|
and tenant_name or id to be provided. Other values will be lazily loaded
|
|
as needed from the service catalog.
|
|
|
|
Example::
|
|
|
|
>>> from keystoneauth1.identity import v2
|
|
>>> from keystoneauth1 import session
|
|
>>> from keystoneclient.v2_0 import client
|
|
>>> auth = v2.Password(auth_url=KEYSTONE_URL,
|
|
... username=USER,
|
|
... password=PASS,
|
|
... tenant_name=TENANT_NAME)
|
|
>>> sess = session.Session(auth=auth)
|
|
>>> keystone = client.Client(session=sess)
|
|
>>> keystone.tenants.list()
|
|
...
|
|
>>> user = keystone.users.get(USER_ID)
|
|
>>> user.delete()
|
|
|
|
Once authenticated, you can store and attempt to re-use the
|
|
authenticated token. the auth_ref property on the client
|
|
returns as a dictionary-like-object so that you can export and
|
|
cache it, re-using it when initiating another client::
|
|
|
|
>>> from keystoneauth1.identity import v2
|
|
>>> from keystoneauth1 import session
|
|
>>> from keystoneclient.v2_0 import client
|
|
>>> auth = v2.Password(auth_url=KEYSTONE_URL,
|
|
... username=USER,
|
|
... password=PASS,
|
|
... tenant_name=TENANT_NAME)
|
|
>>> sess = session.Session(auth=auth)
|
|
>>> keystone = client.Client(session=sess)
|
|
>>> auth_ref = keystone.auth_ref
|
|
>>> # pickle or whatever you like here
|
|
>>> new_client = client.Client(auth_ref=auth_ref)
|
|
|
|
Alternatively, you can provide the administrative token configured in
|
|
keystone and an endpoint to communicate with directly. See
|
|
(``admin_token`` in ``keystone.conf``) In this case, authenticate()
|
|
is not needed, and no service catalog will be loaded.
|
|
|
|
Example::
|
|
|
|
>>> from keystoneauth1.identity import v2
|
|
>>> from keystoneauth1 import session
|
|
>>> from keystoneclient.v2_0 import client
|
|
>>> auth = v2.Token(auth_url='http://localhost:35357/v2.0',
|
|
... token='12345secret7890')
|
|
>>> sess = session.Session(auth=auth)
|
|
>>> keystone = client.Client(session=sess)
|
|
>>> keystone.tenants.list()
|
|
|
|
"""
|
|
|
|
version = 'v2.0'
|
|
|
|
def __init__(self, **kwargs):
|
|
"""Initialize a new client for the Keystone v2.0 API."""
|
|
|
|
if not kwargs.get('session'):
|
|
warnings.warn(
|
|
'Constructing an instance of the '
|
|
'keystoneclient.v2_0.client.Client class without a session is '
|
|
'deprecated as of the 1.7.0 release and may be removed in '
|
|
'the 2.0.0 release.', DeprecationWarning)
|
|
|
|
super(Client, self).__init__(**kwargs)
|
|
|
|
self.certificates = certificates.CertificatesManager(self._adapter)
|
|
self.endpoints = endpoints.EndpointManager(self._adapter)
|
|
self.extensions = extensions.ExtensionManager(self._adapter)
|
|
self.roles = roles.RoleManager(self._adapter)
|
|
self.services = services.ServiceManager(self._adapter)
|
|
self.tokens = tokens.TokenManager(self._adapter)
|
|
self.users = users.UserManager(self._adapter, self.roles)
|
|
|
|
self.tenants = tenants.TenantManager(self._adapter,
|
|
self.roles, self.users)
|
|
|
|
# extensions
|
|
self.ec2 = ec2.CredentialsManager(self._adapter)
|
|
|
|
# DEPRECATED: if session is passed then we go to the new behaviour of
|
|
# authenticating on the first required call.
|
|
if not kwargs.get('session') and self.management_url is None:
|
|
self.authenticate()
|
|
|
|
def get_raw_token_from_identity_service(self, auth_url, username=None,
|
|
password=None, tenant_name=None,
|
|
tenant_id=None, token=None,
|
|
project_name=None, project_id=None,
|
|
trust_id=None,
|
|
**kwargs):
|
|
"""Authenticate against the v2 Identity API.
|
|
|
|
If a token is provided it will be used in preference over username and
|
|
password.
|
|
|
|
:returns: access.AccessInfo if authentication was successful.
|
|
:raises keystoneclient.exceptions.AuthorizationFailure: if unable to
|
|
authenticate or validate the existing authorization token
|
|
"""
|
|
try:
|
|
if auth_url is None:
|
|
raise ValueError(_("Cannot authenticate without an auth_url"))
|
|
|
|
new_kwargs = {'trust_id': trust_id,
|
|
'tenant_id': project_id or tenant_id,
|
|
'tenant_name': project_name or tenant_name}
|
|
|
|
if token:
|
|
plugin = v2_auth.Token(auth_url, token, **new_kwargs)
|
|
elif username and password:
|
|
plugin = v2_auth.Password(auth_url, username, password,
|
|
**new_kwargs)
|
|
else:
|
|
msg = _('A username and password or token is required.')
|
|
raise exceptions.AuthorizationFailure(msg)
|
|
|
|
return plugin.get_auth_ref(self.session)
|
|
except (exceptions.AuthorizationFailure, exceptions.Unauthorized):
|
|
_logger.debug("Authorization Failed.")
|
|
raise
|
|
except exceptions.EndpointNotFound:
|
|
msg = (
|
|
_('There was no suitable authentication url for this request'))
|
|
raise exceptions.AuthorizationFailure(msg)
|
|
except Exception as e:
|
|
raise exceptions.AuthorizationFailure(
|
|
_("Authorization Failed: %s") % e)
|