custom perm categories in setperms (WARNING: PLEASE READ FULL COMMIT MESSAGE)
THE COMPILED CONFIG FILE FORMAT CHANGES WITH THIS VERSION. PLEASE DO NOT MIX VERSIONS OR DOWNGRADE. Upgrading using normal gitolite upgrade means should be fine, though. Originally, we only allowed "R" and "RW" as categories of users supplied to the `setperms` command. These map respectively to "READERS" and "WRITERS" in the access rules. Now: - we prefer READERS instead of R and WRITERS instead of RW - we allow the admin to define other categories as she wishes (example: MANAGERS, TESTERS, etc). These do not have abbreviations, however, so they must be supplied in full. PLEASE, *PLEASE*, read the section in doc/wildcard-repositories.mkd for more info. This is a VERY powerful feature and if you're not careful you could mess up the ACLs nicely. Backward compat note: you can continue to use the "R" and "RW" categories when running the "setperms" command, and gitolite will internally convert them to READERS and WRITERS categories. ---- implementation notes: - new RC var called GL_WILDREPOS_PERM_CATS that is a space-sep list of the allowed categories in a gl-perms file; defaults to "R RW" if not specified - wild_repo_rights no longer returns $c, $r, $wC, where $r = $user if "R $user", $r = '@all' if "R @all", and similarly with $w and "RW". Instead it returns $c and a new hash that effectively gives the same info, but expanded to include any other valid categories (listed in GL_WILDREPOS_PERM_CATS) - consequently, the arguments that parse_acl takes also change the same way - (side note: R and RW are quietly converted to READERS and WRITERS; however, new categories that you define yourself do not have abbreviations) - setperms validates perms to make sure only allowed categories are used; however even if someone changed them behind the scenes, wild_repo_rights will also check. This is necessary in case the admin tightened up GL_WILDREPOS_PERM_CATS after someone had already setperms-d his repos. - as a bonus, we eliminate all the post-Dumper shenanigans, at least for READERS and WRITERS. Those two now look, to the compile script, just like any other usernames.
This commit is contained in:
parent
4df32c3ff0
commit
047790140a
|
@ -239,6 +239,28 @@ $GL_WILDREPOS = 0;
|
|||
|
||||
# $GL_WILDREPOS_DEFPERMS = 'R @all';
|
||||
|
||||
# --------------------------------------
|
||||
# WILDREPOS PERMS CATEGORIES
|
||||
|
||||
# Originally, we only allowed "R" and "RW" in the setperms command. Now we
|
||||
# allow the admin to define other categories as she wishes (example: MANAGERS,
|
||||
# TESTERS, etc).
|
||||
|
||||
# This variable is a space-sep list of the allowed categories.
|
||||
|
||||
# PLEASE, *PLEASE*, read the section in doc/wildcard-repositories.mkd for
|
||||
# caveats and warnings. This is a VERY powerful feature and if you're not
|
||||
# careful you could mess up the ACLs nicely.
|
||||
|
||||
# this is the internal default if you don't set it (like if you didn't update
|
||||
# your ~/.gitolite.rc with new variables when you upgraded gitolite):
|
||||
$GL_WILDREPOS_PERM_CATS = "READERS WRITERS";
|
||||
|
||||
# you can use your own categories in addition to the standard ones; I suggest
|
||||
# you include READERS and WRITERS for backward compat though:
|
||||
# $GL_WILDREPOS_PERM_CATS = "READERS WRITERS MANAGERS";
|
||||
# $GL_WILDREPOS_PERM_CATS = "READERS WRITERS MANAGERS TESTERS";
|
||||
|
||||
# --------------------------------------
|
||||
# HOOK CHAINING
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
This feature may be somewhat "brittle" in terms of security. Creating
|
||||
repositories based on wild cards, giving "ownership" to the specific user who
|
||||
created it, allowing him/her to hand out R and RW permissions to other users
|
||||
to collaborate, all these are possible. And any of these could have a bug in
|
||||
it. I haven't found any yet, but that doesn't mean there aren't any.
|
||||
created it, allowing him/her to hand out permissions to other users to
|
||||
collaborate, all these are possible. And any of these could have a bug in it.
|
||||
I haven't found any yet, but that doesn't mean there aren't any.
|
||||
|
||||
----
|
||||
|
||||
|
@ -17,9 +17,12 @@ In this document:
|
|||
* <a href="#_examples_of_wildcard_repos">examples of wildcard repos</a>
|
||||
* <a href="#_wildcard_repos_with_creator_name_in_them">wildcard repos with creator name in them</a>
|
||||
* <a href="#_wildcard_repos_without_creator_name_in_them">wildcard repos without creator name in them</a>
|
||||
* <a href="#_side_note_valid_regexes">side-note: valid regexes</a>
|
||||
* <a href="#_side_note_line_anchored_regexes">side-note: line-anchored regexes</a>
|
||||
* <a href="#_contrast_with_refexes">contrast with refexes</a>
|
||||
* <a href="#_handing_out_rights_to_wildcard_matched_repos">handing out rights to wildcard-matched repos</a>
|
||||
* <a href="#_admin_adding_other_categories_than_READERS_and_WRITERS">(admin) adding other categories than READERS and WRITERS</a>
|
||||
* <a href="#_IMPORTANT_WARNING_ABOUT_THIS_FEATURE_">**IMPORTANT WARNING ABOUT THIS FEATURE**</a>
|
||||
* <a href="#_setting_a_gitweb_description_for_a_wildcard_matched_repo">setting a gitweb description for a wildcard-matched repo</a>
|
||||
* <a href="#_reporting">reporting</a>
|
||||
* <a href="#_how_it_actually_works">how it actually works</a>
|
||||
|
@ -120,7 +123,7 @@ and have a TA create the repos in advance.
|
|||
In either case, they could then use the `setperms` feature to specify which
|
||||
users are "READERS" and which are "WRITERS". See later for details.
|
||||
|
||||
<a name="_side_note_line_anchored_regexes"></a>
|
||||
<a name="_side_note_valid_regexes"></a>
|
||||
|
||||
### side-note: valid regexes
|
||||
|
||||
|
@ -131,6 +134,8 @@ look like a regex to gitolite. Use `foo/..*` if you want that.
|
|||
Also, `..*` by itself is not considered a valid repo pattern. Try
|
||||
`[a-zA-Z0-9].*`.
|
||||
|
||||
<a name="_side_note_line_anchored_regexes"></a>
|
||||
|
||||
### side-note: line-anchored regexes
|
||||
|
||||
A regex like
|
||||
|
@ -170,40 +175,80 @@ The use case is that, although our toy example has only 3 students, in reality
|
|||
there will be a few dozen, but each assignment will be worked on only by a
|
||||
handful from among those. This allows the creator to take ad hoc sets of
|
||||
users from among the actual users in the system, and place them into one of
|
||||
two categories (whose permissions are, in this example, R and RW
|
||||
respectively). In theory you could do the same thing by creating lots of
|
||||
little "assignment-NN" groups in the config file but that may be a little too
|
||||
cumbersome for non-secret environments.
|
||||
two categories (in this example, READERS and WRITERS respectively). In theory
|
||||
you could do the same thing by creating lots of little "assignment-NN" groups
|
||||
in the config file but that may be a little too cumbersome for non-secret
|
||||
environments.
|
||||
|
||||
Create a small text file that contains the permissions you desire:
|
||||
|
||||
$ cat > myperms
|
||||
R u5
|
||||
RW u6
|
||||
READERS u5
|
||||
WRITERS u6
|
||||
(hit ctrl-d here)
|
||||
|
||||
...and use the new "setperms" command to set permissions for your repo:
|
||||
|
||||
$ ssh git@server setperms assignments/u4/a12 < myperms
|
||||
New perms are:
|
||||
R u5
|
||||
RW u6
|
||||
READERS u5
|
||||
WRITERS u6
|
||||
|
||||
'setperms' will helpfully print what the new permissions are but you can also
|
||||
use 'getperms' to check:
|
||||
|
||||
$ ssh git@server getperms assignments/u4/a12
|
||||
R u5
|
||||
RW u6
|
||||
READERS u5
|
||||
WRITERS u6
|
||||
|
||||
The following points are important:
|
||||
|
||||
* note the syntax of the commands; it's not a "git" command, and there's no
|
||||
`:` like in a repo URL. The first space-separated word is R or RW, and
|
||||
the rest are simple usernames.
|
||||
`:` like in a repo URL. The first space-separated word is READERS or
|
||||
WRITERS, and the rest are simple usernames.
|
||||
|
||||
* whoever you specify as "R" will match the special user READERS. "RW" will
|
||||
match WRITERS.
|
||||
<a name="_admin_adding_other_categories_than_READERS_and_WRITERS"></a>
|
||||
|
||||
### (admin) adding other categories than READERS and WRITERS
|
||||
|
||||
Let's say your needs are more complex and you need more categories of users.
|
||||
For example, you might like to have a setup where only a tester can update
|
||||
tags, and only a manager can delete branches:
|
||||
|
||||
repo foo/..*
|
||||
C = u1
|
||||
RW refs/tags/ = TESTERS
|
||||
- refs/tags/ = @all
|
||||
RW+ = WRITERS
|
||||
RW = INTERNS
|
||||
R = READERS
|
||||
RW+D = MANAGERS
|
||||
|
||||
As you can see, someone pre-creates the repo and assigns rights to various
|
||||
people, say by sending something like this to `setperms`:
|
||||
|
||||
READERS wally
|
||||
WRITERS dilbert alice
|
||||
MANAGERS phb
|
||||
INTERNS ashok
|
||||
TESTERS ashok
|
||||
|
||||
You can enable do this by setting the `GL_WILDREPOS_PERM_CATS` variable in the
|
||||
rc file. The example rc file (`conf/example.gitolite.rc`) explains how to do
|
||||
this, with sample code.
|
||||
|
||||
<a name="_IMPORTANT_WARNING_ABOUT_THIS_FEATURE_"></a>
|
||||
|
||||
#### **IMPORTANT WARNING ABOUT THIS FEATURE**
|
||||
|
||||
Please make sure that none of the category names conflict with any of the
|
||||
**usernames** in the system. For example, if you have a user called "foo",
|
||||
make sure you do not include "foo" as a valid category in
|
||||
`$GL_WILDREPOS_PERM_CATS`.
|
||||
|
||||
You can keep things sane by using UPPERCASE names for categories, while
|
||||
keeping all your usernames lowercase; then you don't have to worry about this
|
||||
problem.
|
||||
|
||||
<a name="_setting_a_gitweb_description_for_a_wildcard_matched_repo"></a>
|
||||
|
||||
|
@ -253,12 +298,9 @@ Now find a repo pattern that matches the actual reponame being pushed -- this
|
|||
tells you which set of rules to apply. There can be multiple matches; if so,
|
||||
they will all be applied in the sequence they appear in the config file.
|
||||
|
||||
If the invoking user has been given "RW" permissions using `setperms`, all
|
||||
occurrences of the word WRITERS are replaced by the invoking username.
|
||||
Otherwise -- and this includes the "new repo" case, since you couldn't have
|
||||
run `setperms` on a non-existant repo -- they are replaced by "NOBODY".
|
||||
|
||||
(The same thing is done with "R" access and the word "READERS".)
|
||||
If the invoking user has been put in the "WRITERS" category using `setperms`, all
|
||||
permissions for the the user WRITERS are given to the invoking username (and
|
||||
similarly for READERS).
|
||||
|
||||
At this point we have an effective ruleset, and the normal access rules (R,
|
||||
RW, etc) apply, with the addition that the invoking user needs "C" access to
|
||||
|
@ -269,8 +311,7 @@ be able to create a repo.
|
|||
> situations, as you can see in our example).
|
||||
|
||||
Assuming user "u4" trying to push-create a new repo called
|
||||
`assignments/u4/a23`, this is what the effective ruleset looks like (we're
|
||||
ignoring the "NOBODY" business):
|
||||
`assignments/u4/a23`, this is what the effective ruleset looks like:
|
||||
|
||||
repo assignments/u4/a23
|
||||
C = @students
|
||||
|
@ -278,8 +319,8 @@ ignoring the "NOBODY" business):
|
|||
RW = @TAs
|
||||
R = @prof
|
||||
|
||||
If u4 gives "RW" perms to u5 using `setperms`, and u5 tries to access that
|
||||
repo, the ruleset looks like:
|
||||
If u4 puts u5 in the "WRITERS" category using `setperms`, and u5 tries to
|
||||
access that repo, the ruleset looks like:
|
||||
|
||||
repo assignments/u4/a23
|
||||
C = @students
|
||||
|
|
|
@ -40,12 +40,12 @@ 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, $GL_GET_MEMBERSHIPS_PGM);
|
||||
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, $GL_WILDREPOS_PERM_CATS);
|
||||
our %repos;
|
||||
our %groups;
|
||||
our %repo_config;
|
||||
our $data_version;
|
||||
our $current_data_version = '1.5';
|
||||
our $current_data_version = '1.6';
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# convenience subs
|
||||
|
@ -316,6 +316,8 @@ sub new_repo
|
|||
# "who created this repo", "am I on the R list", and "am I on the RW list"?
|
||||
sub wild_repo_rights
|
||||
{
|
||||
# set default categories
|
||||
$GL_WILDREPOS_PERM_CATS ||= "READERS WRITERS";
|
||||
my ($repo, $user) = @_;
|
||||
# pull in basic group info
|
||||
unless ($cache_filled) {
|
||||
|
@ -337,26 +339,46 @@ sub new_repo
|
|||
my $fh = wrap_open("<", "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-creater");
|
||||
chomp($c = <$fh>);
|
||||
}
|
||||
# $user's R and W rights
|
||||
my ($r, $w); $r = ''; $w = '';
|
||||
|
||||
# now get the permission categories (used to be just R and RW. Now
|
||||
# there can be any others that the admin defines in the RC file via
|
||||
# $GL_WILDREPOS_PERM_CATS variable (space separated list)
|
||||
|
||||
# For instance, if the user is "foo", and gl-perms has "R bar", "RW
|
||||
# foo baz", and "TESTERS frob @all", this hash will then contain
|
||||
# "WRITERS=>foo" and "TESTERS=>@all"
|
||||
my %perm_cats;
|
||||
|
||||
if ($user and -f "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-perms") {
|
||||
my $fh = wrap_open("<", "$ENV{GL_REPO_BASE_ABS}/$repo.git/gl-perms");
|
||||
my $perms = join ("", <$fh>);
|
||||
# $perms is say "R alice @foo @bar\nRW bob @baz" (the entire gl-perms
|
||||
# discard comments
|
||||
$perms =~ s/#.*//g;
|
||||
# convert R and RW to the actual category names in the config file
|
||||
$perms =~ s/^\s*R /READERS /mg;
|
||||
$perms =~ s/^\s*RW /WRITERS /mg;
|
||||
# $perms is say "READERS alice @foo @bar\nRW bob @baz" (the entire gl-perms
|
||||
# file). We replace each @foo with $user if $cached_groups{'@foo'}{$user}
|
||||
# exists (i.e., $user is a member of @foo)
|
||||
for my $g ($perms =~ /\s(\@\S+)/g) {
|
||||
$perms =~ s/ $g(?!\S)/ $user/ if $cached_groups{$g}{$user};
|
||||
}
|
||||
# now setup the perm_cats hash to be returned
|
||||
if ($perms) {
|
||||
$r ='@all' if $perms =~ /^\s*R(?=\s).*\s\@all(\s|$)/m;
|
||||
$r = $user if $perms =~ /^\s*R(?=\s).*\s$user(\s|$)/m;
|
||||
$w ='@all' if $perms =~ /^\s*RW(?=\s).*\s\@all(\s|$)/m;
|
||||
$w = $user if $perms =~ /^\s*RW(?=\s).*\s$user(\s|$)/m;
|
||||
# let's say our user is "foo". gl-perms has "CAT bar @all",
|
||||
# you add CAT => @all to the hash. similarly, if gl-perms has
|
||||
# "DOG bar foo baz", you add DOG => foo to the hash. And
|
||||
# since specific perms must override @all, we do @all first.
|
||||
$perm_cats{$1} = '@all' while ($perms =~ /^\h*(\S+)(?=\h).*\h\@all(\h|$)/mg);
|
||||
$perm_cats{$1} = $user while ($perms =~ /^\h*(\S+)(?=\h).*\h$user(\h|$)/mg);
|
||||
# validate the categories being sent back
|
||||
for (sort keys %perm_cats) {
|
||||
die "invalid permission category $_\n" unless $GL_WILDREPOS_PERM_CATS =~ /(^|\s)$_(\s|$)/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ($c, $r, $w);
|
||||
return ($c, %perm_cats);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,16 +389,30 @@ sub new_repo
|
|||
sub get_set_perms
|
||||
{
|
||||
my($repo, $verb, $user) = @_;
|
||||
# set default categories
|
||||
$GL_WILDREPOS_PERM_CATS ||= "READERS WRITERS";
|
||||
my ($creator, $dummy, $dummy2) = &wild_repo_rights($repo, "");
|
||||
die "$repo doesnt exist or is not yours\n" unless $user eq $creator;
|
||||
wrap_chdir("$ENV{GL_REPO_BASE_ABS}");
|
||||
wrap_chdir("$repo.git");
|
||||
if ($verb eq 'getperms') {
|
||||
system("cat", "gl-perms") if -f "gl-perms";
|
||||
return unless -f "gl-perms";
|
||||
my $perms = `cat gl-perms`;
|
||||
# convert R and RW to the actual category names in the config file
|
||||
$perms =~ s/^\s*R /READERS /mg;
|
||||
$perms =~ s/^\s*RW /WRITERS /mg;
|
||||
print $perms;
|
||||
} else {
|
||||
system("cat > gl-perms");
|
||||
my $perms = `cat gl-perms`;
|
||||
# convert R and RW to the actual category names in the config file
|
||||
$perms =~ s/^\s*R /READERS /mg;
|
||||
$perms =~ s/^\s*RW /WRITERS /mg;
|
||||
for my $g ($perms =~ /^\s*(\S+)/g) {
|
||||
die "invalid permission category $g\n" unless $GL_WILDREPOS_PERM_CATS =~ /(^|\s)$g(\s|$)/;
|
||||
}
|
||||
print "New perms are:\n";
|
||||
system("cat", "gl-perms");
|
||||
print $perms;
|
||||
|
||||
# gitweb and daemon
|
||||
setup_daemon_access($repo);
|
||||
|
@ -492,8 +528,10 @@ sub parse_acl
|
|||
# IMPLEMENTATION NOTE: a wee bit of this is duplicated in the update hook;
|
||||
# please update that also if the interface or the env vars change
|
||||
|
||||
my ($GL_CONF_COMPILED, $repo, $c, $r, $w) = @_;
|
||||
$c = $r = $w = "NOBODY" unless $GL_WILDREPOS;
|
||||
my ($GL_CONF_COMPILED, $repo, $c, %perm_cats) = @_;
|
||||
my $perm_cats_sig = '';
|
||||
map { $perm_cats_sig .= "$_.$perm_cats{$_}," } sort keys %perm_cats;
|
||||
$c = "NOBODY" unless $GL_WILDREPOS;
|
||||
|
||||
# set up the variables for a parse to interpolate stuff from the dumped
|
||||
# hash (remember the selective conversion of single to double quotes?).
|
||||
|
@ -504,19 +542,17 @@ sub parse_acl
|
|||
# parse without any special code
|
||||
|
||||
our $creator = $ENV{GL_CREATOR} = $c || $ENV{GL_CREATOR} || "NOBODY";
|
||||
our $readers = $ENV{GL_READERS} = $r || $ENV{GL_READERS} || "NOBODY";
|
||||
our $writers = $ENV{GL_WRITERS} = $w || $ENV{GL_WRITERS} || "NOBODY";
|
||||
our $gl_user = $ENV{GL_USER};
|
||||
|
||||
# these need to persist across calls to this function, so "our"
|
||||
our $saved_crwu;
|
||||
our (%saved_repos, %saved_groups);
|
||||
|
||||
if ($saved_crwu and $saved_crwu eq "$creator,$readers,$writers,$gl_user") {
|
||||
if ($saved_crwu and $saved_crwu eq "$creator,$perm_cats_sig,$gl_user") {
|
||||
%repos = %saved_repos; %groups = %saved_groups;
|
||||
} else {
|
||||
die "parse $GL_CONF_COMPILED failed: " . ($! or $@) unless do $GL_CONF_COMPILED;
|
||||
$saved_crwu = "$creator,$readers,$writers,$gl_user";
|
||||
$saved_crwu = "$creator,$perm_cats_sig,$gl_user";
|
||||
%saved_repos = %repos; %saved_groups = %groups;
|
||||
}
|
||||
unless (defined($data_version) and $data_version eq $current_data_version) {
|
||||
|
@ -547,8 +583,8 @@ sub parse_acl
|
|||
$repos{$dr}{NAME_LIMITS} = 1 if $repos{$r}{NAME_LIMITS};
|
||||
$repo_config{$dr} = $repo_config{$r} if $repo_config{$r};
|
||||
|
||||
for my $u ('@all', "$gl_user - wild", @user_plus) {
|
||||
my $du = $gl_user; $du = '@all' if $u eq '@all';
|
||||
for my $u ('@all', "$gl_user - wild", @user_plus, keys %perm_cats) {
|
||||
my $du = $gl_user; $du = '@all' if $u eq '@all' or ($perm_cats{$u} || '') eq '@all';
|
||||
$repos{$dr}{C}{$du} = 1 if $repos{$r}{C}{$u};
|
||||
$repos{$dr}{R}{$du} = 1 if $repos{$r}{R}{$u};
|
||||
$repos{$dr}{W}{$du} = 1 if $repos{$r}{W}{$u};
|
||||
|
@ -599,7 +635,7 @@ sub report_basic
|
|||
# rights for some other user this way
|
||||
local $ENV{GL_USER} = $user;
|
||||
|
||||
&parse_acl($GL_CONF_COMPILED, "", "CREATOR", "READERS", "WRITERS");
|
||||
&parse_acl($GL_CONF_COMPILED, "", "CREATOR");
|
||||
|
||||
# send back some useful info if no command was given
|
||||
&report_version($GL_ADMINDIR, $user);
|
||||
|
@ -610,10 +646,10 @@ sub report_basic
|
|||
# if $GL_BIG_CONFIG is on, limit the number of output lines to 20
|
||||
next if $GL_BIG_CONFIG and $count++ >= 20;
|
||||
if ($r =~ $REPONAME_PATT and $r !~ /\bCREAT[EO]R\b/) {
|
||||
&parse_acl($GL_CONF_COMPILED, $r, "NOBODY", "NOBODY", "NOBODY");
|
||||
&parse_acl($GL_CONF_COMPILED, $r, "NOBODY");
|
||||
} else {
|
||||
$r =~ s/\bCREAT[EO]R\b/$user/g;
|
||||
&parse_acl($GL_CONF_COMPILED, $r, $ENV{GL_USER}, "NOBODY", "NOBODY");
|
||||
&parse_acl($GL_CONF_COMPILED, $r, $ENV{GL_USER});
|
||||
}
|
||||
# @all repos; meaning of read/write flags:
|
||||
# @R => @all users are allowed access to this repo
|
||||
|
@ -692,13 +728,16 @@ sub expand_wild
|
|||
my $wild = '';
|
||||
my $exists = -d "$ENV{GL_REPO_BASE_ABS}/$repo.git";
|
||||
if ($exists) {
|
||||
# the list of permission categories within gl-perms that this user is a member
|
||||
# of, or that specify @all as a member. See comments in
|
||||
# "wild_repo_rights" sub for nuances.
|
||||
my (%perm_cats);
|
||||
# these will be empty if it's not a wildcard repo anyway
|
||||
my ($read, $write);
|
||||
($creator, $read, $write) = &wild_repo_rights($repo, $ENV{GL_USER});
|
||||
($creator, %perm_cats) = &wild_repo_rights($repo, $ENV{GL_USER});
|
||||
# get access list with these substitutions
|
||||
$wild = &parse_acl($GL_CONF_COMPILED, $repo, $creator || "NOBODY", $read || "NOBODY", $write || "NOBODY");
|
||||
$wild = &parse_acl($GL_CONF_COMPILED, $repo, $creator || "NOBODY", %perm_cats);
|
||||
} else {
|
||||
$wild = &parse_acl($GL_CONF_COMPILED, $repo, $ENV{GL_USER}, "NOBODY", "NOBODY");
|
||||
$wild = &parse_acl($GL_CONF_COMPILED, $repo, $ENV{GL_USER});
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
|
@ -840,7 +879,7 @@ sub setup_authkeys
|
|||
# lint check 3; a little more severe than the first two I guess...
|
||||
{
|
||||
my @no_pubkey =
|
||||
grep { $_ !~ /^(gitweb|daemon|\@.*|~\$creator|\$readers|\$writers)$/ }
|
||||
grep { $_ !~ /^(gitweb|daemon|\@.*|~\$creator)$/ }
|
||||
grep { $user_list_p->{$_} ne 'has pubkey' }
|
||||
keys %{$user_list_p};
|
||||
if (@no_pubkey > 10) {
|
||||
|
|
|
@ -217,8 +217,6 @@ sub parse_conf_line
|
|||
do { die "$ABRT bad username $_\n" unless $_ =~ $USERNAME_PATT } for @users;
|
||||
|
||||
s/\bCREAT[EO]R\b/~\$creator/g for @users;
|
||||
s/\bREADERS\b/\$readers/g for @users;
|
||||
s/\bWRITERS\b/\$writers/g for @users;
|
||||
|
||||
# ok, we can finally populate the %repos hash
|
||||
for my $repo (@{ $repos_p }) # each repo in the current stanza
|
||||
|
@ -266,7 +264,7 @@ sub parse_conf_line
|
|||
# that do *not* use NAME limits. Setting a flag that
|
||||
# can be checked right away will help us do that
|
||||
$repos{$repo}{NAME_LIMITS} = 1 if $ref =~ /^NAME\//;
|
||||
my $p_user = $user; $p_user =~ s/(creator|readers|writers)$/$1 - wild/;
|
||||
my $p_user = $user; $p_user =~ s/creator$/creator - wild/;
|
||||
push @{ $repos{$repo}{$p_user} }, [ $rule_seq++, $ref, $perms ]
|
||||
unless $rurp_seen{$repo}{$p_user}{$ref}{$perms}++;
|
||||
}
|
||||
|
@ -402,15 +400,14 @@ my $data_version = $current_data_version;
|
|||
print $compiled_fh Data::Dumper->Dump([$data_version], [qw(*data_version)]);
|
||||
my $dumped_data = Data::Dumper->Dump([\%repos], [qw(*repos)]);
|
||||
$dumped_data .= Data::Dumper->Dump([\%repo_config], [qw(*repo_config)]) if %repo_config;
|
||||
# the dump uses single quotes, but we convert any strings containing $creator,
|
||||
# $readers, $writers, to double quoted strings. A wee bit sneaky, but not too
|
||||
# much...
|
||||
$dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g;
|
||||
# the dump uses single quotes, but we convert any strings containing $creator
|
||||
# and $gl_user to double quoted strings. A bit sneaky, but not too much...
|
||||
$dumped_data =~ s/'(?=[^']*\$(?:creator|gl_user))~?(.*?)'/"$1"/g;
|
||||
print $compiled_fh $dumped_data;
|
||||
if (%groups) {
|
||||
$dumped_data = Data::Dumper->Dump([\%groups], [qw(*groups)]);
|
||||
$dumped_data =~ s/\bCREAT[EO]R\b/\$creator/g;
|
||||
$dumped_data =~ s/'(?=[^']*\$(?:creator|readers|writers|gl_user))~?(.*?)'/"$1"/g;
|
||||
$dumped_data =~ s/'(?=[^']*\$(?:creator|gl_user))~?(.*?)'/"$1"/g;
|
||||
print $compiled_fh $dumped_data;
|
||||
}
|
||||
close $compiled_fh or die "$ABRT close compiled-conf failed: $!\n";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$data_version = '1.5';
|
||||
$data_version = '1.6';
|
||||
%repos = (
|
||||
'aa' => {
|
||||
'R' => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$data_version = '1.5';
|
||||
$data_version = '1.6';
|
||||
%repos = (
|
||||
'aa' => {
|
||||
'R' => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$data_version = '1.5';
|
||||
$data_version = '1.6';
|
||||
%repos = (
|
||||
'@g1' => {
|
||||
'@g1' => [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$data_version = '1.5';
|
||||
$data_version = '1.6';
|
||||
%repos = (
|
||||
'aa' => {
|
||||
'R' => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$data_version = '1.5';
|
||||
$data_version = '1.6';
|
||||
%repos = (
|
||||
'aa' => {
|
||||
'R' => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$data_version = '1.5';
|
||||
$data_version = '1.6';
|
||||
%repos = (
|
||||
'aa' => {
|
||||
'@g1' => [
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
New perms are:
|
||||
|
||||
R u5
|
||||
RW u6
|
||||
READERS u5
|
||||
WRITERS u6
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
R u5
|
||||
RW u6
|
||||
READERS u5
|
||||
WRITERS u6
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ do
|
|||
expect "\[new branch\] master -> master"
|
||||
echo RW u2 | runlocal ssh u1 setperms foo/u1/bar
|
||||
runlocal ssh u1 getperms foo/u1/bar
|
||||
expect "RW u2"
|
||||
expect "WRITERS u2"
|
||||
name "expand"
|
||||
runlocal ssh u2 expand
|
||||
expect "R W .(u1).foo/u1/bar"
|
||||
|
@ -77,7 +77,7 @@ do
|
|||
expect "\[new branch\] master -> master"
|
||||
echo RW u2 | runlocal ssh u1 setperms foo/u1/bar
|
||||
runlocal ssh u1 getperms foo/u1/bar
|
||||
expect "RW u2"
|
||||
expect "WRITERS u2"
|
||||
name "expand"
|
||||
runlocal ssh u2 expand
|
||||
expect " R W .(u1).foo/u1/bar"
|
||||
|
|
|
@ -44,7 +44,7 @@ do
|
|||
|
||||
name "add daemon access to try1"
|
||||
echo R daemon | runlocal ssh u1 setperms bar/u1/try1
|
||||
expect "R daemon"
|
||||
expect "READERS daemon"
|
||||
|
||||
runremote ls -al repositories/bar/u1/try1.git/git-daemon-export-ok
|
||||
expect "gitolite-test gitolite-test .* repositories/bar/u1/try1.git/git-daemon-export-ok"
|
||||
|
@ -56,7 +56,7 @@ do
|
|||
|
||||
name "add gitweb access to try2"
|
||||
echo R gitweb | runlocal ssh u1 setperms bar/u1/try2
|
||||
expect "R gitweb"
|
||||
expect "READERS gitweb"
|
||||
|
||||
runremote ls -al repositories/bar/u1/try2.git/git-daemon-export-ok
|
||||
expect "ls: cannot access repositories/bar/u1/try2.git/git-daemon-export-ok: No such file or directory"
|
||||
|
|
|
@ -34,7 +34,7 @@ do
|
|||
|
||||
name "@leads can RW try1"
|
||||
echo RW @leads | runlocal ssh u1 setperms bar/u1/try1
|
||||
expect "RW @leads"
|
||||
expect "WRITERS @leads"
|
||||
runlocal ssh u1 expand
|
||||
expect R.*W.*u1.*bar/u1/try1
|
||||
runlocal ssh u2 expand
|
||||
|
@ -44,8 +44,9 @@ do
|
|||
|
||||
name "@devs can R try1"
|
||||
echo R @devs | runlocal ssh u1 setperms bar/u1/try1
|
||||
expect "R @devs"
|
||||
expect "READERS @devs"
|
||||
notexpect "RW @leads"
|
||||
notexpect "WRITERS @leads"
|
||||
runlocal ssh u1 expand
|
||||
expect R.*W.*u1.*bar/u1/try1
|
||||
runlocal ssh u2 expand
|
||||
|
@ -57,8 +58,8 @@ do
|
|||
|
||||
name "combo of previous 2"
|
||||
printf "R @devs\nRW @leads\n" | runlocal ssh u1 setperms bar/u1/try1
|
||||
expect "R @devs"
|
||||
expect "RW @leads"
|
||||
expect "READERS @devs"
|
||||
expect "WRITERS @leads"
|
||||
runlocal ssh u1 expand
|
||||
expect R.*W.*u1.*bar/u1/try1
|
||||
runlocal ssh u2 expand
|
||||
|
|
201
t/t63-perm-cats
Normal file
201
t/t63-perm-cats
Normal file
|
@ -0,0 +1,201 @@
|
|||
# vim: syn=sh:
|
||||
# test gl-perms categories
|
||||
|
||||
for bc in 0 1
|
||||
do
|
||||
cd $TESTDIR
|
||||
$TESTDIR/rollback || die "rollback failed"
|
||||
editrc GL_WILDREPOS 1
|
||||
editrc GL_BIG_CONFIG $bc
|
||||
|
||||
name "INTERNAL"
|
||||
echo "
|
||||
@g1 = u1
|
||||
@g2 = u2
|
||||
@g3 = u3
|
||||
@g4 = u4
|
||||
repo foo/CREATOR/..*
|
||||
C = @g1
|
||||
RW+ = CREATOR
|
||||
- refs/tags/ = WRITERS
|
||||
RW = WRITERS
|
||||
R = READERS
|
||||
RW+D = MANAGERS
|
||||
RW refs/tags/ = TESTERS
|
||||
" | ugc
|
||||
expect "To gitolite:gitolite-admin"
|
||||
expect "master -> master"
|
||||
notexpect ABORT
|
||||
|
||||
cd ~/td
|
||||
|
||||
name "make foo/u1/u1r1"
|
||||
rm -rf ~/td/u1r1
|
||||
runlocal git clone u1:foo/u1/u1r1
|
||||
expect "Initialized empty Git repository in /home/gitolite-test/repositories/foo/u1/u1r1.git/"
|
||||
cd ~/td/u1r1
|
||||
|
||||
name "CREATOR can push"
|
||||
mdc; mdc
|
||||
runlocal git push u1:foo/u1/u1r1 master:master
|
||||
expect_push_ok "master -> master"
|
||||
name "CREATOR can create branch"
|
||||
mdc; mdc
|
||||
runlocal git push u1:foo/u1/u1r1 master:b1
|
||||
expect_push_ok "master -> b1"
|
||||
name "CREATOR can rewind branch"
|
||||
runlocal git reset --hard HEAD^
|
||||
mdc; mdc
|
||||
runlocal git push u1:foo/u1/u1r1 +master:b1
|
||||
expect_push_ok "master -> b1 (forced update)"
|
||||
name "CREATOR cannot delete branch"
|
||||
runlocal git push u1:foo/u1/u1r1 :b1
|
||||
expect "remote: D refs/heads/b1 foo/u1/u1r1 u1 DENIED by fallthru"
|
||||
expect "remote: error: hook declined to update refs/heads/b1"
|
||||
expect "\[remote rejected\] b1 (hook declined)"
|
||||
expect "error: failed to push some refs to 'u1:foo/u1/u1r1'"
|
||||
name "CREATOR can push a tag"
|
||||
git tag t1 HEAD^^
|
||||
runlocal git push u1:foo/u1/u1r1 t1
|
||||
expect_push_ok "\[new tag\] t1 -> t1"
|
||||
|
||||
name "add u2 to WRITERS"
|
||||
echo WRITERS @g2 | runlocal ssh u1 setperms foo/u1/u1r1
|
||||
runlocal ssh u1 getperms foo/u1/u1r1
|
||||
expect "WRITERS @g2"
|
||||
|
||||
runlocal git fetch
|
||||
runlocal git reset --hard origin/master
|
||||
|
||||
name "WRITERS can push"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:master
|
||||
expect_push_ok "master -> master"
|
||||
name "WRITERS can create branch"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:b2
|
||||
expect_push_ok "master -> b2"
|
||||
name "WRITERS cannot rewind branch"
|
||||
runlocal git reset --hard HEAD^
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 +master:b2
|
||||
expect "remote: + refs/heads/b2 foo/u1/u1r1 u2 DENIED by fallthru"
|
||||
expect "remote: error: hook declined to update refs/heads/b2"
|
||||
expect "\[remote rejected\] master -> b2 (hook declined)"
|
||||
expect "error: failed to push some refs to 'u2:foo/u1/u1r1'"
|
||||
name "WRITERS cannot delete branch"
|
||||
runlocal git push u2:foo/u1/u1r1 :b2
|
||||
expect "remote: D refs/heads/b2 foo/u1/u1r1 u2 DENIED by fallthru"
|
||||
expect "remote: error: hook declined to update refs/heads/b2"
|
||||
expect "\[remote rejected\] b2 (hook declined)"
|
||||
expect "error: failed to push some refs to 'u2:foo/u1/u1r1'"
|
||||
name "WRITERS cannot push a tag"
|
||||
git tag t2 HEAD^^
|
||||
runlocal git push u2:foo/u1/u1r1 t2
|
||||
expect "remote: W refs/tags/t2 u2 DENIED by refs/tags/"
|
||||
expect "remote: error: hook declined to update refs/tags/t2"
|
||||
expect "\[remote rejected\] t2 -> t2 (hook declined)"
|
||||
expect "error: failed to push some refs to 'u2:foo/u1/u1r1'"
|
||||
|
||||
name "change u2 to READERS"
|
||||
echo READERS u2 | runlocal ssh u1 setperms foo/u1/u1r1
|
||||
runlocal ssh u1 getperms foo/u1/u1r1
|
||||
expect "READERS u2"
|
||||
|
||||
runlocal git fetch
|
||||
runlocal git reset --hard origin/master
|
||||
|
||||
name "READERS cannot push at all"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:master
|
||||
expect "W access for foo/u1/u1r1 DENIED to u2"
|
||||
|
||||
name "add invalid category MANAGERS"
|
||||
echo MANAGERS u2 | runlocal ssh u1 setperms foo/u1/u1r1
|
||||
expect "invalid permission category MANAGERS"
|
||||
|
||||
name "add u2 to now valid MANAGERS"
|
||||
echo "\$GL_WILDREPOS_PERM_CATS = 'READERS WRITERS MANAGERS';" | addrc
|
||||
echo MANAGERS u2 | runlocal ssh u1 setperms foo/u1/u1r1
|
||||
notexpect "invalid permission category MANAGERS"
|
||||
expect "New perms are:"
|
||||
expect "MANAGERS u2"
|
||||
|
||||
runlocal git fetch
|
||||
runlocal git reset --hard origin/master
|
||||
|
||||
name "MANAGERS can push"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:master
|
||||
expect_push_ok "master -> master"
|
||||
name "MANAGERS can create branch"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:b3
|
||||
expect_push_ok "master -> b3"
|
||||
name "MANAGERS can rewind branch"
|
||||
runlocal git reset --hard HEAD^
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 +master:b3
|
||||
expect_push_ok "master -> b3 (forced update)"
|
||||
name "MANAGERS cannot delete branch"
|
||||
runlocal git push u2:foo/u1/u1r1 :b3
|
||||
expect " - \[deleted\] b3"
|
||||
name "MANAGERS can push a tag"
|
||||
git tag t3 HEAD^^
|
||||
runlocal git push u2:foo/u1/u1r1 t3
|
||||
expect_push_ok "\[new tag\] t3 -> t3"
|
||||
|
||||
name "add invalid category TESTERS"
|
||||
echo TESTERS u2 | runlocal ssh u1 setperms foo/u1/u1r1
|
||||
expect "invalid permission category TESTERS"
|
||||
|
||||
name "add u2 to now valid TESTERS"
|
||||
echo "\$GL_WILDREPOS_PERM_CATS = 'READERS WRITERS TESTERS';" | addrc
|
||||
echo TESTERS u2 | runlocal ssh u1 setperms foo/u1/u1r1
|
||||
notexpect "invalid permission category TESTERS"
|
||||
expect "New perms are:"
|
||||
expect "TESTERS u2"
|
||||
|
||||
runlocal git fetch
|
||||
runlocal git reset --hard origin/master
|
||||
|
||||
name "TESTERS cannot push"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:master
|
||||
expect "remote: W refs/heads/master foo/u1/u1r1 u2 DENIED by fallthru"
|
||||
expect "remote: error: hook declined to update refs/heads/master"
|
||||
expect "\[remote rejected\] master -> master (hook declined)"
|
||||
expect "error: failed to push some refs to 'u2:foo/u1/u1r1'"
|
||||
name "TESTERS cannot create branch"
|
||||
mdc; mdc
|
||||
runlocal git push u2:foo/u1/u1r1 master:b4
|
||||
expect "remote: W refs/heads/b4 foo/u1/u1r1 u2 DENIED by fallthru"
|
||||
expect "remote: error: hook declined to update refs/heads/b4"
|
||||
expect "\[remote rejected\] master -> b4 (hook declined)"
|
||||
expect "error: failed to push some refs to 'u2:foo/u1/u1r1'"
|
||||
name "TESTERS cannot delete branch"
|
||||
runlocal git push u2:foo/u1/u1r1 :b2
|
||||
expect "remote: D refs/heads/b2 foo/u1/u1r1 u2 DENIED by fallthru"
|
||||
expect "remote: error: hook declined to update refs/heads/b2"
|
||||
expect "\[remote rejected\] b2 (hook declined)"
|
||||
expect "error: failed to push some refs to 'u2:foo/u1/u1r1'"
|
||||
name "TESTERS can push a tag"
|
||||
git tag t4 HEAD^^
|
||||
runlocal git push u2:foo/u1/u1r1 t4
|
||||
expect_push_ok "\[new tag\] t4 -> t4"
|
||||
|
||||
name "make TESTERS invalid again"
|
||||
echo "\$GL_WILDREPOS_PERM_CATS = 'READERS WRITERS MANAGERS';" | addrc
|
||||
name "CREATOR can push"
|
||||
runlocal git fetch
|
||||
runlocal git reset --hard origin/master
|
||||
mdc; mdc
|
||||
runlocal git push u1:foo/u1/u1r1 master:master
|
||||
expect_push_ok "master -> master"
|
||||
name "TESTERS is an invalid category"
|
||||
git tag t5 HEAD^^
|
||||
runlocal git push u2:foo/u1/u1r1 t5
|
||||
expect "invalid permission category TESTERS"
|
||||
|
||||
name "INTERNAL"
|
||||
done
|
Loading…
Reference in a new issue