~ubuntu-branches/ubuntu/precise/keystone/precise-security

« back to all changes in this revision

Viewing changes to keystone/logic/service.py

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2011-08-23 10:18:22 UTC
  • Revision ID: james.westby@ubuntu.com-20110823101822-enve6zceb3lqhuvj
Tags: upstream-1.0~d4~20110823.1078
ImportĀ upstreamĀ versionĀ 1.0~d4~20110823.1078

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2010-2011 OpenStack, LLC.
 
2
#
 
3
# Licensed under the Apache License, Version 2.0 (the "License");
 
4
# you may not use this file except in compliance with the License.
 
5
# You may obtain a copy of the License at
 
6
#
 
7
#    http://www.apache.org/licenses/LICENSE-2.0
 
8
#
 
9
# Unless required by applicable law or agreed to in writing, software
 
10
# distributed under the License is distributed on an "AS IS" BASIS,
 
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 
12
# implied.
 
13
# See the License for the specific language governing permissions and
 
14
# limitations under the License.
 
15
 
 
16
from datetime import datetime, timedelta
 
17
import uuid
 
18
 
 
19
from keystone.logic.types import auth, atom
 
20
from keystone.logic.signer import Signer
 
21
import keystone.backends as backends
 
22
import keystone.backends.api as api
 
23
import keystone.backends.models as models
 
24
from keystone.logic.types import fault
 
25
from keystone.logic.types.tenant import \
 
26
    Tenant, Tenants, User as TenantUser
 
27
from keystone.logic.types.role import Role, RoleRef, RoleRefs, Roles
 
28
from keystone.logic.types.service import Service, Services
 
29
from keystone.logic.types.user import User, User_Update, Users
 
30
from keystone.logic.types.endpoint import Endpoint, Endpoints, \
 
31
    EndpointTemplate, EndpointTemplates
 
32
import keystone.utils as utils
 
33
 
 
34
 
 
35
class IdentityService(object):
 
36
    """Implements Identity service"""
 
37
 
 
38
    #
 
39
    #  Token Operations
 
40
    #
 
41
    def authenticate(self, credentials):
 
42
        # Check credentials
 
43
        if not isinstance(credentials, auth.PasswordCredentials):
 
44
            raise fault.BadRequestFault("Expecting Password Credentials!")
 
45
 
 
46
        def validate(duser):
 
47
            return api.USER.check_password(duser, credentials.password)
 
48
 
 
49
        return self._authenticate(validate,
 
50
                                  credentials.username,
 
51
                                  credentials.tenant_id)
 
52
 
 
53
    def authenticate_ec2(self, credentials):
 
54
        # Check credentials
 
55
        if not isinstance(credentials, auth.Ec2Credentials):
 
56
            raise fault.BadRequestFault("Expecting Ec2 Credentials!")
 
57
 
 
58
        creds = api.CREDENTIALS.get_by_access(credentials.access)
 
59
        if not creds:
 
60
            raise fault.UnauthorizedFault("No credentials found for %s"
 
61
                                          % credentials.access)
 
62
 
 
63
        def validate(duser):
 
64
            signer = Signer(creds.secret)
 
65
            signature = signer.generate(credentials)
 
66
            if signature == credentials.signature:
 
67
                return True
 
68
            # NOTE(vish): Some libraries don't use the port when signing
 
69
            #             requests, so try again without port.
 
70
            if ':' in credentials.host:
 
71
                hostname, _sep, port = credentials.partition(':')
 
72
                credentials.host = hostname
 
73
                signature = signer.generate(credentials)
 
74
                return signature == credentials.signature
 
75
            return False
 
76
 
 
77
        return self._authenticate(validate, creds.user_id, creds.tenant_id)
 
78
 
 
79
    def _authenticate(self, validate, user_id, tenant_id=None):
 
80
        if not tenant_id:
 
81
            duser = api.USER.get(user_id)
 
82
            if duser == None:
 
83
                raise fault.UnauthorizedFault("Unauthorized")
 
84
        else:
 
85
            duser = api.USER.get_by_tenant(user_id, tenant_id)
 
86
            if duser == None:
 
87
                raise fault.UnauthorizedFault("Unauthorized on this tenant")
 
88
 
 
89
        if not duser.enabled:
 
90
            raise fault.UserDisabledFault("Your account has been disabled")
 
91
 
 
92
        if not validate(duser):
 
93
            raise fault.UnauthorizedFault("Unauthorized")
 
94
 
 
95
        #
 
96
        # Look for an existing token, or create one,
 
97
        # TODO: Handle tenant/token search
 
98
        #
 
99
        user_id = duser.id
 
100
        tenant_id = tenant_id or duser.tenant_id
 
101
        dtoken = api.TOKEN.get_for_user_by_tenant(user_id, tenant_id)
 
102
 
 
103
        if not dtoken or dtoken.expires < datetime.now():
 
104
            # Create new token
 
105
            dtoken = models.Token()
 
106
            dtoken.id = str(uuid.uuid4())
 
107
            dtoken.user_id = user_id
 
108
            dtoken.tenant_id = tenant_id
 
109
            dtoken.expires = datetime.now() + timedelta(days=1)
 
110
            api.TOKEN.create(dtoken)
 
111
        #if tenant_id is passed in the call that tenant_id is passed else
 
