summaryrefslogtreecommitdiff
path: root/keystoneclient/v2_0/client.py
blob: 904f7693553f8d91cf260896670b6880050102ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# 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)