fold rebel into master :) [please read]

Well, something even more outrageous than deny rules and path-based
limits came along, so I decided that "rebel" was actually quite
"conformist" in comparision ;-)

Jokes apart, the fact is that the access control rules, even when using
deny rules and path-limits, are still *auditable*.  Which means it is
good enough for "corporate use".

[The stuff that I'm working on now takes away the auditability aspect --
individual users can "own" repos, create rules for themselves, etc.

So let's just say that is the basis of distinguishing "master" now.]
This commit is contained in:
Sitaram Chamarty 2009-12-01 07:15:05 +05:30
parent 498e62c2f3
commit d71720d050
3 changed files with 63 additions and 132 deletions

View file

@ -3,28 +3,7 @@
> [Update 2009-10-28: apart from all the nifty new features, there's now an > [Update 2009-10-28: apart from all the nifty new features, there's now an
> "easy install" script in the src directory. This script can be used to > "easy install" script in the src directory. This script can be used to
> install as well as upgrade a gitolite install. Please see the INSTALL > install as well as upgrade a gitolite install. Please see the INSTALL
> document for details]
> ----
> ***REBEL FORK WARNING***
> The paranoid half of Sitaram's brain would like to warn you that the other
> half rebelled and created this fork.
> 1. please read the "design choices" section in the [faqs, tips, etc]
> [fted] document for background
> 2. please read the comments in the example.conf file carefully before
> creating your own config file
> 3. please test your configuration carefully
> 4. if you still have problems and contact me, please mention right up
> front that you're using the ***rebel edition***; makes it easier to
> troubleshoot
[fted]: http://github.com/sitaramc/gitolite/blob/rebel/doc/3-faq-tips-etc.mkd
----
> document in the doc directory for details]
---- ----
@ -100,8 +79,7 @@ detail [here][gsdiff].
a synonym for "annotate" :-)] a synonym for "annotate" :-)]
* "personal namespace" prefix for each dev * "personal namespace" prefix for each dev
* migration guide and simple converter for gitosis conf file * migration guide and simple converter for gitosis conf file
* "exclude" (or "deny") rights in the config file -- this is the "rebel" * "exclude" (or "deny") rights at the branch/tag level
branch in the repository, and always will be ;-)
### security ### security

View file

@ -99,6 +99,10 @@ repo @oss_repos
# ADVANCED PERMISSIONS USING REFEXES # ADVANCED PERMISSIONS USING REFEXES
# - refexes are specified in perl regex syntax # - refexes are specified in perl regex syntax
# - refexes are matched without any anchoring, which means a refex like
# "refs/tags/v[0-9]" matches anything *containing* that pattern. There
# may be text before and after it (example: refs/tags/v4-r3p7), and it
# will still match
# - if no refex appears, the rule applies to all refs in that repo # - if no refex appears, the rule applies to all refs in that repo
# - a refex is automatically prefixed by "refs/heads/" if it doesn't start # - a refex is automatically prefixed by "refs/heads/" if it doesn't start
# with "refs/" (so tags have to be explicitly named as # with "refs/" (so tags have to be explicitly named as
@ -123,9 +127,11 @@ repo git
RW tmp/ = @all RW tmp/ = @all
RW refs/tags/v[0-9] = junio RW refs/tags/v[0-9] = junio
# REBEL BRANCH -- DENY/EXCLUDE RULES # DENY/EXCLUDE RULES
# please see the "faq, tips, etc" document for details on the "rebel" edition. # ***IMPORTANT NOTE: if you use deny rules, the order of the rules also makes
# a difference, where earlier it did not. Please review your ruleset
# carefully or test it***. Or ask me.
# in the example above, you cannot easily say "anyone can write any tag, # in the example above, you cannot easily say "anyone can write any tag,
# except version tags can only be written by junio". The following might look # except version tags can only be written by junio". The following might look
@ -134,7 +140,8 @@ repo git
# RW refs/tags/v[0-9] = junio # RW refs/tags/v[0-9] = junio
# RW refs/tags/ = junio linus pasky @others # RW refs/tags/ = junio linus pasky @others
# in the "rebel" branch, however, you can do this: # if you use "deny" rules, however, you can do this (a "deny" rule just uses
# "-" instead of "R" or "RW" or "RW+" in the permission field)
RW refs/tags/v[0-9] = junio RW refs/tags/v[0-9] = junio
- refs/tags/v[0-9] = linus pasky @others - refs/tags/v[0-9] = linus pasky @others

View file