112
        #user's default tenant_id is used.
 
113
        return self.__get_auth_data(dtoken, tenant_id)
 
114
 
 
115
    def validate_token(self, admin_token, token_id, belongs_to=None):
 
116
        self.__validate_service_or_keystone_admin_token(admin_token)
 
117
 
 
118
        if not api.TOKEN.get(token_id):
 
119
            raise fault.UnauthorizedFault("Bad token, please reauthenticate")
 
120
 
 
121
        (token, user) = self.__validate_token(token_id, belongs_to)
 
122
 
 
123
        return self.__get_validate_data(token, user)
 
124
 
 
125
    def revoke_token(self, admin_token, token_id):
 
126
        self.__validate_admin_token(admin_token)
 
127
 
 
128
        dtoken = api.TOKEN.get(token_id)
 
129
        if not dtoken:
 
130
            raise fault.ItemNotFoundFault("Token not found")
 
131
 
 
132
        api.TOKEN.delete(token_id)
 
133
 
 
134
    #
 
135
    #   Tenant Operations
 
136
    #
 
137
 
 
138
    def create_tenant(self, admin_token, tenant):
 
139
        self.__validate_admin_token(admin_token)
 
140
 
 
141
        if not isinstance(tenant, Tenant):
 
142
            raise fault.BadRequestFault("Expecting a Tenant")
 
143
 
 
144
        if tenant.tenant_id == None or len(tenant.tenant_id.strip()) == 0:
 
145
            raise fault.BadRequestFault("Expecting a unique Tenant Id")
 
146
 
 
147
        if api.TENANT.get(tenant.tenant_id) != None:
 
148
            raise fault.TenantConflictFault(
 
149
                "A tenant with that id already exists")
 
150
 
 
151
        dtenant = models.Tenant()
 
152
        dtenant.id = tenant.tenant_id
 
153
        dtenant.desc = tenant.description
 
154
        dtenant.enabled = tenant.enabled
 
155
 
 
156
        api.TENANT.create(dtenant)
 
157
        return tenant
 
158
 
 
159
    def get_tenants(self, admin_token, marker, limit, url):
 
160
        """Fetch tenants for either an admin user or service user."""
 
161
        ts = []
 
162
 
 
163
        try:
 
164
            # If Global admin...
 
165
            (_token, user) = self.__validate_admin_token(admin_token)
 
166
 
 
167
            # Return all tenants
 
168
            dtenants = api.TENANT.get_page(marker, limit)
 
169
            prev_page, next_page = api.TENANT.get_page_markers(marker, limit)
 
170
        except fault.UnauthorizedFault:
 
171
            # If not global admin...
 
172
            (_token, user) = self.__validate_token(admin_token, False)
 
173
 
 
174
            # Return tenants specific to user
 
175
            dtenants = api.TENANT.tenants_for_user_get_page(
 
176
                user, marker, limit)
 
177
            prev_page, next_page = api.TENANT.\
 
178
                tenants_for_user_get_page_markers(user, marker, limit)
 
179
 
 
180
        for dtenant in dtenants:
 
181
            ts.append(Tenant(dtenant.id, dtenant.desc, dtenant.enabled))
 
182
 
 
183
        links = []
 
184
        if prev_page:
 
185
            links.append(atom.Link('prev',
 
186
                "%s?'marker=%s&limit=%s'" % (url, prev_page, limit)))
 
187
        if next_page:
 
188
            links.append(atom.Link('next',
 
189
                "%s?'marker=%s&limit=%s'" % (url, next_page, limit)))
 
190
 
 
191
        return Tenants(ts, links)
 
192
 
 
193
    def get_tenant(self, admin_token, tenant_id):
 
194
        self.__validate_admin_token(admin_token)
 
195
 
 
196
        dtenant = api.TENANT.get(tenant_id)
 
197
        if not dtenant:
 
198
            raise fault.ItemNotFoundFault("The tenant could not be found")
 
199
        return Tenant(dtenant.id, dtenant.desc, dtenant.enabled)
 
200
 
 
201
    def update_tenant(self, admin_token, tenant_id, tenant):
 
202
        self.__validate_admin_token(admin_token)
 
203
 
 
204
        if not isinstance(tenant, Tenant):
 
205
            raise fault.BadRequestFault("Expecting a Tenant")
 
206
 
 
207
        dtenant = api.TENANT.get(tenant_id)
 
208
        if dtenant == None:
 
209
            raise fault.ItemNotFoundFault("The tenant could not be found")
 
210
        values = {'desc': tenant.description, 'enabled': tenant.enabled}
 
211
        api.TENANT.update(tenant_id, values)
 
212
        return Tenant(dtenant.id, tenant.description, tenant.enabled)
 
213
 
 
214
    def delete_tenant(self, admin_token, tenant_id):
 
215
        self.__validate_admin_token(admin_token)
 
216
 
 
217
        dtenant = api.TENANT.get(tenant_id)
 
218
        if dtenant == None:
 
219
            raise fault.ItemNotFoundFault("The tenant could not be found")
 
220
 
 
221
        if not api.TENANT.is_empty(tenant_id):
 
222
            raise fault.ForbiddenFault("You may not delete a tenant that "
 
223
                                       "contains get_users")
 
224
 
 
225
        api.TENANT.delete(dtenant.id)
 
