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 # ----------------------------------------------------------------------------