Skip to content

simple script to copy ldap groups and members to a svn authz file

License

Notifications You must be signed in to change notification settings

cattz/ldap-to-svn-authz

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

================================================================================
=========        LDAP Groups to Subversion Authz Groups Bridge        ==========
================================================================================
Author: Jeremy Whitlock <[email protected]>, Christophe Drevet <[email protected]>
License: GPLv3
Version: 1.1.0
Website: http://www.thoughtspark.org/
Support: Feel free to reach out to me for bugs, suggestions, etc.
================================================================================

Change Log
--------------------------------------------------------------------------------
2010-05-28 (version 1.1.0):
- fix 'invalid cross-device link' error
- handle TypeError when group not in search scope
- print a warning when a sub group is not in search scope
- add an option to follow sub groups to include all user members recursively (avoids previous warnings)
- print group processing progress in verbose mode (like : +..++.-.--)
2009-01-22 - There was a bug when you didn't specify the -z flag and when the query returned no groups. Version 1.0.1 has been produced as a result.
2009-04-15 - There was a bug with nested groups.  Version 1.0.2 has been produced as a result.

Background
--------------------------------------------------------------------------------
When building a Subversion server, people usually go for the setup that requires
the least amount of administrative overhead.  For many, especially in the
enterprise where Active Directory and OpenLDAP rule, this means hooking up
Apache to a directory server to authenticate users via LDAP.  The reason for
such a setup is that you can use the same credentials that log you into your
computer, and other internal resources usually, to access Subversion.  One less
set of credentials for the user to remember and one less user data store for the
administrator to maintain.  Initially, this scenario is without any real
disadvantage.  But once you want to start using your groups defined in your
directory with Subversion's authorization (authz) mechanism, you find one of the
shortcomings of such a configuration.

The Problem
--------------------------------------------------------------------------------
Subversion's authz architecture requires your group definitions to be defined
within the authz file.  Subversion's authz architecture is also unaware of
third-party data stores for users/groups.  This means that if you do not define
your group within the authz file, Subversion will not know whether a user is a
member of said group and will ultimately tell you that you do not have access
to a resource.  That being said, the current problem is that with this server
configuration, either you cannot harness group models defined in your directory
server or you have to manually synchronize your group models from your
directory server to Subversion's authz file.  There are many downsides to doing
things this way:

  * It's time consuming
  * It's easy to forget that changes have been made and need to be mirrored
  * It's very easy to make mistakes when doing it yourself
  * ...

So while using LDAP for Subversion authentication is a dream, things are not
so nice when it comes to reusing your group models for authz that are defined
in your directory server.

The Solution
--------------------------------------------------------------------------------
Well, it just so happens that I have a solution.  One that is repeatable,
loss-less and can be easily setup using the same information you used to
configure Apache to authenticate your Subversion users.  The solution is the
"LDAP Groups to Subversion Authz Groups Bridge" script.

The "LDAP Groups to Subversion Authz Groups Bridge" script is written in Python
and, as mentioned before, does its work in a loss-less fashion.  This means that
while this script will take on the trouble of taking your groups models defined
in your directory server and reproducing them in a Subversion authz file, the
script will not prohibit you from creating group definitions within the authz
file that are not defined in your directory server.  Tired of all of the
background?  Ready to see the script in action?  Let's go.