226
        return None
 
227
 
 
228
    #
 
229
    # Private Operations
 
230
    #
 
231
    def __get_dauth_data(self, token_id):
 
232
        """return token and user object for a token_id"""
 
233
 
 
234
        token = None
 
235
        user = None
 
236
        if token_id:
 
237
            token = api.TOKEN.get(token_id)
 
238
            if token:
 
239
                user = api.USER.get(token.user_id)
 
240
        return (token, user)
 
241
 
 
242
    #
 
243
    #   User Operations
 
244
    #
 
245
    def create_user(self, admin_token, user):
 
246
        self.__validate_admin_token(admin_token)
 
247
 
 
248
        self.validate_and_fetch_user_tenant(user.tenant_id)
 
249
 
 
250
        if not isinstance(user, User):
 
251
            raise fault.BadRequestFault("Expecting a User")
 
252
 
 
253
        if user.user_id == None or len(user.user_id.strip()) == 0:
 
254
            raise fault.BadRequestFault("Expecting a unique User Id")
 
255
 
 
256
        if api.USER.get(user.user_id) != None:
 
257
            raise fault.UserConflictFault(
 
258
                "An user with that id already exists")
 
259
 
 
260
        if api.USER.get_by_email(user.email) != None:
 
261
            raise fault.EmailConflictFault("Email already exists")
 
262
 
 
263
        duser = models.User()
 
264
        duser.id = user.user_id
 
265
        duser.password = user.password
 
266
        duser.email = user.email
 
267
        duser.enabled = user.enabled
 
268
        duser.tenant_id = user.tenant_id
 
269
        api.USER.create(duser)
 
270
 
 
271
        return user
 
272
 
 
273
    def validate_and_fetch_user_tenant(self, tenant_id):
 
274
        if tenant_id != None and len(tenant_id) > 0:
 
275
            dtenant = api.TENANT.get(tenant_id)
 
276
            if dtenant == None:
 
277
                raise fault.ItemNotFoundFault("The tenant is not found")
 
278
            elif not dtenant.enabled:
 
279
                raise fault.TenantDisabledFault(
 
280
                    "Your account has been disabled")
 
281
            return dtenant
 
282
        else:
 
283
            return None
 
284
 
 
285
    def get_tenant_users(self, admin_token, tenant_id, marker, limit, url):
 
286
        self.__validate_admin_token(admin_token)
 
287
 
 
288
        if tenant_id == None:
 
289
            raise fault.BadRequestFault("Expecting a Tenant Id")
 
290
        dtenant = api.TENANT.get(tenant_id)
 
291
        if dtenant is  None:
 
292
            raise fault.ItemNotFoundFault("The tenant not found")
 
293
        if not dtenant.enabled:
 
294
            raise fault.TenantDisabledFault("Your account has been disabled")
 
295
        ts = []
 
296
        dtenantusers = api.USER.users_get_by_tenant_get_page(tenant_id, marker,
 
297
                                                          limit)
 
298
        for dtenantuser in dtenantusers:
 
299
            ts.append(User(None, dtenantuser.id, tenant_id,
 
300
                           dtenantuser.email, dtenantuser.enabled,
 
301
                           dtenantuser.tenant_roles if hasattr(dtenantuser,
 
302
                                                    "tenant_roles") else None))
 
303
        links = []
 
304
        if ts.__len__():
 
305
            prev, next = api.USER.users_get_by_tenant_get_page_markers(
 
306
                    tenant_id, marker, limit)
 
307
            if prev:
 
308
                links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" %
 
309
                                      (url, prev, limit)))
 
310
            if next:
 
311
                links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" %
 
312
                                      (url, next, limit)))
 
313
        return Users(ts, links)
 
314
 
 
315
    def get_users(self, admin_token, marker, limit, url):
 
316
        self.__validate_admin_token(admin_token)
 
317
        ts = []
 
318
        dusers = api.USER.users_get_page(marker, limit)
 
319
        for duser in dusers:
 
320
            ts.append(User(None, duser.id, duser.tenant_id,
 
321
                                   duser.email, duser.enabled))
 
322
        links = []
 
323
        if ts.__len__():
 
324
            prev, next = api.USER.users_get_page_markers(marker, limit)
 
325
            if prev:
 
326
                links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" %
 
327
                                      (url, prev, limit)))
 
328
            if next:
 
329
                links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" %
 
330
                                      (url, next, limit)))
 
331
        return Users(ts, links)
 
332
 
 
333
    def get_user(self, admin_token, user_id):
 
334
        self.__validate_admin_token(admin_token)
 
335
        duser = api.USER.get(user_id)
 
336
        if not duser:
 
337
            raise fault.ItemNotFoundFault("The user could not be found")
 
338
        return User_Update(None, duser.id, duser.tenant_id,
 
339
                duser.email, duser.enabled)
 
340
 
 
341
    def update_user(self, admin_token, user_id, user):
 
342
        self.__validate_admin_token(admin_token)
 
343
 
 
344
        duser = api.USER.get(user_id)
 
345
 
 
346
        if not duser:
 
347
            raise fault.ItemNotFoundFault("The user could not be found")
 
348
 
 
349
        if not isinstance(user, User):
 
350
            raise fault.BadRequestFault("Expecting a User")
 
351
 
 
352
        if user.email != duser.email and \
 
