diff --git a/conf/example.gitolite.rc b/conf/example.gitolite.rc
index e189595..c563e81 100644
--- a/conf/example.gitolite.rc
+++ b/conf/example.gitolite.rc
@@ -273,6 +273,18 @@ $GL_WILDREPOS = 0;
# $GL_SITE_INFO = "";
# $GL_SITE_INFO = "XYZ.COM DEVELOPERS: PLEASE SEE http://xyz.com/gitolite/help first";
+# --------------------------------------
+# USERGROUP HANDLING
+
+# Some sites would like to store group membership outside gitolite, because
+# they already have it in (usually) their LDAP server, and it doesn't make
+# sense to be forced to duplicate this information.
+
+# Set the following variable to the name of a script that, given a username as
+# argument, will return a list of groups that she is a member of.
+
+# $GL_GET_MEMBERSHIPS_PGM = "/usr/local/bin/expand-ldap-user-to-groups"
+
# --------------------------------------
# per perl rules, this should be the last line in such a file:
1;
diff --git a/doc/big-config.mkd b/doc/big-config.mkd
index b2f35b0..c4ea551 100644
--- a/doc/big-config.mkd
+++ b/doc/big-config.mkd
@@ -6,7 +6,9 @@ In this document:
* how do we use it?
* other optimisations
* what are the downsides?
- * (extra coolness) usergroups and LDAP/similar tools
+ * storing usergroup information outside gitolite (like in LDAP)
+ * why
+ * how
@@ -190,51 +192,58 @@ subset of the allowed @fragname, which would work normally, do not work now).
(If you didn't understand all that, you're probably not using delegation, so
feel free to ignore it!)
-
+
-### (extra coolness) usergroups and LDAP/similar tools
+### storing usergroup information outside gitolite (like in LDAP)
[Please NOTE: this is all about *user* groups, not *repo* groups]
-Gitolite now allows usergroup information to be passed in from outside. The
-`gl-auth-commmand` can now take an optional list of usergroup names after the
-first argument (which is the username).
+[WARNING: the earlier method of doing this has been discontinued; please see
+the commit message for details]
-To understand why this is useful, consider the following:
+Gitolite now allows usergroup information to be stored outside its own config
+file. We'll see "why" first, then the "how".
-Some people have an LDAP-backed ssh daemon (or some other similar mechanism
-that can speak "ssh" to the client), with pubkeys stored in LDAP, etc., and
-some way (not using `~/.ssh/authorized_keys`) of invoking gitolite.
+
-Such setups also have "usergroups", and a way to tell, for each user, what
-groups he/she is a member of. So let's say "alice" works on projects "foo"
-and "bar", while "bob" works on project "bar" and is a member of the
-`L3_support` team.
+#### why
-You can use those group names in the gitolite config file for access control
-as "@foo", "@bar", `@L3_support`, etc.; please note the "@" prefix because
-gitolite requires it.
+Large sites often have LDAP servers that already contain user and group
+information, including group membership details. Such sites may prefer that
+gitolite just pick up that info instead of having to redundantly put it in
+gitolite's config file.
-However, that still leaves a wee little inconvenience. You still have to add
-lines like this to the gitolite config file:
+Consider this example config for one repo:
- @foo = alice
- @bar = alice bob
- @L3_support = bob
+ repo foo
+ RW+ = @lead_devs
+ RW = @devs
+ R = @interns
-You don't need to do that anymore now. Tell your authentication system that,
-after authenticating alice, instead of running:
+Normally, you would also need to specify:
- /some/path/to/gl-auth-command alice
+ @lead_devs = dilbert alice
+ @devs = wally
+ @interns = ashok
-it should first find the groups that alice is a member of, and then run:
+However, if the corporate LDAP server already tags these people correctly, and
+if there is some way of getting that information out **at run time**, that
+would be cool.
- /some/path/to/gl-auth-command alice foo bar
+
-That's it. Internally, gitolite will behave as if the config file had also
-specified:
+#### how
- @foo = alice
- @bar = alice
+All you need is a script that, given a username, queries your LDAP or similar
+server, and returns a space-separated list of all the groups she is a member
+of. If an invalid user name is sent in, or the user is valid but is not part
+of any groups, it should print nothing.
+
+This script will probably be specific to your site. [**Help wanted**: I don't
+know LDAP, so if someone wants to contribute some sample code I'd be happy to
+put it in contrib/, with credit of course!]
+
+Then set the `$GL_GET_MEMBERSHIPS_PGM` variable in the rc file to the full
+path to this program, set `$GL_BIG_CONFIG` to 1, and that will be that.
[gwd]: http://github.com/sitaramc/gitolite/blob/pu/doc/3-faq-tips-etc.mkd#gwd
diff --git a/src/gitolite.pm b/src/gitolite.pm
index 80210d5..d689f88 100644
--- a/src/gitolite.pm
+++ b/src/gitolite.pm
@@ -40,7 +40,7 @@ our $REPOPATT_PATT=qr(^\@?[0-9a-zA-Z[][\\^.$|()[\]*+?{}0-9a-zA-Z._\@/-]*$);
our $ADC_CMD_ARGS_PATT=qr(^[0-9a-zA-Z._\@/+-]*$);
# these come from the RC file
-our ($REPO_UMASK, $GL_WILDREPOS, $GL_PACKAGE_CONF, $GL_PACKAGE_HOOKS, $REPO_BASE, $GL_CONF_COMPILED, $GL_BIG_CONFIG, $GL_PERFLOGT, $PROJECTS_LIST, $GL_ALL_INCLUDES_SPECIAL, $GL_SITE_INFO);
+our ($REPO_UMASK, $GL_WILDREPOS, $GL_PACKAGE_CONF, $GL_PACKAGE_HOOKS, $REPO_BASE, $GL_CONF_COMPILED, $GL_BIG_CONFIG, $GL_PERFLOGT, $PROJECTS_LIST, $GL_ALL_INCLUDES_SPECIAL, $GL_SITE_INFO, $GL_GET_MEMBERSHIPS_PGM);
our %repos;
our %groups;
our %repo_config;
@@ -932,6 +932,7 @@ sub special_cmd
# - (only for repos) as an indirect wildcard (@g = foo/.*; repo @g).
# note: the wildcard stuff does not apply to username memberships
+our %extgroups_cache;
sub get_memberships {
my $base = shift; # reponame or username
my $is_repo = shift; # some true value means a repo name has been passed
@@ -969,10 +970,17 @@ sub get_memberships {
# deal with returning user info first
unless ($is_repo) {
- # add in group membership info sent in via second and subsequent
- # arguments to gl-auth-command; be sure to prefix the "@" sign to each
- # of them!
- push @ret, map { s/^/@/; $_; } split(' ', $ENV{GL_GROUP_LIST}) if $ENV{GL_GROUP_LIST};
+ # bring in group membership info stored externally, by running
+ # $GL_GET_MEMBERSHIPS_PGM if it is defined
+
+ if ($extgroups_cache{$base}) {
+ push @ret, @{ $extgroups_cache{$base} };
+ } elsif ($GL_GET_MEMBERSHIPS_PGM) {
+ my @extgroups = map { s/^/@/; $_; } split ' ', `$GL_GET_MEMBERSHIPS_PGM $base`;
+ $extgroups_cache{$base} = \@extgroups;
+ push @ret, @extgroups;
+ }
+
return (@ret);
}
diff --git a/src/gl-auth-command b/src/gl-auth-command
index 2a6ab02..dabfa71 100755
--- a/src/gl-auth-command
+++ b/src/gl-auth-command
@@ -114,10 +114,6 @@ if ($ENV{REQUEST_URI}) {
$user=$ENV{GL_USER}=shift;
}
-# if there are any more arguments, they're a list of group names that the user
-# is a member of
-$ENV{GL_GROUP_LIST} = join(" ", @ARGV) if @ARGV;
-
# ----------------------------------------------------------------------------
# logging, timestamp env vars
# ----------------------------------------------------------------------------