The Implementation
--------------------------------------------------------------------------------
Implementing the "LDAP Groups to Subversion Authz Groups Bridge" is actually
simple.  If you've already configured Apache to authenticate your Subversion
users, which we will not be covering, you can honestly copy/paste pieces of the
Apache configuration into the script.  Before we go through an example though,
there are a few prerequisites that you need to have taken care of before the
script will run:

  * Install Python (http://www.python.org)
  * Install the python-ldap module (http://python-ldap.sourceforge.net)

Now that we have those things out of the way, let's look at the help output of
the script, just to get our bearings:

  Usage: sync_ldap_groups_to_svn_authz.py [options]

  Options:
    -h, --help            show this help message and exit
    -d BIND_DN, --bind-dn=BIND_DN
                          The DN of the user to bind to the directory with
    -p BIND_PASSWORD, --bind-password=BIND_PASSWORD
                          The password for the user specified with the --bind-dn
    -l URL, --url=URL     The url (scheme://hostname:port) for the directory
                          server
    -b BASE_DN, --base-dn=BASE_DN
                          The DN at which to perform the recursive search
    -g GROUP_QUERY, --group-query=GROUP_QUERY
                          The query/filter used to identify group objects.
                          [Default: objectClass=group]
    -m GROUP_MEMBER_ATTRIBUTE, --group-member-attribute=GROUP_MEMBER_ATTRIBUTE
                          The attribute of the group object that stores the
                          group memberships.  [Default: member]
    -u USER_QUERY, --user-query=USER_QUERY
                          The query/filter used to identify user objects.
                          [Default: objectClass=user]
    -i USERID_ATTRIBUTE, --userid_attribute=USERID_ATTRIBUTE
                          The attribute of the user object that stores the
                          userid to be used in the authz file.  [Default: cn]
    -z AUTHZ_PATH, --authz-path=AUTHZ_PATH
                          The path to the authz file to update/create
    -f, --follow-groups   Follow sub-groups
    -q, --quiet           Suppress logging information

Anything that has a "[Default:" string in its corresponding documentation is
"optional" and can usually be omitted when running against most directory
servers.  The things that are not optional are things that you can get from
your Apache configuration.  Now that we have our bearings, let's see an
example.

Let's pretend that I have a directory structure like this:

  * Release Managers (CN=Release Managers,OU=Groups,DC=subversion,DC=thoughtspark,DC=org)
       * Release Manager One (CN=Release Manager One,OU=Users,DC=subversion,DC=thoughtspark,DC=org)
  * Developers (CN=Developers,OU=Groups,DC=subversion,DC=thoughtspark,DC=org)
       * Release Managers (CN=Release Managers,OU=Nested Groups,OU=Groups,DC=subversion,DC=thoughtspark,DC=org)
       * Developer One (CN=Developer One,OU=Users,DC=subversion,DC=thoughtspark,DC=org)
       * Developer Two (CN=Developer Two,OU=Users,DC=subversion,DC=thoughtspark,DC=org)
       * Developer Three (CN=Developer Three,OU=Users,DC=subversion,DC=thoughtspark,DC=org)
  * Release Managers (CN=Release Managers,OU=Nested Groups,OU=Groups,DC=subversion,DC=thoughtspark,DC=org)
       * Release Manager Two (CN=Release Manager Two,OU=Users,DC=subversion,DC=thoughtspark,DC=org)
  * Administrators (CN=Administrators,CN=Roles,DC=subversion,DC=thoughtspark,DC=org)
       * Jeremy Whitlock (CN=Jeremy Whitlock,OU=Users,DC=subversion,DC=thoughtspark,DC=org)

(Yes...I have two groups with the same name but in different locations.
This will help showcase how the "LDAP Groups to Subversion Authz Groups
Bridge" handles this situation.)  I now want to run the script:

  python sync_ldap_groups_to_svn_authz.py \
    -d "CN=Jeremy Whitlock,OU=Users,DC=subversion,DC=thoughtspark,DC=org" \
    -l "ldap://localhost:389" \
    -b "DC=subversion,DC=thoughtspark,DC=org" > svn_auth.txt

You'll notice I didn't specify a password.  In this event, the script will
prompt you, securely, for a password.  After the script runs, as long as you
didn't run with the "-q" flag, you should see output like this:

  Successfully bound to ldap://localhost:389
  4 groups found.
  
Okay, things ran smoothly.  (If you notice any "[WARNING]" output, just look at
the message along side the warning to see why.)  So what does the file look like?

  [groups]
  
  ### Start generated content: LDAP Groups to Subversion Authz Groups Bridge (2009/01/19 23:17:07) ###
  ReleaseManagers = Release Manager One
  Developers = @ReleaseManagers1, Developer Three, Developer Two, Developer One
  ReleaseManagers1 = Release Manager Two
  Administrators = Jeremy Whitlock

  ################################################################################
  ###########   LDAP Groups to Subversion Authz Groups Bridge (Legend)  ##########
  ################################################################################
  ### ReleaseManagers = CN=Release Managers,OU=Groups,DC=subversion,DC=thoughtspark,DC=org
  ### Developers = CN=Developers,OU=Groups,DC=subversion,DC=thoughtspark,DC=org
  ### ReleaseManagers1 = CN=Release Managers,OU=Nested Groups,OU=Groups,DC=subversion,DC=thoughtspark,DC=org
  ### Administrators = CN=Administrators,CN=Roles,DC=subversion,DC=thoughtspark,DC=org
  ###############################################################################

  ### End generated content: LDAP Groups to Subversion Authz Groups Bridge ###

Here is a list of features, or things to realize, based on the output of this
script:

  * The "[groups]" section is created but only if necessary
  * All generated content is within known "markers" for loss-less regeneration
  * The header tells you when the file was last synchronized
  * Nested groups, of any level, are supported
  * Groups with the same name, but different locations, are supported
  * An easy-to-read legend is created for reference reasons

Now that we've seen a very simple example, let's see one more example of how we
might take an Apache configuration and turn that into a call to the
"LDAP Groups to Subversion Authz Groups Bridge".

Below we have a snippet of the important parts of an Apache configuration using
LDAP for Subversion authentication:

  ...
  # The distinguished name to bind to the directory server
  AuthLDAPBindDN "CN=Jeremy Whitlock,OU=Users,DC=subversion,DC=thoughtspark,DC=org"

  # The password for the user above
  AuthLDAPBindPassword "myP455w0rd"

  # The LDAP query url
  AuthLDAPURL "ldap://localhost:389/DC=subversion,DC=thoughtspark,DC=org?sAMAccountName?sub?(objectClass=user)"
  ...

With the above information, Apache could connect to my theoretical Active
Directory server and look for user objects.  The way Apache identifies user
objects is by the "objectClass" attribute being set to "user".  Once a user is
found, the "sAMAccountName" attribute is queried to see if it matches the user
logging in.  Once the user is found, it is authenticated.  That being said,
let's parse this information and turn it into a successful call to the
"LDAP Groups to Subversion Authz Groups Bridge":

  python sync_ldap_groups_to_svn_authz.py \
    -d "CN=Jeremy Whitlock,OU=Users,DC=subversion,DC=thoughtspark,DC=org" \
    -p "myP455w0rd" \
    -l "ldap://localhost:389" \
    -b "DC=subversion,DC=thoughtspark,DC=org" \
    -i "sAMAccountName" > svn_auth.txt

The new things you see in this call that differ from the first call is that we
are now looking for the "sAMAccountName" attribute for the username instead of
the "cn" attribute.  You also see that we can pass the password as a command
line argument.

Summary
--------------------------------------------------------------------------------
So now that we've seen how the script is ran, what is necessary to get it
running and even a complete example, it's now up to you to get this thing into
your Subversion infrastructure.  Immediate ideas are to automate this with your
operating system's task scheduler and/or create a web interface to kick this
script off on an as-needed basis.  Regardless of how you use it, the
"LDAP Groups to Subversion Authz Groups Bridge" should make the error-prone,
tedious and easy-to-forget process of manually synchronizing your LDAP group
models to Subversion's authz file much, much easier.  It might even get so easy
you forget that Subversion doesn't natively support LDAP groups.

About

simple script to copy ldap groups and members to a svn authz file

Resources

License

Stars

Watchers

Forks

Packages

No packages published