353
            api.USER.get_by_email(user.email) is not None:
 
354
            raise fault.EmailConflictFault(
 
355
                "Email already exists")
 
356
 
 
357
        values = {'email': user.email}
 
358
        api.USER.update(user_id, values)
 
359
        duser = api.USER.user_get_update(user_id)
 
360
        return User(duser.password, duser.id, duser.tenant_id,
 
361
                          duser.email, duser.enabled)
 
362
 
 
363
    def set_user_password(self, admin_token, user_id, user):
 
364
        self.__validate_admin_token(admin_token)
 
365
 
 
366
        duser = api.USER.get(user_id)
 
367
        if not duser:
 
368
            raise fault.ItemNotFoundFault("The user could not be found")
 
369
 
 
370
        if not isinstance(user, User):
 
371
            raise fault.BadRequestFault("Expecting a User")
 
372
 
 
373
        duser = api.USER.get(user_id)
 
374
        if duser == None:
 
375
            raise fault.ItemNotFoundFault("The user could not be found")
 
376
 
 
377
        values = {'password': user.password}
 
378
 
 
379
        api.USER.update(user_id, values)
 
380
 
 
381
        return User_Update(user.password,
 
382
            None, None, None, None)
 
383
 
 
384
    def enable_disable_user(self, admin_token, user_id, user):
 
385
        self.__validate_admin_token(admin_token)
 
386
        duser = api.USER.get(user_id)
 
387
        if not duser:
 
388
            raise fault.ItemNotFoundFault("The user could not be found")
 
389
        if not isinstance(user, User):
 
390
            raise fault.BadRequestFault("Expecting a User")
 
391
 
 
392
        duser = api.USER.get(user_id)
 
393
        if duser == None:
 
394
            raise fault.ItemNotFoundFault("The user could not be found")
 
395
 
 
396
        values = {'enabled': user.enabled}
 
397
 
 
398
        api.USER.update(user_id, values)
 
399
 
 
400
        return User_Update(None,
 
401
            None, None, None, user.enabled)
 
402
 
 
403
    def set_user_tenant(self, admin_token, user_id, user):
 
404
        self.__validate_admin_token(admin_token)
 
405
        duser = api.USER.get(user_id)
 
406
        if not duser:
 
407
            raise fault.ItemNotFoundFault("The user could not be found")
 
408
        if not isinstance(user, User):
 
409
            raise fault.BadRequestFault("Expecting a User")
 
410
 
 
411
        duser = api.USER.get(user_id)
 
412
        if duser == None:
 
413
            raise fault.ItemNotFoundFault("The user could not be found")
 
414
 
 
415
        self.validate_and_fetch_user_tenant(user.tenant_id)
 
416
        values = {'tenant_id': user.tenant_id}
 
417
        api.USER.update(user_id, values)
 
418
        return User_Update(None,
 
419
            None, user.tenant_id, None, None)
 
420
 
 
421
    def delete_user(self, admin_token, user_id):
 
422
        self.__validate_admin_token(admin_token)
 
423
        duser = api.USER.get(user_id)
 
424
        if not duser:
 
425
            raise fault.ItemNotFoundFault("The user could not be found")
 
426
 
 
427
        dtenant = api.TENANT.get(duser.tenant_id)
 
428
        if dtenant != None:
 
429
            api.USER.delete_tenant_user(user_id, dtenant.id)
 
430
        else:
 
431
            api.USER.delete(user_id)
 
432
        return None
 
433
 
 
434
    def __get_auth_data(self, dtoken, tenant_id):
 
435
        """return AuthData object for a token"""
 
436
        endpoints = None
 
437
        try:
 
438
            endpoints = api.TENANT.get_all_endpoints(tenant_id)
 
439
        except:
 
440
            pass
 
441
        token = auth.Token(dtoken.expires, dtoken.id, tenant_id)
 
442
        return auth.AuthData(token, endpoints)
 
443
 
 
444
    def __get_validate_data(self, dtoken, duser):
 
445
        """return ValidateData object for a token/user pair"""
 
446
 
 
447
        token = auth.Token(dtoken.expires, dtoken.id, dtoken.tenant_id)
 
448
        ts = []
 
449
        if dtoken.tenant_id:
 
450
            drole_refs = api.ROLE.ref_get_all_tenant_roles(duser.id,
 
451
                                                             dtoken.tenant_id)
 
452
            for drole_ref in drole_refs:
 
453
                ts.append(RoleRef(drole_ref.id, drole_ref.role_id,
 
454
                                         drole_ref.tenant_id))
 
455
        drole_refs = api.ROLE.ref_get_all_global_roles(duser.id)
 
456
        for drole_ref in drole_refs:
 
457
            ts.append(RoleRef(drole_ref.id, drole_ref.role_id,
 
458
                                     drole_ref.tenant_id))
 
459
        user = auth.User(duser.id, duser.tenant_id, RoleRefs(ts, []))
 
460
        return auth.ValidateData(token, user)
 
461
 
 
462
    def __validate_tenant(self, tenant_id):
 
463
        if not tenant_id:
 
464
            raise fault.UnauthorizedFault("Missing tenant")
 
465
 
 
466
        tenant = api.TENANT.get(tenant_id)
 
467
 
 
468
        if not tenant.enabled:
 