@ -17,12 +17,10 @@ In this document:
* one user, many keys * one user, many keys
* support for git installed outside default PATH * support for git installed outside default PATH
* what repos do I have access to? * what repos do I have access to?
* other cool things * "exclude" (or "deny") rules
* "personal" branches * "personal" branches
* design choices * design choices
* keeping the parser and the access control separate * keeping the parser and the access control separate
* why we don't do "excludes"
* how the rebel edition does it anyway :)
### common errors and mistakes ### common errors and mistakes
@ -179,8 +177,8 @@ Each refex that allows `W` access (or `+` if this is a rewind) for *this*
user, on *this* repo, is matched against the actual refname being updated. If user, on *this* repo, is matched against the actual refname being updated. If
any of the refexes match, the push succeeds. If none of them match, it fails. any of the refexes match, the push succeeds. If none of them match, it fails.
The normal gitolite does not allow "exclude" or "deny" rules. But see the Gitolite also allows "exclude" or "deny" rules. See later in this document
"how the rebel edition does it anyway" below. for details.
#### error checking the config file #### error checking the config file
@ -404,7 +402,54 @@ Note that until this version, we used to put out an ugly `need
SSH_ORIGINAL_COMMAND` error, just like gitosis used to. All we did is put SSH_ORIGINAL_COMMAND` error, just like gitosis used to. All we did is put
that code path to better use :-) that code path to better use :-)
### other cool things #### "exclude" (or "deny") rules
Take a look at the following snippet, which *seems* to say that "bruce" can
write versioned tags (anything containing `refs/tags/v[0-9]`), but the other
staffers can't:
@staff = bruce whitfield martin
[... and later ...]
RW refs/tags/v[0-9] = bruce
RW refs/tags = @staff
But that's not how the matching works. As long as any refex matches the
refname being updated, it's a "yes". Since the second refex (which says
"anything containing `refs/tags`") is a superset of the first one, it lets
anyone on `@staff` create versioned tags, not just Bruce.
One way to fix this is to allow "excludes" -- some changes in syntax, combined
with a rigorous, ordered, interpretation would do it.
Let's recap the **existing semantics**:
> the first matching refex that has the permission you're looking for (`W`
> or `+`), results in success. A fallthrough results in failure
Here are the **new semantics**, with changes from the "main" one in bold:
> the first matching refex that has the permission you're looking for (`W`
> or `+`) **or a minus (`-`)**, results in success **or failure,
> respectively**. A fallthrough **also** results in failure
So the example we started with becomes, if you use "deny" rules:
RW refs/tags/v[0-9] = bruce
- refs/tags/v[0-9] = @staff
RW refs/tags = @staff
And here's how it works:
* for non-version tags, only the 3rd rule matches, so anyone on staff can
push them
* for version tags by bruce, the first rule matches so he can push them
* for version tags by staffers *other than bruce*, the second rule matches
before the third one, and it has a `-` as the permission, so the push
fails
***IMPORTANT NOTE: if you use deny rules, the order of the rules also makes a
difference, where earlier it did not. Please review your ruleset carefully or
test it***. Or ask me.
#### "personal" branches #### "personal" branches
@ -481,102 +526,3 @@ have to be first "compiled", and the access control programs use this
If you choose the "easy install" method, all this is quite transparent to you If you choose the "easy install" method, all this is quite transparent to you
anyway. If you cannot use the easy install and must install manually, I have anyway. If you cannot use the easy install and must install manually, I have
clear instructions on how to set it up. clear instructions on how to set it up.
#### why we don't do "excludes"
[umm... having said all this, I implemented it anyway; see the "rebel"
branch!]
I found an error in the example conf file. This snippet *seems* to say that
"bruce" can write versioned tags (`refs/tags/v[0-9].*`), but the other
staffers can't:
@staff = bruce whitfield martin
[... and later ...]
RW refs/tags/v[0-9].* = bruce
RW refs/tags = @staff
But that's not how the matching works. As long as any refex matches the
refname being updated, it's a "yes". So the second refex lets anyone on
`@staff` create versioned tags, not just Bruce.
One way to fix this is to allow "excludes" -- some changes in syntax, combined
with a rigorous, ordered, interpretation would do it.
But if you're ever played with squid ACLs, or the include/exclude rules for
rsync, or rdiff-backup, or even git's own ignore mechanism, you'll see why I
won't do this. It bloats the code and the docs, and, despite all the docs,
*still* confuses people, which may then *reduce* security!
Squid, rsync, gitignore, and all *need* the feature and so tolerate all this;
but we don't need it. All we need to do is make the refexes *disjoint* in
what they match (i.e., ensure that no refname can be matched by more than one
refex):
RW refs/tags/v[0-9].* = bruce
RW refs/tags/staff/ = @staff
In general, you probably want to control the refnames writable by devs anyway,
if at least to maintain some sanity, so being forced to make the refexes
disjoint is not a big problem. Here's an example: only the `project_lead` can
make arbitrarily named refs, while the rest have to stay within their assigned
namespaces:
RW+ = project_lead
RW refs/tags/qa/ = @qa_team
RW bugID/ = @dev_team
RW trac/ = @dev_team
The lack of overlap between refexes ensures ***no confusion*** in specifying,
understanding, and ***auditing***, what is allowed and what is not.
And in security, "no confusion" is a good thing :-)
#### how the rebel edition does it anyway :)
Well, reuss on #git asked, I pointed him to the discussion above and said
"no", and he was nice enough to agree. But then I started thinking that maybe
not everyone needs such "safe" environments. And so, as the README says:
> The paranoid half of Sitaram's brain would like to warn you that the other
> half rebelled and created this fork.
Let's recap the **existing semantics**:
> the first matching refex that has the permission you're looking for (`W`
> or `+`), results in success. A fallthrough results in failure
First I changed the format of the compiled config file (an internal file that
the user doesn't have to worry about, as long as he remembers to run the
compile script on every upgrade). The format change kept the existing syntax
and semantics of the config file, but it laid the ground work for allowing
"excludes" using **just one extra line of code** (and a very slight change to
another)!
This extremely small delta between the rebel edition and the main one will
make it trivial to maintain it as a separate branch, regardless of what other
changes happen in the mainline, because I honestly don't see rebel merging
into the mainline.
Yet ;-)
Here are the **rebel semantics**, with changes from the "main" one in bold:
> the first matching refex that has the permission you're looking for (`W`
> or `+`) **or a minus (`-`)**, results in success **or failure,
> respectively**. A fallthrough **also** results in failure
So the example we started with becomes, in the rebel edition:
RW refs/tags/v[0-9].* = bruce
- refs/tags/v[0-9].* = @staff
RW refs/tags = @staff
And here's how it works:
* for non-version tags, only the 3rd rule matches, so anyone on staff can
push them
* for version tags by bruce, the first rule matches so he can push them
* for version tags by staffers *other than bruce*, the second rule matches
before the third one, and it has a `-` as the permission, so the push
fails