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

« back to all changes in this revision

Viewing changes to keystone/backends/ldap/api/role.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
import ldap
 
2
 
 
3
from keystone.backends.api import BaseTenantAPI
 
4
from keystone.common import exception
 
5
 
 
6
from .. import models
 
7
from .base import  BaseLdapAPI
 
8
 
 
9
 
 
10
class RoleAPI(BaseLdapAPI, BaseTenantAPI):
 
11
    DEFAULT_TREE_DN = 'ou=Groups,dc=example,dc=com'
 
12
    options_name = 'role_tree_dn'
 
13
    object_class = 'keystoneRole'
 
14
    model = models.Role
 
15
    attribute_mapping = {'desc': 'description', 'service_id': 'serviceId'}
 
16
 
 
17
    @staticmethod
 
18
    def _create_ref(role_id, tenant_id, user_id):
 
19
        role_id = '' if role_id is None else str(role_id)
 
20
        tenant_id = '' if tenant_id is None else str(tenant_id)
 
21
        user_id = '' if user_id is None else str(user_id)
 
22
        return '%d-%d-%s%s%s' % (len(role_id), len(tenant_id),
 
23
                                 role_id, tenant_id, user_id)
 
24
 
 
25
    @staticmethod
 
26
    def _explode_ref(role_ref):
 
27
        a = role_ref.split('-', 2)
 
28
        len_role = int(a[0])
 
29
        len_tenant = int(a[1])
 
30
        role_id = a[2][:len_role]
 
31
        role_id = None if len(role_id) == 0 else str(role_id)
 
32
        tenant_id = a[2][len_role:len_tenant + len_role]
 
33
        tenant_id = None if len(tenant_id) == 0 else str(tenant_id)
 
34
        user_id = a[2][len_tenant + len_role:]
 
35
        user_id = None if len(user_id) == 0 else str(user_id)
 
36
        return role_id, tenant_id, user_id
 
37
 
 
38
    def _subrole_id_to_dn(self, role_id, tenant_id):
 
39
        if tenant_id is None:
 
40
            return self._id_to_dn(role_id)
 
41
        else:
 
42
            return "cn=%s,%s" % (ldap.dn.escape_dn_chars(role_id),
 
43
                                 self.api.tenant._id_to_dn(tenant_id))
 
44
 
 
45
    def add_user(self, role_id, user_id, tenant_id=None):
 
46
        user = self.api.user.get(user_id)
 
47
        if user is None:
 
48
            raise exception.NotFound("User %s not found" % (user_id,))
 
49
        role_dn = self._subrole_id_to_dn(role_id, tenant_id)
 
50
        conn = self.api.get_connection()
 
51
        user_dn = self.api.user._id_to_dn(user_id)
 
52
        try:
 
53
            conn.modify_s(role_dn, [(ldap.MOD_ADD, 'member', user_dn)])
 
54
        except ldap.TYPE_OR_VALUE_EXISTS:
 
55
            raise exception.Duplicate(
 
56
                "User %s already has role %s in tenant %s" % (user_id,
 
57
                    role_id, tenant_id))
 
58
        except ldap.NO_SUCH_OBJECT:
 
59
            if tenant_id is None or self.get(role_id) is None:
 
60
                raise exception.NotFound("Role %s not found" % (role_id,))
 
61
            if tenant_id != None:
 
62
                tenant_dn = self.api.tenant._id_to_dn(tenant_id)
 
63
            else:
 
64
                tenant_dn = None
 
65
            attrs = [
 
66
                ('objectClass', 'keystoneTenantRole'),
 
67
                ('member', user_dn),
 
68
                ('keystoneRole', self._id_to_dn(role_id)),
 
69
            ]
 
70
            conn.add_s(role_dn, attrs)
 
71
        return models.UserRoleAssociation(
 
72
            id=self._create_ref(role_id, tenant_id, user_id),
 
73
            role_id=role_id, user_id=user_id, tenant_id=tenant_id)
 
74
 
 
75
    def get_by_service(self, service_id):
 
76
        roles = self.get_all('(serviceId=%s)' % \
 
77
                    (ldap.filter.escape_filter_chars(service_id),))
 
78
        try:
 
79
            res = []
 
80
            for role in roles:
 
81
                res.append(role)
 
82
            return res
 
83
        except IndexError:
 
84
            return None
 
85
 
 
86
    def get_role_assignments(self, tenant_id):
 
87
        conn = self.api.get_connection()
 
88
        query = '(objectClass=keystoneTenantRole)'
 
89
        tenant_dn = self.api.tenant._id_to_dn(tenant_id)
 
90
        try:
 
91
            roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
 
92
        except ldap.NO_SUCH_OBJECT:
 
93
            return []
 
94
        res = []
 
95
        for role_dn, attrs in roles:
 
96
            try:
 
97
                user_dns = attrs['member']
 
98
            except KeyError:
 
99
                continue
 
100
            for user_dn in user_dns:
 
101
                user_id = ldap.dn.str2dn(user_dn)[0][0][1]
 
102
                role_id = ldap.dn.str2dn(role_dn)[0][0][1]
 
103
                res.append(models.UserRoleAssociation(
 
104
                    id=self._create_ref(role_id, tenant_id, user_id),
 
105
                    user_id=user_id,
 
106
                    role_id=role_id,
 
107
                    tenant_id=tenant_id))
 
108
        return res
 
109
 
 
110
    def ref_get_all_global_roles(self, user_id):
 