469
            raise fault.TenantDisabledFault("Tenant %s has been disabled!"
 
470
                                          % tenant.id)
 
471
 
 
472
    def __validate_token(self, token_id, belongs_to=None):
 
473
        if not token_id:
 
474
            raise fault.UnauthorizedFault("Missing token")
 
475
 
 
476
        (token, user) = self.__get_dauth_data(token_id)
 
477
 
 
478
        if not token:
 
479
            raise fault.ItemNotFoundFault("Bad token, please reauthenticate")
 
480
 
 
481
        if token.expires < datetime.now():
 
482
            raise fault.ForbiddenFault("Token expired, please renew")
 
483
 
 
484
        if not user.enabled:
 
485
            raise fault.UserDisabledFault("User %s has been disabled!"
 
486
                                          % user.id)
 
487
 
 
488
        if user.tenant_id:
 
489
            self.__validate_tenant(user.tenant_id)
 
490
 
 
491
        if token.tenant_id:
 
492
            self.__validate_tenant(token.tenant_id)
 
493
 
 
494
        if belongs_to and token.tenant_id != belongs_to:
 
495
            raise fault.UnauthorizedFault("Unauthorized on this tenant")
 
496
 
 
497
        return (token, user)
 
498
 
 
499
    def __validate_admin_token(self, token_id):
 
500
        (token, user) = self.__validate_token(token_id)
 
501
 
 
502
        for role_ref in api.ROLE.ref_get_all_global_roles(user.id):
 
503
            if role_ref.role_id == backends.KEYSTONEADMINROLE and \
 
504
                    role_ref.tenant_id is None:
 
505
                return (token, user)
 
506
 
 
507
        raise fault.UnauthorizedFault(
 
508
            "You are not authorized to make this call")
 
509
 
 
510
    def __validate_service_or_keystone_admin_token(self, token_id):
 
511
        (token, user) = self.__validate_token(token_id)
 
512
        for role_ref in api.ROLE.ref_get_all_global_roles(user.id):
 
513
            if (role_ref.role_id == backends.KEYSTONEADMINROLE or \
 
514
                role_ref.role_id == backends.KEYSTONESERVICEADMINROLE) and \
 
515
                    role_ref.tenant_id is None:
 
516
                return (token, user)
 
517
        raise fault.UnauthorizedFault(
 
518
            "You are not authorized to make this call")
 
519
 
 
520
    def create_role(self, admin_token, role):
 
521
        self.__validate_service_or_keystone_admin_token(admin_token)
 
522
 
 
523
        if not isinstance(role, Role):
 
524
            raise fault.BadRequestFault("Expecting a Role")
 
525
 
 
526
        if role.role_id == None or len(role.role_id.strip()) == 0:
 
527
            raise fault.BadRequestFault("Expecting a Role Id")
 
528
 
 
529
        if api.ROLE.get(role.role_id) != None:
 
530
            raise fault.RoleConflictFault(
 
531
                "A role with that id '" + role.role_id + "' already exists")
 
532
        #Check if the passed service exist
 
533
        #and the role begins with service_id:.
 
534
        if role.service_id != None and\
 
535
            len(role.service_id.strip()) > 0:
 
536
            if api.SERVICE.get(role.service_id) == None:
 
537
                raise fault.BadRequestFault(
 
538
                        "A service with that id doesnt exist.")
 
539
            if not role.role_id.startswith(role.service_id + ":"):
 
540
                raise fault.BadRequestFault(
 
541
                    "Role should begin with service id '" +
 
542
                        role.service_id + ":'")
 
543
 
 
544
        drole = models.Role()
 
545
        drole.id = role.role_id
 
546
        drole.desc = role.desc
 
547
        drole.service_id = role.service_id
 
548
        api.ROLE.create(drole)
 
549
        return role
 
550
 
 
551
    def get_roles(self, admin_token, marker, limit, url):
 
552
        self.__validate_service_or_keystone_admin_token(admin_token)
 
553
 
 
554
        ts = []
 
555
        droles = api.ROLE.get_page(marker, limit)
 
556
        for drole in droles:
 
557
            ts.append(Role(drole.id,
 
558
                                     drole.desc, drole.service_id))
 
559
        prev, next = api.ROLE.get_page_markers(marker, limit)
 
560
        links = []
 
561
        if prev:
 
562
            links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" \
 
563
                                                % (url, prev, limit)))
 
564
        if next:
 
565
            links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" \
 
566
                                                % (url, next, limit)))
 
567
        return Roles(ts, links)
 
568
 
 
569
    def get_role(self, admin_token, role_id):
 
570
        self.__validate_service_or_keystone_admin_token(admin_token)
 
571
 
 
572
        drole = api.ROLE.get(role_id)
 
573
        if not drole:
 
574
            raise fault.ItemNotFoundFault("The role could not be found")
 
575
        return Role(drole.id, drole.desc, drole.service_id)
 
576
 
 
577
    def delete_role(self, admin_token, role_id):
 
578
        self.__validate_service_or_keystone_admin_token(admin_token)
 
579
        drole = api.ROLE.get(role_id)
 
580
        if not drole:
 
581
            raise fault.ItemNotFoundFault("The role could not be found")
 
582
        role_refs = api.ROLE.ref_get_by_role(role_id)
 
583
        if role_refs != None:
 
