Merge lp:~rlane/nova/ldap-schema-modifications-1 into lp:~hudson-openstack/nova/trunk

Proposed by Ryan Lane
Status: Merged
Approved by: Vish Ishaya
Approved revision: 393
Merged at revision: 489
Proposed branch: lp:~rlane/nova/ldap-schema-modifications-1
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 576 lines (+107/-153)
8 files modified
nova/auth/fakeldap.py (+3/-0)
nova/auth/ldapdriver.py (+92/-73)
nova/auth/nova_openldap.schema (+6/-40)
nova/auth/nova_sun.schema (+5/-8)
nova/auth/opendj.sh (+0/-1)
nova/auth/openssh-lpk_openldap.schema (+0/-19)
nova/auth/openssh-lpk_sun.schema (+0/-10)
nova/auth/slap.sh (+1/-2)
To merge this branch: bzr merge lp:~rlane/nova/ldap-schema-modifications-1
Reviewer Review Type Date Requested Status
Devin Carlen (community) Approve
Vish Ishaya (community) Approve
Review via email: mp+42662@code.launchpad.net

Commit message

Simplifies and improves ldap schema.

To post a comment you must log in.
Revision history for this message
Vish Ishaya (vishvananda) wrote :
Download full text (8.0 KiB)

Suggestion:

Can we have the isAdmin/isNovaAdmin attribute as a flag that defaults to isNovaAdmin. I'm thinking that it would be nice if we don't force an ldap data migration if users have the old schema.

On Dec 3, 2010, at 9:47 AM, Ryan Lane wrote:

