Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

# 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 

 

from keystoneclient import client 

from keystoneclient import exceptions 

from keystoneclient import service_catalog 

from keystoneclient.v2_0 import ec2 

from keystoneclient.v2_0 import endpoints 

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(client.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: If provided, used as a local certificate to communicate 

                        with the keystone endpoint. If provided, requires the 

                        additional parameter key. (optional) 

    :param string key: The key associated with the certificate for secure 

                       keystone communication. (optional) 

    :param string cacert: the ca-certs to verify the secure communications 

                          with keystone. (optional) 

    :param boolean insecure: If using an SSL endpoint, allows for the certicate 

                             to be unsigned - does not verify the certificate 

                             chain. 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. 

 

 

    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 keystoneclient.v2_0 import client 

        >>> keystone = client.Client(username=USER, 

                                     password=PASS, 

                                     tenant_name=TENANT_NAME, 

                                     auth_url=KEYSTONE_URL) 

        >>> 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 keystoneclient.v2_0 import client 

        >>> keystone = client.Client(username=USER, 

                                     password=PASS, 

                                     tenant_name=TENANT_NAME, 

                                     auth_url=KEYSTONE_URL) 

        >>> 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 keystoneclient.v2_0 import client 

        >>> admin_client = client.Client( 

                token='12345secret7890', 

                endpoint='http://localhost:35357/v2.0') 

        >>> keystone.tenants.list() 

 

    """ 

 

    def __init__(self, **kwargs): 

        """ Initialize a new client for the Keystone v2.0 API. """ 

        super(Client, self).__init__(**kwargs) 

        self.endpoints = endpoints.EndpointManager(self) 

        self.roles = roles.RoleManager(self) 

        self.services = services.ServiceManager(self) 

        self.tenants = tenants.TenantManager(self) 

        self.tokens = tokens.TokenManager(self) 

        self.users = users.UserManager(self) 

 

        # extensions 

        self.ec2 = ec2.CredentialsManager(self) 

 

        if self.management_url is None: 

            self.authenticate() 

 

    #TODO(heckj): move to a method on auth_ref 

    def has_service_catalog(self): 

        """Returns True if this client provides a service catalog.""" 

        return hasattr(self, 'service_catalog') 

 

    def process_token(self): 

        """ Extract and process information from the new auth_ref. 

 

        And set the relevant authentication information. 

        """ 

        # if we got a response without a service catalog, set the local 

        # list of tenants for introspection, and leave to client user 

        # to determine what to do. Otherwise, load up the service catalog 

        if self.auth_ref.scoped: 

            if self.management_url is None and self.auth_ref.management_url: 

                self.management_url = self.auth_ref.management_url[0] 

            self.tenant_name = self.auth_ref.tenant_name 

            self.tenant_id = self.auth_ref.tenant_id 

            self.user_id = self.auth_ref.user_id 

        self._extract_service_catalog(self.auth_url, self.auth_ref) 

 

    def get_raw_token_from_identity_service(self, auth_url, username=None, 

                                            password=None, tenant_name=None, 

                                            tenant_id=None, token=None): 

        """ Authenticate against the Keystone API. 

 

        :returns: ``raw token`` if authentication was successful. 

        :raises: AuthorizationFailure if unable to authenticate or validate 

                 the existing authorization token 

        :raises: ValueError if insufficient parameters are used. 

 

        """ 

        try: 

            return self._base_authN(auth_url, 

                                    username=username, 

                                    tenant_id=tenant_id, 

                                    tenant_name=tenant_name, 

                                    password=password, 

                                    token=token) 

        except (exceptions.AuthorizationFailure, exceptions.Unauthorized): 

            _logger.debug("Authorization Failed.") 

            raise 

        except Exception as e: 

            raise exceptions.AuthorizationFailure("Authorization Failed: " 

                                                  "%s" % e) 

 

    def _base_authN(self, auth_url, username=None, password=None, 

                    tenant_name=None, tenant_id=None, token=None): 

        """ Takes a username, password, and optionally a tenant_id or 

        tenant_name to get an authentication token from keystone. 

        May also take a token and a tenant_id to re-scope a token 

        to a tenant.""" 

        headers = {} 

        url = auth_url + "/tokens" 

        if token: 

            headers['X-Auth-Token'] = token 

            params = {"auth": {"token": {"id": token}}} 

197        elif username and password: 

            params = {"auth": {"passwordCredentials": {"username": username, 

                                                       "password": password}}} 

        else: 

            raise ValueError('A username and password or token is required.') 

        if tenant_id: 

            params['auth']['tenantId'] = tenant_id 

201        elif tenant_name: 

            params['auth']['tenantName'] = tenant_name 

        resp, body = self.request(url, 'POST', body=params, headers=headers) 

        return body['access'] 

 

    # TODO(heckj): remove entirely in favor of access.AccessInfo and 

    # associated methods 

    def _extract_service_catalog(self, url, body): 

        """ Set the client's service catalog from the response data. """ 

        self.service_catalog = service_catalog.ServiceCatalog( 

            body, region_name=self.region_name) 

        try: 

            sc = self.service_catalog.get_token() 

            # Save these since we have them and they'll be useful later 

            self.auth_tenant_id = sc.get('tenant_id') 

            self.auth_user_id = sc.get('user_id') 

        except KeyError: 

            raise exceptions.AuthorizationFailure()