584
            for role_ref in role_refs:
 
585
                api.ROLE.ref_delete(role_ref.id)
 
586
        api.ROLE.delete(role_id)
 
587
 
 
588
    def create_role_ref(self, admin_token, user_id, role_ref):
 
589
        self.__validate_service_or_keystone_admin_token(admin_token)
 
590
        duser = api.USER.get(user_id)
 
591
 
 
592
        if not duser:
 
593
            raise fault.ItemNotFoundFault("The user could not be found")
 
594
 
 
595
        if not isinstance(role_ref, RoleRef):
 
596
            raise fault.BadRequestFault("Expecting a Role Ref")
 
597
 
 
598
        if role_ref.role_id == None:
 
599
            raise fault.BadRequestFault("Expecting a Role Id")
 
600
 
 
601
        drole = api.ROLE.get(role_ref.role_id)
 
602
        if drole == None:
 
603
            raise fault.ItemNotFoundFault("The role not found")
 
604
 
 
605
        if role_ref.tenant_id != None:
 
606
            dtenant = api.TENANT.get(role_ref.tenant_id)
 
607
            if dtenant == None:
 
608
                raise fault.ItemNotFoundFault("The tenant not found")
 
609
 
 
610
        drole_ref = models.UserRoleAssociation()
 
611
        drole_ref.user_id = duser.id
 
612
        drole_ref.role_id = drole.id
 
613
        if role_ref.tenant_id != None:
 
614
            drole_ref.tenant_id = dtenant.id
 
615
        user_role_ref = api.USER.user_role_add(drole_ref)
 
616
        role_ref.role_ref_id = user_role_ref.id
 
617
        return role_ref
 
618
 
 
619
    def delete_role_ref(self, admin_token, role_ref_id):
 
620
        self.__validate_service_or_keystone_admin_token(admin_token)
 
621
        api.ROLE.ref_delete(role_ref_id)
 
622
        return None
 
623
 
 
624
    def get_user_roles(self, admin_token, marker, limit, url, user_id):
 
625
        self.__validate_service_or_keystone_admin_token(admin_token)
 
626
        duser = api.USER.get(user_id)
 
627
 
 
628
        if not duser:
 
629
            raise fault.ItemNotFoundFault("The user could not be found")
 
630
 
 
631
        ts = []
 
632
        drole_refs = api.ROLE.ref_get_page(marker, limit, user_id)
 
633
        for drole_ref in drole_refs:
 
634
            ts.append(RoleRef(drole_ref.id, drole_ref.role_id,
 
635
                                     drole_ref.tenant_id))
 
636
        prev, next = api.ROLE.ref_get_page_markers(user_id, marker, limit)
 
637
        links = []
 
638
        if prev:
 
639
            links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" \
 
640
                                                % (url, prev, limit)))
 
641
        if next:
 
642
            links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" \
 
643
                                                % (url, next, limit)))
 
644
        return RoleRefs(ts, links)
 
645
 
 
646
    def add_endpoint_template(self, admin_token, endpoint_template):
 
647
        self.__validate_service_or_keystone_admin_token(admin_token)
 
648
 
 
649
        if not isinstance(endpoint_template, EndpointTemplate):
 
650
            raise fault.BadRequestFault("Expecting a EndpointTemplate")
 
651
 
 
652
        #Check if the passed service exist.
 
653
        if endpoint_template.service != None and\
 
654
            len(endpoint_template.service.strip()) > 0 and\
 
655
            api.SERVICE.get(endpoint_template.service) == None:
 
656
            raise fault.BadRequestFault(
 
657
                    "A service with that id doesnt exist.")
 
658
        dendpoint_template = models.EndpointTemplates()
 
659
        dendpoint_template.region = endpoint_template.region
 
660
        dendpoint_template.service = endpoint_template.service
 
661
        dendpoint_template.public_url = endpoint_template.public_url
 
662
        dendpoint_template.admin_url = endpoint_template.admin_url
 
663
        dendpoint_template.internal_url = endpoint_template.internal_url
 
664
        dendpoint_template.enabled = endpoint_template.enabled
 
665
        dendpoint_template.is_global = endpoint_template.is_global
 
666
        dendpoint_template = api.ENDPOINT_TEMPLATE.create(dendpoint_template)
 
667
        endpoint_template.id = dendpoint_template.id
 
668
        return endpoint_template
 
669
 
 
670
    def modify_endpoint_template(self,
 
671
        admin_token, endpoint_template_id, endpoint_template):
 
672
        self.__validate_service_or_keystone_admin_token(admin_token)
 
673
 
 
674
        if not isinstance(endpoint_template, EndpointTemplate):
 
675
            raise fault.BadRequestFault("Expecting a EndpointTemplate")
 
676
        dendpoint_template = api.ENDPOINT_TEMPLATE.get(endpoint_template_id)
 
677
        if not dendpoint_template:
 
678
            raise fault.ItemNotFoundFault(
 
679
                "The endpoint template could not be found")
 
680
 
 
681
        #Check if the passed service exist.
 
682
        if endpoint_template.service != None and\
 
683
            len(endpoint_template.service.strip()) > 0 and\
 
684
            api.SERVICE.get(endpoint_template.service) == None:
 
685
            raise fault.BadRequestFault(
 
686
                    "A service with that id doesn't exist.")
 