111
        user_dn = self.api.user._id_to_dn(user_id)
 
112
        roles = self.get_all('(member=%s)' % (user_dn,))
 
113
        return [models.UserRoleAssociation(
 
114
                    id=self._create_ref(role.id, None, user_id),
 
115
                    role_id=role.id,
 
116
                    user_id=user_id) for role in roles]
 
117
 
 
118
    def ref_get_all_tenant_roles(self, user_id, tenant_id=None):
 
119
        conn = self.api.get_connection()
 
120
        user_dn = self.api.user._id_to_dn(user_id)
 
121
        query = '(&(objectClass=keystoneTenantRole)(member=%s))' % (user_dn,)
 
122
        if tenant_id is not None:
 
123
            tenant_dn = self.api.tenant._id_to_dn(tenant_id)
 
124
            try:
 
125
                roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
 
126
            except ldap.NO_SUCH_OBJECT:
 
127
                return []
 
128
            res = []
 
129
            for role_dn, _ in roles:
 
130
                role_id = ldap.dn.str2dn(role_dn)[0][0][1]
 
131
                res.append(models.UserRoleAssociation(
 
132
                       id=self._create_ref(role_id, tenant_id, user_id),
 
133
                       user_id=user_id,
 
134
                       role_id=role_id,
 
135
                       tenant_id=tenant_id))
 
136
            return res
 
137
        else:
 
138
            try:
 
139
                roles = conn.search_s(self.api.tenant.tree_dn,
 
140
                                        ldap.SCOPE_SUBTREE, query)
 
141
            except ldap.NO_SUCH_OBJECT:
 
142
                return []
 
143
            res = []
 
144
            for role_dn, _ in roles:
 
145
                role_id = ldap.dn.str2dn(role_dn)[0][0][1]
 
146
                tenant_id = ldap.dn.str2dn(role_dn)[1][0][1]
 
147
                res.append(models.UserRoleAssociation(
 
148
                       id=self._create_ref(role_id, tenant_id, user_id),
 
149
                       user_id=user_id,
 
150
                       role_id=role_id,
 
151
                       tenant_id=tenant_id))
 
152
            return res
 
153
 
 
154
    def ref_get(self, id):
 
155
        role_id, tenant_id, user_id = self._explode_ref(id)
 
156
        user_dn = self.api.user._id_to_dn(user_id)
 
157
        role_dn = self._subrole_id_to_dn(role_id, tenant_id)
 
158
        query = '(&(objectClass=keystoneTenantRole)(member=%s))' % (user_dn,)
 
159
        try:
 
160
            res = search_s(role_dn, ldap.SCOPE_BASE, query)
 
161
        except ldap.NO_SUCH_OBJECT:
 
162
            return None
 
163
        if len(res) == 0:
 
164
            return None
 
165
        return models.UserRoleAssociation(id=id, role_id=role_id,
 
166
                                tenant_id=tenant_id, user_id=user_id)
 
167
 
 
168
    def ref_delete(self, id):
 
169
        role_id, tenant_id, user_id = self._explode_ref(id)
 
170
        user_dn = self.api.user._id_to_dn(user_id)
 
171
        role_dn = self._subrole_id_to_dn(role_id, tenant_id)
 
172
        conn = self.api.get_connection()
 
173
        try:
 
174
            conn.modify_s(role_dn, [(ldap.MOD_DELETE, 'member', [user_dn])])
 
175
        except ldap.NO_SUCH_ATTRIBUTE:
 
176
            raise exception.NotFound("No such user in role")
 
177
 
 
178
    def ref_get_page(self, marker, limit, user_id):
 
179
        all_roles = self.ref_get_all_global_roles(user_id)
 
180
        for tenant in self.api.tenant.get_all():
 
181
            all_roles += self.ref_get_all_tenant_roles(user_id, tenant.id)
 
182
        return self._get_page(marker, limit, all_roles)
 
183
 
 
184
    def ref_get_page_markers(self, user_id, marker, limit):
 
185
        all_roles = self.ref_get_all_global_roles(user_id)
 
186
        for tenant in self.api.tenant.get_all():
 
187
            all_roles += self.ref_get_all_tenant_roles(user_id, tenant.id)
 
188
        return self._get_page_markers(marker, limit, all_roles)
 
189
 
 
190
    def ref_get_by_role(self, id):
 
191
        role_dn = self._id_to_dn(id)
 
192
        try:
 
193
            roles = self.get_all('(keystoneRole=%s)' % (role_dn,))
 
194
        except ldap.NO_SUCH_OBJECT:
 
195
            return []
 
196
        res = []
 
197
        for role_dn, attrs in roles:
 
198
            try:
 
199
                user_dns = attrs['member']
 
200
                tenant_dns = attrs['tenant']
 
201
            except KeyError:
 
202
                continue
 
203
            for user_dn in user_dns:
 
204
                user_id = ldap.dn.str2dn(user_dn)[0][0][1]
 
205
                tenant_id = None
 
206
                if tenant_dns != None:
 
207
                    for tenant_dn in tenant_dns:
 
208
                        tenant_id = ldap.dn.str2dn(tenant_dn)[0][0][1]
 
209
                role_id = ldap.dn.str2dn(role_dn)[0][0][1]
 
210
                res.append(models.UserRoleAssociation(
 
211
                    id=self._create_ref(role_id, tenant_id, user_id),
 
212
                    user_id=user_id,
 
213
                    role_id=role_id,
 
214
                    tenant_id=tenant_id))
 
215
        return res