> Ryan Lane has proposed merging lp:~rlane/nova/ldap-schema-modifications-1 into lp:nova.
>
> Requested reviews:
> Nova Core (nova-core)
> Related bugs:
> #681030 Nova's LDAP schema has an unneeded requirement on the nis or bis schema
> https://bugs.launchpad.net/bugs/681030
>
> --
> https://code.launchpad.net/~rlane/nova/ldap-schema-modifications-1/+merge/42662
> Your team Nova Core is requested to review the proposed merge of lp:~rlane/nova/ldap-schema-modifications-1 into lp:nova.
> === modified file 'nova/auth/ldapdriver.py'
> --- nova/auth/ldapdriver.py 2010-11-26 17:01:50 +0000
> +++ nova/auth/ldapdriver.py 2010-12-03 17:46:55 +0000
> @@ -37,6 +37,8 @@
> flags.DEFINE_string('ldap_password', 'changeme', 'LDAP password')
> flags.DEFINE_string('ldap_user_dn', 'cn=Manager,dc=example,dc=com',
> 'DN of admin user')
> +flags.DEFINE_string('ldap_user_id_attribute', 'uid', 'Attribute to use as id')
> +flags.DEFINE_string('ldap_user_name_attribute', 'cn', 'Attribute to use as name')
> flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users')
> flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
> 'OU for Users')
> @@ -131,12 +133,12 @@
> 'inetOrgPerson',
> 'novaUser']),
> ('ou', [FLAGS.ldap_user_unit]),
> - ('uid', [name]),
> + (FLAGS.ldap_user_id_attribute, [name]),
> ('sn', [name]),
> - ('cn', [name]),
> + (FLAGS.ldap_user_name_attribute, [name]),
> ('secretKey', [secret_key]),
> ('accessKey', [access_key]),
> - ('isAdmin', [str(is_admin).upper()]),
> + ('isNovaAdmin', [str(is_admin).upper()]),
> ]
> self.conn.add_s(self.__uid_to_dn(name), attr)
> return self.__to_user(dict(attr))
> @@ -274,7 +276,7 @@
> if secret_key:
> attr.append((self.ldap.MOD_REPLACE, 'secretKey', secret_key))
> if admin is not None:
> - attr.append((self.ldap.MOD_REPLACE, 'isAdmin', str(admin).upper()))
> + attr.append((self.ldap.MOD_REPLACE, 'isNovaAdmin', str(admin).upper()))
> self.conn.modify_s(self.__uid_to_dn(uid), attr)
>
> def __user_exists(self, uid):
> @@ -450,11 +452,11 @@
> if attr == None:
> return None
> return {
> - 'id': attr['uid'][0],
> - 'name': attr['cn'][0],
> + 'id': attr[FLAGS.ldap_user_id_attribute][0],
> + 'name': attr[FLAGS.ldap_user_name_attribute][0],
> 'access': attr['accessKey'][0],
> 'secret': attr['secretKey'][0],
> - 'admin': (attr['isAdmin'][0] == 'TRUE')}
> + 'admin': (attr['isNovaAdmin'][0] == 'TRUE')}
>
> def __to_project(self, attr):
> """Convert ldap attributes to Project object"""
> @@ -474,9 +476,10 @@
> return dn.split(','...

Read more...

Revision history for this message
Ryan Lane (rlane) wrote :

After thinking about it more, it would be good to get rid of the isAdmin attribute altogether and use a group for this. This will cause more queries, but I can reduce that for servers that support memberOf.

This is a more standard way of handling this in LDAP.

Revision history for this message
Ryan Lane (rlane) wrote :

I've found a further improvement to be made, that should likely be added before merging this...

The groupOfNames objectclass has an "owner" attribute that expects a DN. Using this we can eliminate the novaProject objectclass and attributes.

Overall I think the schema can be reduced to the novaUser objectclass, and the accessKey and secretKey attributes.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

Yes, I had considered the same thing (owner and group instead of specific project class). It will require refining the search for roles to make sure that it doesn't pick up projects by accident.

isAdmin could be moved to a group as well. But I think it needs to appear to external services as an attribute of the user. The purpose of isAdmin is to completely bypass role checking.

Vish

On Dec 3, 2010, at 1:25 PM, Ryan Lane wrote:

> I've found a further improvement to be made, that should likely be added before merging this...
>
> The groupOfNames objectclass has an "owner" attribute that expects a DN. Using this we can eliminate the novaProject objectclass and attributes.
>
> Overall I think the schema can be reduced to the novaUser objectclass, and the accessKey and secretKey attributes.
> --
> https://code.launchpad.net/~rlane/nova/ldap-schema-modifications-1/+merge/42662
> Your team Nova Core is requested to review the proposed merge of lp:~rlane/nova/ldap-schema-modifications-1 into lp:nova.

Revision history for this message
Ryan Lane (rlane) wrote :

All projects should have an owner, and roles shouldn't. We can refine the search for projects to include owner in the query.

Revision history for this message
Ryan Lane (rlane) wrote :

Alternatively, we could require that roles and projects should be placed in separate OUs.

Revision history for this message
Ryan Lane (rlane) wrote :

Made suggested schema selection change. This branch now also removes the novaProject part of the schema. Only novaUser remains.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

Minor nits.
Can you align the second line with the parens for multiline code?
                    attr.append((self.ldap.MOD_REPLACE, 'accessKey',
                    [access_key]))
becomes:
                    attr.append((self.ldap.MOD_REPLACE, 'accessKey',
                                 [access_key]))

makes it a little easier to read.

also would you mind changing <email address hidden> > <email address hidden> ?

Finally, is there a reason why you made class variables for the params
LdapDriver.project_pattern vs. self.project_pattern ?
It seems a little odd to me to change the class variables in __init__ which is the ctor for the instance of the class. Not sure if there is a prettier pattern, but perhaps if version 2 ... elif version 1 ... and using self.project_pattern would be a little nicer?

review: Needs Information
Revision history for this message
Ryan Lane (rlane) wrote :

I originally tried setting object variables, but it caused a bunch of tests to fail because the fake ldap driver couldn't access them. Also, one variable is used in a static method. Using class variables eliminated those problems. If there's a better way, I'd love to use it; I used this method because I couldn't get others to work.

Also just pushed the other requested fixes.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

Understandable. LGTM

review: Approve
Revision history for this message
Devin Carlen (devcamcar) wrote :

Nice work, this is much cleaner.

review: Approve
Revision history for this message
OpenStack Infra (hudson-openstack) wrote :

Attempt to merge into lp:nova failed due to conflicts:

text conflict in nova/auth/ldapdriver.py

Revision history for this message
Vish Ishaya (vishvananda) wrote :

this needs a quick trunk merge and repush.

Revision history for this message
Ryan Lane (rlane) wrote :

Merged with trunk and resolved conflict; repushed.

Revision history for this message
OpenStack Infra (hudson-openstack) wrote :
Download full text (34.5 KiB)

The attempt to merge lp:~rlane/nova/ldap-schema-modifications-1 into lp:nova failed. Below is the output from the failed tests.

nova.tests.access_unittest
  AccessTestCase
    test_001_allow_all ... [OK]
    test_002_allow_none ... [OK]
    test_003_allow_project_manager ... [OK]
    test_004_allow_sys_and_net ... [OK]
nova.tests.api_unittest
  ApiEc2TestCase
    test_authorize_revoke_security_group_cidr ... [OK]
    test_authorize_revoke_security_group_foreign_group ... [OK]
    test_create_delete_security_group ... [OK]
    test_describe_instances ... [OK]
    test_get_all_key_pairs ... [OK]
    test_get_all_security_groups ... [OK]
  XmlConversionTestCase
    test_number_conversion ... [OK]
nova.tests.auth_unittest
  AuthManagerDbTestCase
    test_004_signature_is_valid ... [OK]
    test_005_can_get_credentials ... [OK]
    test_add_user_role_doesnt_infect_project_roles ... [OK]
    test_adding_role_to_project_is_ignored_unless_added_to_user ... [OK]
    test_can_add_and_remove_user_role ... [OK]
    test_can_add_remove_user_with_role ... [OK]
    test_can_add_user_to_project ... [OK]
    test_can_create_and_get_project ... [OK]
    test_can_create_and_get_project_with_attributes ... [OK]
    test_can_create_project_with_manager ... [OK]
    test_can_delete_project ... [OK]
    test_can_delete_user ... [OK]
    test_can_generate_x509 ... [OK]
    test_can_list_project_roles ... [OK]
    test_can_list_projects ... [OK]
    test_can_list_user_roles ... [OK]
    test_can_list_users ... [OK]
    test_can_modify_project ... [OK]
    test_can_modify_users ... [OK]
    test_can_remove_project_role_but_keep_user_role ... [OK]
    test_can_remove_user_from_project ... [OK]
    test_can_remove_user_roles ... [OK]
    test_can_retrieve_project_by_user ... [OK]
    test_create_and_find_user ... [OK]
    test_create_and_find_with_properties ... [OK]
    test_create_project_assigns_m...

Revision history for this message
Vish Ishaya (vishvananda) wrote :

This looks like a bunk failure, reapproving.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

something odd is happening with tarmac, trying a reapprove first to get it building properly, then we'll try again.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

yes tarmac is complaining about some odd bzrlib error. We'll have to wait for packaging gurus to figure out what is going on.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

I'm also noticing that you aren't in Authors or .mailmap correctly. It also seems that you haven't signed the CLA, which might be causing the merge to fail.

Revision history for this message
Ryan Lane (rlane32) wrote :

That's odd.

<email address hidden>

Sent from my iPhone

On Dec 22, 2010, at 6:41 PM, Vish Ishaya <email address hidden> wrote:

> yes tarmac is complaining about some odd bzrlib error. We'll have to wait for packaging gurus to figure out what is going on.
> --
> https://code.launchpad.net/~rlane/nova/ldap-schema-modifications-1/+merge/42662
> You are the owner of lp:~rlane/nova/ldap-schema-modifications-1.

Revision history for this message
Ryan Lane (rlane32) wrote :

I did sign the cla... I can do so again if needed.

Sent from my iPhone

On Dec 22, 2010, at 7:47 PM, Vish Ishaya <email address hidden> wrote:

> I'm also noticing that you aren't in Authors or .mailmap correctly. It also seems that you haven't signed the CLA, which might be causing the merge to fail.
> --
> https://code.launchpad.net/~rlane/nova/ldap-schema-modifications-1/+merge/42662
> You are the owner of lp:~rlane/nova/ldap-schema-modifications-1.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

If you signed it, you probably just need to add your info to this page:

http://wiki.openstack.org/Contributors

On Dec 22, 2010, at 5:53 PM, Ryan Lane wrote:

> I did sign the cla... I can do so again if needed.
>
> Sent from my iPhone
>
> On Dec 22, 2010, at 7:47 PM, Vish Ishaya <email address hidden> wrote:
>
>> I'm also noticing that you aren't in Authors or .mailmap correctly. It also seems that you haven't signed the CLA, which might be causing the merge to fail.
>> --
>> https://code.launchpad.net/~rlane/nova/ldap-schema-modifications-1/+merge/42662
>> You are the owner of lp:~rlane/nova/ldap-schema-modifications-1.
> --
> https://code.launchpad.net/~rlane/nova/ldap-schema-modifications-1/+merge/42662
> You are reviewing the proposed merge of lp:~rlane/nova/ldap-schema-modifications-1 into lp:nova.

Revision history for this message
Vish Ishaya (vishvananda) wrote :

It was the lack of a commit message that was causing it to fail. Trying to merge again.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/auth/fakeldap.py'
2--- nova/auth/fakeldap.py 2010-12-22 20:59:53 +0000
3+++ nova/auth/fakeldap.py 2010-12-22 23:56:00 +0000
4@@ -150,6 +150,9 @@
5 """Match a given key and value against an attribute list."""
6 if key not in attrs:
7 return False
8+ # This is a wild card search. Implemented as all or nothing for now.
9+ if value == "*":
10+ return True
11 if key != "objectclass":
12 return value in attrs[key]
13 # it is an objectclass check, so check subclasses
14
15=== modified file 'nova/auth/ldapdriver.py'
16--- nova/auth/ldapdriver.py 2010-12-22 20:59:53 +0000
17+++ nova/auth/ldapdriver.py 2010-12-22 23:56:00 +0000
18@@ -32,11 +32,16 @@
19
20
21 FLAGS = flags.FLAGS
22+flags.DEFINE_integer('ldap_schema_version', 2,
23+ 'Current version of the LDAP schema')
24 flags.DEFINE_string('ldap_url', 'ldap://localhost',
25 'Point this at your ldap server')
26 flags.DEFINE_string('ldap_password', 'changeme', 'LDAP password')
27 flags.DEFINE_string('ldap_user_dn', 'cn=Manager,dc=example,dc=com',
28 'DN of admin user')
29+flags.DEFINE_string('ldap_user_id_attribute', 'uid', 'Attribute to use as id')
30+flags.DEFINE_string('ldap_user_name_attribute', 'cn',
31+ 'Attribute to use as name')
32 flags.DEFINE_string('ldap_user_unit', 'Users', 'OID for Users')
33 flags.DEFINE_string('ldap_user_subtree', 'ou=Users,dc=example,dc=com',
34 'OU for Users')
35@@ -73,10 +78,20 @@
36 Defines enter and exit and therefore supports the with/as syntax.
37 """
38
39+ project_pattern = '(owner=*)'
40+ isadmin_attribute = 'isNovaAdmin'
41+ project_attribute = 'owner'
42+ project_objectclass = 'groupOfNames'
43+
44 def __init__(self):
45 """Imports the LDAP module"""
46 self.ldap = __import__('ldap')
47 self.conn = None
48+ if FLAGS.ldap_schema_version == 1:
49+ LdapDriver.project_pattern = '(objectclass=novaProject)'
50+ LdapDriver.isadmin_attribute = 'isAdmin'
51+ LdapDriver.project_attribute = 'projectManager'
52+ LdapDriver.project_objectclass = 'novaProject'
53
54 def __enter__(self):
55 """Creates the connection to LDAP"""
56@@ -104,13 +119,13 @@
57 """Retrieve project by id"""
58 dn = 'cn=%s,%s' % (pid,
59 FLAGS.ldap_project_subtree)
60- attr = self.__find_object(dn, '(objectclass=novaProject)')
61+ attr = self.__find_object(dn, LdapDriver.project_pattern)
62 return self.__to_project(attr)
63
64 def get_users(self):
65 """Retrieve list of users"""
66 attrs = self.__find_objects(FLAGS.ldap_user_subtree,
67- '(objectclass=novaUser)')
68+ '(objectclass=novaUser)')
69 users = []
70 for attr in attrs:
71 user = self.__to_user(attr)
72@@ -120,7 +135,7 @@
73
74 def get_projects(self, uid=None):
75 """Retrieve list of projects"""
76- pattern = '(objectclass=novaProject)'
77+ pattern = LdapDriver.project_pattern
78 if uid:
79 pattern = "(&%s(member=%s))" % (pattern, self.__uid_to_dn(uid))
80 attrs = self.__find_objects(FLAGS.ldap_project_subtree,
81@@ -139,23 +154,25 @@
82 # Malformed entries are useless, replace attributes found.
83 attr = []
84 if 'secretKey' in user.keys():
85- attr.append((self.ldap.MOD_REPLACE, 'secretKey', \
86- [secret_key]))
87+ attr.append((self.ldap.MOD_REPLACE, 'secretKey',
88+ [secret_key]))
89 else:
90- attr.append((self.ldap.MOD_ADD, 'secretKey', \
91- [secret_key]))
92+ attr.append((self.ldap.MOD_ADD, 'secretKey',
93+ [secret_key]))
94 if 'accessKey' in user.keys():
95- attr.append((self.ldap.MOD_REPLACE, 'accessKey', \
96- [access_key]))
97- else:
98- attr.append((self.ldap.MOD_ADD, 'accessKey', \
99- [access_key]))
100- if 'isAdmin' in user.keys():
101- attr.append((self.ldap.MOD_REPLACE, 'isAdmin', \
102- [str(is_admin).upper()]))
103- else:
104- attr.append((self.ldap.MOD_ADD, 'isAdmin', \
105- [str(is_admin).upper()]))
106+ attr.append((self.ldap.MOD_REPLACE, 'accessKey',
107+ [access_key]))
108+ else:
109+ attr.append((self.ldap.MOD_ADD, 'accessKey',
110+ [access_key]))
111+ if LdapDriver.isadmin_attribute in user.keys():
112+ attr.append((self.ldap.MOD_REPLACE,
113+ LdapDriver.isadmin_attribute,
114+ [str(is_admin).upper()]))
115+ else:
116+ attr.append((self.ldap.MOD_ADD,
117+ LdapDriver.isadmin_attribute,
118+ [str(is_admin).upper()]))
119 self.conn.modify_s(self.__uid_to_dn(name), attr)
120 return self.get_user(name)
121 else:
122@@ -168,12 +185,12 @@
123 'inetOrgPerson',
124 'novaUser']),
125 ('ou', [FLAGS.ldap_user_unit]),
126- ('uid', [name]),
127+ (FLAGS.ldap_user_id_attribute, [name]),
128 ('sn', [name]),
129- ('cn', [name]),
130+ (FLAGS.ldap_user_name_attribute, [name]),
131 ('secretKey', [secret_key]),
132 ('accessKey', [access_key]),
133- ('isAdmin', [str(is_admin).upper()]),
134+ (LdapDriver.isadmin_attribute, [str(is_admin).upper()]),
135 ]
136 self.conn.add_s(self.__uid_to_dn(name), attr)
137 return self.__to_user(dict(attr))
138@@ -204,10 +221,10 @@
139 if not manager_dn in members:
140 members.append(manager_dn)
141 attr = [
142- ('objectclass', ['novaProject']),
143+ ('objectclass', [LdapDriver.project_objectclass]),
144 ('cn', [name]),
145 ('description', [description]),
146- ('projectManager', [manager_dn]),
147+ (LdapDriver.project_attribute, [manager_dn]),
148 ('member', members)]
149 self.conn.add_s('cn=%s,%s' % (name, FLAGS.ldap_project_subtree), attr)
150 return self.__to_project(dict(attr))
151@@ -223,7 +240,8 @@
152 "manager %s doesn't exist")
153 % manager_uid)
154 manager_dn = self.__uid_to_dn(manager_uid)
155- attr.append((self.ldap.MOD_REPLACE, 'projectManager', manager_dn))
156+ attr.append((self.ldap.MOD_REPLACE, LdapDriver.project_attribute,
157+ manager_dn))
158 if description:
159 attr.append((self.ldap.MOD_REPLACE, 'description', description))
160 self.conn.modify_s('cn=%s,%s' % (project_id,
161@@ -283,10 +301,9 @@
162 return roles
163 else:
164 project_dn = 'cn=%s,%s' % (project_id, FLAGS.ldap_project_subtree)
165- roles = self.__find_objects(project_dn,
166- '(&(&(objectclass=groupOfNames)'
167- '(!(objectclass=novaProject)))'
168- '(member=%s))' % self.__uid_to_dn(uid))
169+ query = ('(&(&(objectclass=groupOfNames)(!%s))(member=%s))' %
170+ (LdapDriver.project_pattern, self.__uid_to_dn(uid)))
171+ roles = self.__find_objects(project_dn, query)
172 return [role['cn'][0] for role in roles]
173
174 def delete_user(self, uid):
175@@ -300,14 +317,15 @@
176 # Retrieve user by name
177 user = self.__get_ldap_user(uid)
178 if 'secretKey' in user.keys():
179- attr.append((self.ldap.MOD_DELETE, 'secretKey', \
180- user['secretKey']))
181+ attr.append((self.ldap.MOD_DELETE, 'secretKey',
182+ user['secretKey']))
183 if 'accessKey' in user.keys():
184- attr.append((self.ldap.MOD_DELETE, 'accessKey', \
185- user['accessKey']))
186- if 'isAdmin' in user.keys():
187- attr.append((self.ldap.MOD_DELETE, 'isAdmin', \
188- user['isAdmin']))
189+ attr.append((self.ldap.MOD_DELETE, 'accessKey',
190+ user['accessKey']))
191+ if LdapDriver.isadmin_attribute in user.keys():
192+ attr.append((self.ldap.MOD_DELETE,
193+ LdapDriver.isadmin_attribute,
194+ user[LdapDriver.isadmin_attribute]))
195 self.conn.modify_s(self.__uid_to_dn(uid), attr)
196 else:
197 # Delete entry
198@@ -329,7 +347,8 @@
199 if secret_key:
200 attr.append((self.ldap.MOD_REPLACE, 'secretKey', secret_key))
201 if admin is not None:
202- attr.append((self.ldap.MOD_REPLACE, 'isAdmin', str(admin).upper()))
203+ attr.append((self.ldap.MOD_REPLACE, LdapDriver.isadmin_attribute,
204+ str(admin).upper()))
205 self.conn.modify_s(self.__uid_to_dn(uid), attr)
206
207 def __user_exists(self, uid):
208@@ -347,7 +366,7 @@
209 def __get_ldap_user(self, uid):
210 """Retrieve LDAP user entry by id"""
211 attr = self.__find_object(self.__uid_to_dn(uid),
212- '(objectclass=novaUser)')
213+ '(objectclass=novaUser)')
214 return attr
215
216 def __find_object(self, dn, query=None, scope=None):
217@@ -383,19 +402,21 @@
218
219 def __find_role_dns(self, tree):
220 """Find dns of role objects in given tree"""
221- return self.__find_dns(tree,
222- '(&(objectclass=groupOfNames)(!(objectclass=novaProject)))')
223+ query = ('(&(objectclass=groupOfNames)(!%s))' %
224+ LdapDriver.project_pattern)
225+ return self.__find_dns(tree, query)
226
227 def __find_group_dns_with_member(self, tree, uid):
228 """Find dns of group objects in a given tree that contain member"""
229- dns = self.__find_dns(tree,
230- '(&(objectclass=groupOfNames)(member=%s))' %
231- self.__uid_to_dn(uid))
232+ query = ('(&(objectclass=groupOfNames)(member=%s))' %
233+ self.__uid_to_dn(uid))
234+ dns = self.__find_dns(tree, query)
235 return dns
236
237 def __group_exists(self, dn):
238 """Check if group exists"""
239- return self.__find_object(dn, '(objectclass=groupOfNames)') is not None
240+ query = '(objectclass=groupOfNames)'
241+ return self.__find_object(dn, query) is not None
242
243 @staticmethod
244 def __role_to_dn(role, project_id=None):
245@@ -417,9 +438,9 @@
246 if member_uids is not None:
247 for member_uid in member_uids:
248 if not self.__user_exists(member_uid):
249- raise exception.NotFound(_("Group can't be created "
250- "because user %s doesn't exist")
251- % member_uid)
252+ raise exception.NotFound("Group can't be created "
253+ "because user %s doesn't exist" %
254+ member_uid)
255 members.append(self.__uid_to_dn(member_uid))
256 dn = self.__uid_to_dn(uid)
257 if not dn in members:
258@@ -434,9 +455,8 @@
259 def __is_in_group(self, uid, group_dn):
260 """Check if user is in group"""
261 if not self.__user_exists(uid):
262- raise exception.NotFound(_("User %s can't be searched in group "
263- "because the user doesn't exist")
264- % uid)
265+ raise exception.NotFound("User %s can't be searched in group "
266+ "because the user doesn't exist" % uid)
267 if not self.__group_exists(group_dn):
268 return False
269 res = self.__find_object(group_dn,
270@@ -447,12 +467,11 @@
271 def __add_to_group(self, uid, group_dn):
272 """Add user to group"""
273 if not self.__user_exists(uid):
274- raise exception.NotFound(_("User %s can't be added to the group "
275- "because the user doesn't exist")
276- % uid)
277+ raise exception.NotFound("User %s can't be added to the group "
278+ "because the user doesn't exist" % uid)
279 if not self.__group_exists(group_dn):
280- raise exception.NotFound(_("The group at dn %s doesn't exist")
281- % group_dn)
282+ raise exception.NotFound("The group at dn %s doesn't exist" %
283+ group_dn)
284 if self.__is_in_group(uid, group_dn):
285 raise exception.Duplicate(_("User %s is already a member of "
286 "the group %s") % (uid, group_dn))
287@@ -462,18 +481,17 @@
288 def __remove_from_group(self, uid, group_dn):
289 """Remove user from group"""
290 if not self.__group_exists(group_dn):
291- raise exception.NotFound(_("The group at dn %s doesn't exist")
292- % group_dn)
293+ raise exception.NotFound("The group at dn %s doesn't exist" %
294+ group_dn)
295 if not self.__user_exists(uid):
296- raise exception.NotFound(_("User %s can't be removed from the "
297- "group because the user doesn't exist")
298- % uid)
299+ raise exception.NotFound("User %s can't be removed from the "
300+ "group because the user doesn't exist" %
301+ uid)
302 if not self.__is_in_group(uid, group_dn):
303- raise exception.NotFound(_("User %s is not a member of the group")
304- % uid)
305+ raise exception.NotFound("User %s is not a member of the group" %
306+ uid)
307 # NOTE(vish): remove user from group and any sub_groups
308- sub_dns = self.__find_group_dns_with_member(
309- group_dn, uid)
310+ sub_dns = self.__find_group_dns_with_member(group_dn, uid)
311 for sub_dn in sub_dns:
312 self.__safe_remove_from_group(uid, sub_dn)
313
314@@ -491,9 +509,8 @@
315 def __remove_from_all(self, uid):
316 """Remove user from all roles and projects"""
317 if not self.__user_exists(uid):
318- raise exception.NotFound(_("User %s can't be removed from all "
319- "because the user doesn't exist")
320- % uid)
321+ raise exception.NotFound("User %s can't be removed from all "
322+ "because the user doesn't exist" % uid)
323 role_dns = self.__find_group_dns_with_member(
324 FLAGS.role_project_subtree, uid)
325 for role_dn in role_dns:
326@@ -521,13 +538,13 @@
327 if attr is None:
328 return None
329 if ('accessKey' in attr.keys() and 'secretKey' in attr.keys() \
330- and 'isAdmin' in attr.keys()):
331+ and LdapDriver.isadmin_attribute in attr.keys()):
332 return {
333- 'id': attr['uid'][0],
334- 'name': attr['cn'][0],
335+ 'id': attr[FLAGS.ldap_user_id_attribute][0],
336+ 'name': attr[FLAGS.ldap_user_name_attribute][0],
337 'access': attr['accessKey'][0],
338 'secret': attr['secretKey'][0],
339- 'admin': (attr['isAdmin'][0] == 'TRUE')}
340+ 'admin': (attr[LdapDriver.isadmin_attribute][0] == 'TRUE')}
341 else:
342 return None
343
344@@ -539,7 +556,8 @@
345 return {
346 'id': attr['cn'][0],
347 'name': attr['cn'][0],
348- 'project_manager_id': self.__dn_to_uid(attr['projectManager'][0]),
349+ 'project_manager_id':
350+ self.__dn_to_uid(attr[LdapDriver.project_attribute][0]),
351 'description': attr.get('description', [None])[0],
352 'member_ids': [self.__dn_to_uid(x) for x in member_dns]}
353
354@@ -549,9 +567,10 @@
355 return dn.split(',')[0].split('=')[1]
356
357 @staticmethod
358- def __uid_to_dn(dn):
359+ def __uid_to_dn(uid):
360 """Convert uid to dn"""
361- return 'uid=%s,%s' % (dn, FLAGS.ldap_user_subtree)
362+ return (FLAGS.ldap_user_id_attribute + '=%s,%s'
363+ % (uid, FLAGS.ldap_user_subtree))
364
365
366 class FakeLdapDriver(LdapDriver):
367
368=== modified file 'nova/auth/nova_openldap.schema'
369--- nova/auth/nova_openldap.schema 2010-10-25 22:42:49 +0000
370+++ nova/auth/nova_openldap.schema 2010-12-22 23:56:00 +0000
371@@ -1,7 +1,9 @@
372 #
373 # Person object for Nova
374 # inetorgperson with extra attributes
375-# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
376+# Schema version: 2
377+# Authors: Vishvananda Ishaya <vishvananda@gmail.com>
378+# Ryan Lane <rlane@wikimedia.org>
379 #
380 #
381
382@@ -31,54 +33,18 @@
383 )
384
385 attributetype (
386- novaAttrs:3
387- NAME 'keyFingerprint'
388- DESC 'Fingerprint of private key'
389- EQUALITY caseIgnoreMatch
390- SUBSTR caseIgnoreSubstringsMatch
391- SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
392- SINGLE-VALUE
393- )
394-
395-attributetype (
396 novaAttrs:4
397- NAME 'isAdmin'
398- DESC 'Is user an administrator?'
399+ NAME 'isNovaAdmin'
400+ DESC 'Is user an nova administrator?'
401 EQUALITY booleanMatch
402 SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
403 SINGLE-VALUE
404 )
405
406-attributetype (
407- novaAttrs:5
408- NAME 'projectManager'
409- DESC 'Project Managers of a project'
410- SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
411- )
412-
413 objectClass (
414 novaOCs:1
415 NAME 'novaUser'
416 DESC 'access and secret keys'
417 AUXILIARY
418- MUST ( uid )
419- MAY ( accessKey $ secretKey $ isAdmin )
420- )
421-
422-objectClass (
423- novaOCs:2
424- NAME 'novaKeyPair'
425- DESC 'Key pair for User'
426- SUP top
427- STRUCTURAL
428- MUST ( cn $ sshPublicKey $ keyFingerprint )
429- )
430-
431-objectClass (
432- novaOCs:3
433- NAME 'novaProject'
434- DESC 'Container for project'
435- SUP groupOfNames
436- STRUCTURAL
437- MUST ( cn $ projectManager )
438+ MAY ( accessKey $ secretKey $ isNovaAdmin )
439 )
440
441=== modified file 'nova/auth/nova_sun.schema'
442--- nova/auth/nova_sun.schema 2010-10-25 22:42:49 +0000
443+++ nova/auth/nova_sun.schema 2010-12-22 23:56:00 +0000
444@@ -1,16 +1,13 @@
445 #
446 # Person object for Nova
447 # inetorgperson with extra attributes
448-# Author: Vishvananda Ishaya <vishvananda@yahoo.com>
449-# Modified for strict RFC 4512 compatibility by: Ryan Lane <ryan@ryandlane.com>
450+# Schema version: 2
451+# Authors: Vishvananda Ishaya <vishvananda@gmail.com>
452+# Ryan Lane <rlane@wikimedia.org>
453 #
454 # using internet experimental oid arc as per BP64 3.1
455 dn: cn=schema
456 attributeTypes: ( 1.3.6.1.3.1.666.666.3.1 NAME 'accessKey' DESC 'Key for accessing data' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
457 attributeTypes: ( 1.3.6.1.3.1.666.666.3.2 NAME 'secretKey' DESC 'Secret key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
458-attributeTypes: ( 1.3.6.1.3.1.666.666.3.3 NAME 'keyFingerprint' DESC 'Fingerprint of private key' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE)
459-attributeTypes: ( 1.3.6.1.3.1.666.666.3.4 NAME 'isAdmin' DESC 'Is user an administrator?' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
460-attributeTypes: ( 1.3.6.1.3.1.666.666.3.5 NAME 'projectManager' DESC 'Project Managers of a project' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
461-objectClasses: ( 1.3.6.1.3.1.666.666.4.1 NAME 'novaUser' DESC 'access and secret keys' SUP top AUXILIARY MUST ( uid ) MAY ( accessKey $ secretKey $ isAdmin ) )
462-objectClasses: ( 1.3.6.1.3.1.666.666.4.2 NAME 'novaKeyPair' DESC 'Key pair for User' SUP top STRUCTURAL MUST ( cn $ sshPublicKey $ keyFingerprint ) )
463-objectClasses: ( 1.3.6.1.3.1.666.666.4.3 NAME 'novaProject' DESC 'Container for project' SUP groupOfNames STRUCTURAL MUST ( cn $ projectManager ) )
464+attributeTypes: ( 1.3.6.1.3.1.666.666.3.4 NAME 'isNovaAdmin' DESC 'Is user a nova administrator?' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
465+objectClasses: ( 1.3.6.1.3.1.666.666.4.1 NAME 'novaUser' DESC 'access and secret keys' SUP top AUXILIARY MAY ( accessKey $ secretKey $ isNovaAdmin ) )
466
467=== modified file 'nova/auth/opendj.sh'
468--- nova/auth/opendj.sh 2010-11-30 23:12:19 +0000
469+++ nova/auth/opendj.sh 2010-12-22 23:56:00 +0000
470@@ -32,7 +32,6 @@
471 schemapath='/var/opendj/instance/config/schema'
472 cp $abspath/openssh-lpk_sun.schema $schemapath/97-openssh-lpk_sun.ldif
473 cp $abspath/nova_sun.schema $schemapath/98-nova_sun.ldif
474-chown opendj:opendj $schemapath/97-openssh-lpk_sun.ldif
475 chown opendj:opendj $schemapath/98-nova_sun.ldif
476
477 cat >/etc/ldap/ldap.conf <<LDAP_CONF_EOF
478
479=== added file 'nova/auth/openssh-lpk_openldap.schema'
480--- nova/auth/openssh-lpk_openldap.schema 1970-01-01 00:00:00 +0000
481+++ nova/auth/openssh-lpk_openldap.schema 2010-12-22 23:56:00 +0000
482@@ -0,0 +1,19 @@
483+#
484+# LDAP Public Key Patch schema for use with openssh-ldappubkey
485+# Author: Eric AUGE <eau@phear.org>
486+#
487+# Based on the proposal of : Mark Ruijter
488+#
489+
490+
491+# octetString SYNTAX
492+attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
493+ DESC 'MANDATORY: OpenSSH Public key'
494+ EQUALITY octetStringMatch
495+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
496+
497+# printableString SYNTAX yes|no
498+objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
499+ DESC 'MANDATORY: OpenSSH LPK objectclass'
500+ MAY ( sshPublicKey $ uid )
501+ )
502
503=== removed file 'nova/auth/openssh-lpk_openldap.schema'
504--- nova/auth/openssh-lpk_openldap.schema 2010-10-25 22:42:49 +0000
505+++ nova/auth/openssh-lpk_openldap.schema 1970-01-01 00:00:00 +0000
506@@ -1,19 +0,0 @@
507-#
508-# LDAP Public Key Patch schema for use with openssh-ldappubkey
509-# Author: Eric AUGE <eau@phear.org>
510-#
511-# Based on the proposal of : Mark Ruijter
512-#
513-
514-
515-# octetString SYNTAX
516-attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
517- DESC 'MANDATORY: OpenSSH Public key'
518- EQUALITY octetStringMatch
519- SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
520-
521-# printableString SYNTAX yes|no
522-objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
523- DESC 'MANDATORY: OpenSSH LPK objectclass'
524- MAY ( sshPublicKey $ uid )
525- )
526
527=== added file 'nova/auth/openssh-lpk_sun.schema'
528--- nova/auth/openssh-lpk_sun.schema 1970-01-01 00:00:00 +0000
529+++ nova/auth/openssh-lpk_sun.schema 2010-12-22 23:56:00 +0000
530@@ -0,0 +1,10 @@
531+#
532+# LDAP Public Key Patch schema for use with openssh-ldappubkey
533+# Author: Eric AUGE <eau@phear.org>
534+#
535+# Schema for Sun Directory Server.
536+# Based on the original schema, modified by Stefan Fischer.
537+#
538+dn: cn=schema
539+attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
540+objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) )
541
542=== removed file 'nova/auth/openssh-lpk_sun.schema'
543--- nova/auth/openssh-lpk_sun.schema 2010-10-25 22:50:32 +0000
544+++ nova/auth/openssh-lpk_sun.schema 1970-01-01 00:00:00 +0000
545@@ -1,10 +0,0 @@
546-#
547-# LDAP Public Key Patch schema for use with openssh-ldappubkey
548-# Author: Eric AUGE <eau@phear.org>
549-#
550-# Schema for Sun Directory Server.
551-# Based on the original schema, modified by Stefan Fischer.
552-#
553-dn: cn=schema
554-attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' DESC 'MANDATORY: OpenSSH Public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
555-objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY DESC 'MANDATORY: OpenSSH LPK objectclass' MAY ( sshPublicKey $ uid ) )
556
557=== modified file 'nova/auth/slap.sh'
558--- nova/auth/slap.sh 2010-10-25 22:42:49 +0000
559+++ nova/auth/slap.sh 2010-12-22 23:56:00 +0000
560@@ -22,7 +22,7 @@
561
562 abspath=`dirname "$(cd "${0%/*}" 2>/dev/null; echo "$PWD"/"${0##*/}")"`
563 cp $abspath/openssh-lpk_openldap.schema /etc/ldap/schema/openssh-lpk_openldap.schema
564-cp $abspath/nova_openldap.schema /etc/ldap/schema/nova_openldap.schema
565+cp $abspath/nova_openldap.schema /etc/ldap/schema/nova.schema
566
567 mv /etc/ldap/slapd.conf /etc/ldap/slapd.conf.orig
568 cat >/etc/ldap/slapd.conf <<SLAPD_CONF_EOF
569@@ -33,7 +33,6 @@
570 include /etc/ldap/schema/core.schema
571 include /etc/ldap/schema/cosine.schema
572 include /etc/ldap/schema/inetorgperson.schema
573-include /etc/ldap/schema/openssh-lpk_openldap.schema
574 include /etc/ldap/schema/nova.schema
575 pidfile /var/run/slapd/slapd.pid
576 argsfile /var/run/slapd/slapd.args