687
        dendpoint_template.region = endpoint_template.region
 
688
        dendpoint_template.service = endpoint_template.service
 
689
        dendpoint_template.public_url = endpoint_template.public_url
 
690
        dendpoint_template.admin_url = endpoint_template.admin_url
 
691
        dendpoint_template.internal_url = endpoint_template.internal_url
 
692
        dendpoint_template.enabled = endpoint_template.enabled
 
693
        dendpoint_template.is_global = endpoint_template.is_global
 
694
        dendpoint_template = api.ENDPOINT_TEMPLATE.update(
 
695
            endpoint_template_id, dendpoint_template)
 
696
        return EndpointTemplate(
 
697
            dendpoint_template.id,
 
698
            dendpoint_template.region,
 
699
            dendpoint_template.service,
 
700
            dendpoint_template.public_url,
 
701
            dendpoint_template.admin_url,
 
702
            dendpoint_template.internal_url,
 
703
            dendpoint_template.enabled,
 
704
            dendpoint_template.is_global)
 
705
 
 
706
    def delete_endpoint_template(self, admin_token, endpoint_template_id):
 
707
        self.__validate_service_or_keystone_admin_token(admin_token)
 
708
        dendpoint_template = api.ENDPOINT_TEMPLATE.get(endpoint_template_id)
 
709
        if not dendpoint_template:
 
710
            raise fault.ItemNotFoundFault(
 
711
                "The endpoint template could not be found")
 
712
        #Delete Related endpoints
 
713
        endpoints = api.ENDPOINT_TEMPLATE.\
 
714
            endpoint_get_by_endpoint_template(endpoint_template_id)
 
715
        if endpoints != None:
 
716
            for endpoint in endpoints:
 
717
                api.ENDPOINT_TEMPLATE.endpoint_delete(endpoint.id)
 
718
        api.ENDPOINT_TEMPLATE.delete(endpoint_template_id)
 
719
 
 
720
    def get_endpoint_templates(self, admin_token, marker, limit, url):
 
721
        self.__validate_service_or_keystone_admin_token(admin_token)
 
722
 
 
723
        ts = []
 
724
        dendpoint_templates = api.ENDPOINT_TEMPLATE.get_page(marker, limit)
 
725
        for dendpoint_template in dendpoint_templates:
 
726
            ts.append(EndpointTemplate(
 
727
                dendpoint_template.id,
 
728
                dendpoint_template.region,
 
729
                dendpoint_template.service,
 
730
                dendpoint_template.public_url,
 
731
                dendpoint_template.admin_url,
 
732
                dendpoint_template.internal_url,
 
733
                dendpoint_template.enabled,
 
734
                dendpoint_template.is_global))
 
735
        prev, next = api.ENDPOINT_TEMPLATE.get_page_markers(marker, limit)
 
736
        links = []
 
737
        if prev:
 
738
            links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" \
 
739
                                                % (url, prev, limit)))
 
740
        if next:
 
741
            links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" \
 
742
                                                % (url, next, limit)))
 
743
        return EndpointTemplates(ts, links)
 
744
 
 
745
    def get_endpoint_template(self, admin_token, endpoint_template_id):
 
746
        self.__validate_service_or_keystone_admin_token(admin_token)
 
747
 
 
748
        dendpoint_template = api.ENDPOINT_TEMPLATE.get(endpoint_template_id)
 
749
        if not dendpoint_template:
 
750
            raise fault.ItemNotFoundFault(
 
751
                "The endpoint template could not be found")
 
752
        return EndpointTemplate(
 
753
            dendpoint_template.id,
 
754
            dendpoint_template.region,
 
755
            dendpoint_template.service,
 
756
            dendpoint_template.public_url,
 
757
            dendpoint_template.admin_url,
 
758
            dendpoint_template.internal_url,
 
759
            dendpoint_template.enabled,
 
760
            dendpoint_template.is_global)
 
761
 
 
762
    def get_tenant_endpoints(self, admin_token, marker, limit, url, tenant_id):
 
763
        self.__validate_service_or_keystone_admin_token(admin_token)
 
764
        if tenant_id == None:
 
765
            raise fault.BadRequestFault("Expecting a Tenant Id")
 
766
 
 
767
        if api.TENANT.get(tenant_id) == None:
 
768
            raise fault.ItemNotFoundFault("The tenant not found")
 
769
 
 
770
        ts = []
 
771
 
 
772
        dtenant_endpoints = \
 
773
            api.ENDPOINT_TEMPLATE.\
 
774
                endpoint_get_by_tenant_get_page(
 
775
                    tenant_id, marker, limit)
 
776
        for dtenant_endpoint in dtenant_endpoints:
 
777
            ts.append(Endpoint(dtenant_endpoint.id,
 
778
                    url + '/endpointTemplates/' + \
 
779
                    str(dtenant_endpoint.endpoint_template_id)))
 
780
        links = []
 
781
        if ts.__len__():
 
782
            prev, next = \
 
783
                api.ENDPOINT_TEMPLATE.endpoint_get_by_tenant_get_page_markers(
 
784
                    tenant_id, marker, limit)
 
785
            if prev:
 
786
                links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" %
 
787
                                      (url, prev, limit)))
 
788
            if next:
 
789
                links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" %
 
790
                                      (url, next, limit)))
 
