I have a semi-private SVN repository served up over Apache at my job where I keep all my work. It’s semi-private in that I want my group at to have read and write access. Employees to have read access in case they find anything interesting. And finally non-Employee domain accounts should have no access. Down the road I may want some more flexibility in this setup. Possibly restricting all access to parts of it to just Domain Admins while giving write access to certain other people or groups in the company to certain projects. Rather than creating separate repos with their own separate Apache configs I decided on path based authorization.
There is a downside to this approach and it is how to use our AD groups to control access. By creating separate repos I could use mod_authnz_ldap to authorize access based on our AD groups. I’ve found mention of patches to mod_authz_svn to add LDAP functionality but no patches to try out. With path based authorization I needed a way to keep the groups in the authz file in sync with our AD groups. I ended up settling on a script I found here and run it as a cron job.
Using LDAP Groups With Subversion’s Authz File
[root@corptech ~]# ./sync_ldap_groups_to_svn_authz.py -d cn=nss_ldap,ou=services,dc=example,dc=com \ -p <password> -l ldap://example.com -b ou=groups,dc=example,dc=com -i sAMAccountName \ -z /srv/svn/authz.conf
The script works well but has a few issues. I’ve merged some of the patches in the comments section of that post to his script. These include the fix for the “Invalid cross-device link” error and the patch to handle paged searches. I left out some others since they weren’t useful to me and the time to merge unformated patches (the comments section strips white spaces) wasn’t worth it. I’ve also added support for handling ranged attributes. A Windows 2k3 DC will only return 1500 values of a multi-valued attribute at a single time. This is not to be confused with the page size limit which in Windows 2k was 1000 values and the same as the default page size limit. This is a hard limit and cannot be changed.
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ldap, pprint
>>> l = ldap.initialize('ldap://example.com')
>>> l.simple_bind_s('[email protected]', '*********')
(97, [])
>>> r = l.search_s('ou=groups,dc=example,dc=com', ldap.SCOPE_SUBTREE, 'cn=Employee')
>>> pprint.pprint(r)
[('CN=Employee,OU=Groups,DC=example,DC=com',
{'cn': ['Employee'],
'dSCorePropagationData': ['20100412182218.0Z',
'20100412181952.0Z',
'20091218151750.0Z',
'20091216205638.0Z',
'16010714223649.0Z'],
'description': ['Example Company's Employees'],
'distinguishedName': ['CN=Employee,OU=Groups,DC=example,DC=com'],
'groupType': ['-2147483646'],
'instanceType': ['4'],
'member': [],
'member;range=0-1499': ['CN=TMCLAUGHLIN,CN=Users,DC=example,DC=com',
....
We have over 3000 members of our Employee group so this became a problem. The patch linked at the end of this post includes the two previously mentioned patches along with the ability to handle large groups. One thing the patch does not handle is the way AD handles primary group membership. A user is not listed in the member attribute of their primary group and the group is not listed in the memberOf attribute of the user.
>>> r = l.search_s('cn=users,dc=example,dc=com', ldap.SCOPE_SUBTREE, 'cn=tmclaughlin', ['memberOf', 'primaryGroupID'])
>>> pprint.pprint(r)
[('CN=TMCLAUGHLIN,CN=Users,DC=example,DC=com',
{'memberOf': ['CN=Employee,OU=Groups,DC=example,DC=com',
'CN=Radius Admins,OU=Groups,DC=example,DC=com',
'CN=Domain Server Admin,OU=Groups,DC=example,DC=com',
'CN=Schema Admins,OU=Groups,DC=example,DC=com',
'CN=Domain Admins,OU=Groups,DC=example,DC=com',
'CN=Enterprise Admins,OU=Groups,DC=example,DC=com'],
'primaryGroupID': ['513']})]
The primaryGroupID attribute refers to the last part of the primary group’s SID. In this case it’s Domain Users. Unfortunately I’m not sure how to properly convert the objectSid attribute of a group from its binary form to a string in order to attempt a match. For now I have no way to handle syncing primary groups. I’m open to suggestions though.
Trackback Link…
[...]Here are some of the sites we recommend for our visitors[...]…
Trackback by Guaranteed Facebook Fans — December 20, 2011 @ 12:04 am