791
        return Endpoints(ts, links)
 
792
 
 
793
    def create_endpoint_for_tenant(self, admin_token,
 
794
                                     tenant_id, endpoint_template, url):
 
795
        self.__validate_service_or_keystone_admin_token(admin_token)
 
796
        if tenant_id == None:
 
797
            raise fault.BadRequestFault("Expecting a Tenant Id")
 
798
        if api.TENANT.get(tenant_id) == None:
 
799
            raise fault.ItemNotFoundFault("The tenant not found")
 
800
 
 
801
        dendpoint_template = api.ENDPOINT_TEMPLATE.get(endpoint_template.id)
 
802
        if not dendpoint_template:
 
803
            raise fault.ItemNotFoundFault(
 
804
                "The endpoint template could not be found")
 
805
        dendpoint = models.Endpoints()
 
806
        dendpoint.tenant_id = tenant_id
 
807
        dendpoint.endpoint_template_id = endpoint_template.id
 
808
        dendpoint = api.ENDPOINT_TEMPLATE.endpoint_add(dendpoint)
 
809
        dendpoint = Endpoint(dendpoint.id, url +
 
810
            '/endpointTemplates/' + dendpoint.endpoint_template_id)
 
811
        return dendpoint
 
812
 
 
813
    def delete_endpoint(self, admin_token, endpoint_id):
 
814
        self.__validate_service_or_keystone_admin_token(admin_token)
 
815
        if api.ENDPOINT_TEMPLATE.get(endpoint_id) == None:
 
816
            raise fault.ItemNotFoundFault("The Endpoint is not found.")
 
817
        api.ENDPOINT_TEMPLATE.endpoint_delete(endpoint_id)
 
818
        return None
 
819
 
 
820
    #Service Operations
 
821
    def create_service(self, admin_token, service):
 
822
        self.__validate_service_or_keystone_admin_token(admin_token)
 
823
 
 
824
        if not isinstance(service, Service):
 
825
            raise fault.BadRequestFault("Expecting a Service")
 
826
 
 
827
        if service.service_id == None:
 
828
            raise fault.BadRequestFault("Expecting a Service Id")
 
829
 
 
830
        if api.SERVICE.get(service.service_id) != None:
 
831
            raise fault.ServiceConflictFault(
 
832
                "A service with that id already exists")
 
833
        dservice = models.Service()
 
834
        dservice.id = service.service_id
 
835
        dservice.desc = service.desc
 
836
        api.SERVICE.create(dservice)
 
837
        return service
 
838
 
 
839
    def get_services(self, admin_token, marker, limit, url):
 
840
        self.__validate_service_or_keystone_admin_token(admin_token)
 
841
 
 
842
        ts = []
 
843
        dservices = api.SERVICE.get_page(marker, limit)
 
844
        for dservice in dservices:
 
845
            ts.append(Service(dservice.id,
 
846
                                     dservice.desc))
 
847
        prev, next = api.SERVICE.get_page_markers(marker, limit)
 
848
        links = []
 
849
        if prev:
 
850
            links.append(atom.Link('prev', "%s?'marker=%s&limit=%s'" \
 
851
                                                % (url, prev, limit)))
 
852
        if next:
 
853
            links.append(atom.Link('next', "%s?'marker=%s&limit=%s'" \
 
854
                                                % (url, next, limit)))
 
855
        return Services(ts, links)
 
856
 
 
857
    def get_service(self, admin_token, service_id):
 
858
        self.__validate_service_or_keystone_admin_token(admin_token)
 
859
 
 
860
        dservice = api.SERVICE.get(service_id)
 
861
        if not dservice:
 
862
            raise fault.ItemNotFoundFault("The service could not be found")
 
863
        return Service(dservice.id, dservice.desc)
 
864
 
 
865
    def delete_service(self, admin_token, service_id):
 
866
        self.__validate_service_or_keystone_admin_token(admin_token)
 
867
        dservice = api.SERVICE.get(service_id)
 
868
 
 
869
        if not dservice:
 
870
            raise fault.ItemNotFoundFault("The service could not be found")
 
871
 
 
872
        #Delete Related Endpointtemplates and Endpoints.
 
873
        endpoint_templates = api.ENDPOINT_TEMPLATE.get_by_service(service_id)
 
874
        if endpoint_templates != None:
 
875
            for endpoint_template in endpoint_templates:
 
876
                endpoints = api.ENDPOINT_TEMPLATE.\
 
877
                    endpoint_get_by_endpoint_template(endpoint_template.id)
 
878
                if endpoints != None:
 
879
                    for endpoint in endpoints:
 
880
                        api.ENDPOINT_TEMPLATE.endpoint_delete(endpoint.id)
 
881
                api.ENDPOINT_TEMPLATE.delete(endpoint_template.id)
 
882
        #Delete Related Role and RoleRefs
 
883
        roles = api.ROLE.get_by_service(service_id)
 
884
        if roles != None:
 
885
            for role in roles:
 
886
                role_refs = api.ROLE.ref_get_by_role(role.id)
 
887
                if role_refs != None:
 
888
                    for role_ref in role_refs:
 
889
                        api.ROLE.ref_delete(role_ref.id)
 
890
                api.ROLE.delete(role.id)
 
891
        api.SERVICE.delete(service_id)