TODO: if the verb doesn't actually contain "git-receive-pack", I am
assuming it is some sort of read. The list in services[] in
http-backend.c does not seem to look like any other verb is a "write";
need to check this with someone.
For normal git commands:
- PATH_INFO gives you the repo name
- REQUEST_URI gives you the verb
- we construct a fake SSH_ORIGINAL_COMMAND so the rest of the
processing does not have to change
For our special commands:
- PATH_INFO is actually the verb
- QUERY_STRING has the parameters
- we again fake out the SSH_ORIGINAL_COMMAND
- we print the extra HTTP headers in anticipation of the actual output
Either way, we also fake out the SSH_CONNECTION so that the IP address
can get logged ok
And of course REMOTE_USER is now the incoming userid
Finally, at the end, we exec GIT_HTTP_BACKEND instead of the normal one
By default, @all does not include gitweb and daemon, but if that's what
you want, you can make it happen... see GL_ALL_INCLUDES_SPECIAL
variable in conf/example.gitolite.rc
This should hopefully be the final step in making wildrepos as close to
normal repos as possible. You can now do pretty much anything with them
that you can do with normal repos [1]
Implementation notes:
- compile puts out %groups into the compiled config file regardless of
GL_BIG_CONFIG because this feature needs it
- wild_repo_rights caches %groups because the part of the %groups hash
we care about will not change between calls in the same run
----
[1] **except** use the full-blown config file syntax within the gl-perms
file :-) I don't plan to do that; it's too complicated! [2]
[2] yeah yeah I know -- famous last words!
modifications:
- call setup_gitweb_access and setup_daemon_access from with
get_set_perms so when the user sets a perm explicitly it works
- in setup_gitweb_access, do not delete description file or
gitweb.owner if the repo is wild
- make the "fork" adc set gitweb.owner *and* call setperms using
GL_WILDREPOS_DEFPERMS
- add tests
bug fixes:
- gl-auth did not even *look* at GL_WILDREPOS_DEFPERMS when
auto-"C"reating a wild repo; fixed
- setup_gitweb_access did not delete the description file as
consistently as it deleted the owner
what will NOT work:
- removing gitweb permissions does not clear the name from
"projects.list". That's complicated, so just wait till the next
"compile" to make this happen
(thanks to Jefferai for driving this...)
----
mildly puzzling:
for some strange reason, after a "git ls-remote ...try3" in t58,
instead of not creating a "description" file, we started seeing a
73-byte file containing this message:
Unnamed repository; edit this file 'description' to name the repository.
I'm an idiot. I say I won't do it, then I go and do it anyway.
Fortunately, in this case, the code and execution remain exactly the
same for people who do not set $GL_PERFLOGT in the rc file, so it's
tolerable.
<evil grin> People who want even more than this can contact Greg Lonnon
(see the mailing list archives at
http://groups.google.com/group/gitolite for an obfuscated but easy to
guess email address) ;-)
plus it can also be matched by a normal repo line. In other words, with
repo foo/bar
RW = u1
repo foo/..*
RW = u2
user u2 has access to foo/bar (the non-wild does not cause the wild to
be completely ignored any longer)
implementation notes:
get_memberships:
- no more highlander ("there can only be one") for patterns in
@repo_plus
- return $wild as a space-separated list of matched patterns
collect_repo_patts:
- as of the last change to this section of code it appears we
weren't using the values anyway, but I had forgotten :-)
repo_rights: (big change: $wild no longer implies $creator present,
or vice versa)
- new type of "creator" (like "was_sitaram") is now possible
Implementation notes:
- %repo_config is now "our", not "my"
- collect_repo_patts now uses repo_rights to get the name of the wild
card repo (if any) that pertains to the physical $repo, instead of
all that new code (duh!)
- new "can_read(repo, user)" sub (to help daemon and gitweb use)
- the "convenience copy on steroids" thing now copies %repo_config
also, not just %repos. This makes setup_repo_configs simpler
- $creator gets substituted into %groups also; we need that now that
we (%repos and %groups) are working closer together :)
(thanks to Kevin Fleming for the need/use case)
TODO: tests
TODO: proper documentation; meanwhile, just read this:
- you can give gitweb and daemon read rights to wild card repos also,
and it'll all just work -- when a new repo is 'C'reated, it'll pick
up those rights etc
- you can assign descriptions (and owners) to individual repos as
before, except now you can assign them to repos that actually were
created from wild card patterns. So for example, you can define
rules for
repo foo/..*
and then assign descriptions like
foo/repo1 = "repo one"
foo/repo2 = "repo two"
foo/dil "scott" = "scott's dilbert repo"
However, this only works for repos that already exist, and only when
you push the admin repo.
Thumb rule: have the user create his wild repo, *then* add and push
the admin config file with the description. Not the other way
around.
implementation notes:
- wildcard support for git config revamped, refactored...
it's not just git config that needs wildcard support. daemon and
gitweb access also will be needing it soon, so we start by factoring
out the part that finds the "pattern" given a "real" repo name.
- GL_NO_DAEMON_NO_GITWEB now gates more than just those two things;
see doc/big-config.mkd for details
- we trawl through $GL_REPO_BASE_ABS *once* only, collecting repo
names and tying them to either the same name or to a wild pattern
that the repo name was created from
- nice little subs to setup gitweb, daemon, and git config
- god bless $GL_REPOPATT and the day I decided to set that env var
whenever a user hits a wild repo in any way :-)
- the code in gl-compile-conf is very simple now. Much nicer than
before
make it a sort of "super global" (an ENV var) all through, because
*everyone* seems to need it *and* this variable is pretty much constant
for the entire install
- new GL_GITCONFIG_WILD to gate it
- new sub to do all the hard work (refactored from a few lines in
compile)
- split the call from "compile" into two sets -- first for non-wild,
then for wild
This ensures that after a "compile" (admin push) all git configs are
applied.
TODO: apply them when a new wild repo is created by a user, and then on
the "fork" (admin-defined command)
NOTE: there are no *functional* changes in this for *normal*
gitolite users. It's just a chunk of code moving into a new
subroutine etc.
KDE needs to populate the authkeys file from an LDAP store. Other large
projects may have similar means to store keys, depending on how they do
their user provisioning so a generic solution is worth exploring.
This means that in these special cases
- the gitolite-admin repo's keydir/ directory is not needed [1]
- but they still need to create the authkeys file somehow
Implementation:
- write a shim program to make the authkeys-generation code callable
from the command line/shell.
- set $GL_NO_SETUP_AUTHKEYS=1 in the rc file to disable authkey
generation during a "compile" (admin repo push)
Expected usage of new program gl-setup-authkeys:
- LDAP change triggers some script
- this script collects all keys from LDAP, puts them in some
directory, and then calls gl-setup-authkeys, passing it the name of
the directory
ALSO PLEASE SEE COMMENTS AT THE TOP OF THE NEW PROGRAM IN THIS COMMIT
FOR SOME IMPORTANT DISCUSSION.
----
Footnotes:
[1] It doesn't make sense to use it if the keys will be maintained by
some other entity and can be called up as needed, and it adds an
unnecessary extra step.
sometimes I want to quickly test a few lines of change within the context of
a currently-running/just-ran test, *without* doing the rollback etc.
Here's how you do that now:
- in your source tree, make the change and then run:
cp -a src hooks contrib/adc /some/tmp/place
- go to the tester userid and re-run your tests like so:
GQT=/some/tmp/place ./test-driver.sh
it'll rollback as normal then overwrite src and hooks from $GQT
Also, there's now a "dbg" sub that can be used for quick printf-style
debugging.
Fedora, till now, had no hope in hell of running the info command. Why?
Because the output of the info command is semantically the same as the
output of the compile script *before* the big-config mode was created.
And we all know how _that_ went ;-)
So now you get to give "info" a partial reponame or a pattern, just like
in the case of "expand". And if you're under GL_BIG_CONFIG this pattern
is mandatory. And if you try to cheat it'll still stop after showing 5
entries to prevent (accidental?) DOSs
Anyway, see doc changes in this commit for more details.
thanks to Jesse from the Fedora team for pointing this out. They use
GL_NO_CREATE_REPOS, so sometimes the physical repo on disk doesn't exist
at the time the config file is written.
We're talking about non-wild repos only here, so this means it should
never happen to normal gitolite users. But now -- in the rare case that
there is a disk-side problem -- people who have rights to a repo will
get a more specific error message.
this allows the first part of the repo name (if wildcard repos are
activated) to have a regex like [a-zA-Z0-9]+.
----
Note added by committer:
he assumption used to be that all wildcard repos will have some common
prefix like "users", but I did not imagine it would be like
repo [a-zA-Z0-9]+/users/CREATOR/[a-zA-Z0-9]+
(viz., the "users" is in the middle).
Sounds reasonable...
fixes:
- allow "grouped" admins to get basic info for other users by checking
more than just the *user*'s right to the admin repo
- report_basic is called with a $user argument, but it's not easy
(right now) to propagate this to parse_acl. Use a simple kludge,
(for now at least).
thanks to bcooksley for catching this
This is what I *should* have done back then; thanks to Jeff Mitchell for
pointing out a problem with the old method.
The old one is *definitely* a kludge. <shamefaced grin>
The log message format has changed. All log messages now have a common
prefix (timestamp, user, IP). This is followed by $SSH_ORIGINAL_COMMAND
(or, in one special case, the name of the user's login shell). Any
further text appears after this (currently this only happens in the case
of a successful push -- one for each ref pushed successfully)
in addition, due to "+" becoming a valid character in a normal reponame,
(think gtk+, etc), the pattern
repo dev/CREATOR/.+
doesn't look like a wildcard repo anymore, so we add an extra check that
if CREATOR is mentioned, it *is* a wildcard.
This has been added *only* to the report_basic function; it doesn't
really matter anywhere else.
see doc/3 for details (look for "separating delete and rewind rights"
----
and for gerrit, this is one more thing it can do that we can too ;-)
[the original text was somewhat misleading. We mean "prevent someone
from creating a branch that they have permissions to push". That is
what is now possible, where it was not possible before.]
the commits leading up to v1.5 caused the data format to change (we
added a rule sequence number).
This in turn caused a problem for people who may have installed using
the "system install / user setup" mode of install (which includes people
who used RPM/DEB to install it) -- they would now have to *manually* run
"gl-setup" once after the rpm/deb upgrade.
This commit *tries* to mitigate this problem by recording a data format
version number in the compiled output file. On any access to that file,
if the version number is not found or is found to be not equal to the
current version, gl-setup is run again.
The reason I say "*tries*" is that the exact command used to do this is
a bit of a hack for now. However, if it works for Fedora and Debian,
I'm going to leave it at that :)
There were 2 problems with rule sequencing.
Eli had a use case where everyone is equal, but some are more equal than
the others ;-) He wanted a way to say "everyone can create repos under
their own names, but only some people should be able to rewind their
branches".
Something like this would be ideal (follow the rules in sequence for
u1/u2/u3/u4, and you will see that the "deny" rule kicks in to prevent
u1/u2 from being able to rewind, although they can certainly delete
their branches):
@private-owners = u1 u2
@experienced-private-owners = u3 u4
repo CREATOR/.*
C = @private-owners @experienced-private-owners
RWD = CREATOR
RW = WRITERS
R = READERS
- = @private-owners
RW+D = CREATOR
In normal gitolite this doesn't work because the CREATOR rules (which
get translated to "u1" at runtime) end up over-writing the "deny" rule
when u1 or u2 are the creators. This over-writing happens directly at
the "do compiled.pm" step.
With big-config, this does not happen (because @private-owners does not
get expanded to u1 and u2), but the problem remains: the order of
picking up elements of repo_plus and user_plus is such that, again, the
RW+D wins (it appears before the "-" rule).
We fix all that by
- making CREATOR complete to more than just the creator's name (for
"u1", it now becomes "u1 - wild", which is actually illegal to use
for real so there's no possibility of a name clash!)
- maintaining a rule sequence number that is used to sort the rules
eventually applied (this also resulted in the refex+perm hash
becoming a list)
[Please NOTE: this is all about *user* groups, not *repo* groups]
SUMMARY: gl-auth-commmand can now take an optional list of usergroup
names after the first argument (which is the username).
See doc/big-config.mkd in the next commit or so
If you have many thousands of repos and users, neatly organised into
groups, etc., the normal gitolite fails. (It actually runs out of
memory very fast while doing the "compile" when you push the config, due
to the number of combinations of repo/user being stored in the hash!)
This commit series will stop doing that if you set $GL_BIG_CONFIG = 1 in
the rc file.
Some notes:
- deny rules will still work but somewhat differently -- now they must
be placed all together in one place to work like before. Ask me for
details if you need to know before I get done with the docs
- I've tested most of the important features, but not every single
nuance
- the update hook may be a tad less efficient now; we can try and
tweak it later if needed but it shouldn't really hurt anything
significantly even now
- docs have not been written yet
Ouch! How mortifying :) I'd always thought this was one of the Brit/US
differences, but to find out that it really *isn't* a word... hmph!
Anyway, in the interest of not breaking existing wild repos, the
ownership file is still called "gl-creater". Everything else has been
changed.
(...thanks to Sverre)
This commit series allows an admin to designate a set of commands that
users can run. For example, he can allow users to delete a repo that
they have created:
ssh git@server rmrepo foo/me/bar
or fork (to use github's terminology) a repo they have "R" access to,
into a new one they have "C" access to:
ssh git@server fork foo/someone-else/bar foo/me/bar
Please see documentation for details
----
(this commit)
- (rc) new variable $GL_ADC_PATH; without this none of this is enabled
- (pm) new helper routine "cli_repo_rights" to get rights/ownership
from outside
- (auth) call $GL_ADC_PATH/$cmd if it exists
This commit series refactors all the rights querying logic.
- old repo_rights sub renamed to wild_repo_rights
- new repo_rights sub to be a single entry point for most rights
queries
- callable from gl-auth-command and expand_wild
- callable from *outside* too, as long as $ENV{GL_USER} is set
- the format of the returned permissions contains C, R, and W as
applicable, with sigils reflecting the 3 possible ways in which you
can get R or W perms (2 ways for C):
@R means @all users have the same access
#R means you're a "super user" (think root's shell prompt) so
you can see all repos
R is the normal, explicit, access
All this is about a user trying to look if a repo exists or not, when he
does not have any access to that repo. Ideally, "repo does not exist"
should be indistinguishable from "you dont have perms to that repo".
(1) if $GL_WILDREPOS is not set, you either get a permissions error, or
a "$repo not found in compiled config" death. Fixed.
(2) if $GL_WILDREPOS is set, you either get either a permissions error,
or a "$repo has no matches" death. Fixed.
(3) The following combination leaks info about repo existence:
- actual repo doesn't exist
- spying user don't have C perms
- repo patt doesn't contain CREATER
- RW+ = CREATER is specified (as is normal)
In such case, the "convenience copy" of the ACL that parse_acl
makes, coupled with substituting CREATER for the invoking user means
$repos{$actual_repo} has RW+ for the spying user. This means the
access denied doesn't happen, and control passes to git, which
promptly expresses it unhappiness and angst over being given a repo
that 'does not appear to be a git repository'
This doesn't happen if all those conditions are not met:
- if repo exists, CREATER is set to the real creater, so RW+ =
CREATER does not gain spying user anything
- if spying user has C perms it just gets created, because he has
rights. This is also info leak but we can't prevent it; tighten
the config (maybe by including CREATER in repo pattern) if this
is not wanted
- if repo patt contains CREATER it will never match someone else's
repo anyway!
- no need to put it at the end of the config file now, yeaaay!
- @all for @all is meaningless and not supported. People asking will
be told to get a life or use git-daemon.
- NAME/ limits for @all repos is ignored for efficiency reasons.
Data dumper was failing (returning an empty string!) on an input config
file of about 350 lines or so (output 2400 lines or so).
Removing the sort sub fixed the problem.
To recap why that sub was put in (see deleted lines in this commit for
details), what we really want is that $creater must appear *last* in the
resulting dump.
So we trick it. "man ascii" tells you that ~ is the highest valued
ASCII character (yes, I know, not utf-8 safe etc... I'll deal with that
if and when needed or punt!). So we just put that in front of $creater
and remove it later...
You *don't* want to do this for $readers and $writers -- then they will
once again sort *after* $creater, which would be a bad thing. Also,
it's probably better this way, because now the order of the hash keys
will be: $readers, $writers, any actual users listed, and then $creater.
This means the effective access rights will be:
1. if you are the creater you get CREATER's rights
2. else if your userid is listed *explicitly* in the config, you get
those rights
3. else if you've been setperm'd as a writer, you get WRITERS rights
4. else if you've been setperm'd as a reader, you get READERS rights
This is different from what used to happen till now; READERS and WRITERS
used to trump explicitly given rights. I'd been meaning to fix that
somehow, but never got around to it, until this DDD (damn Data Dumper!)
forced my hand :)
The new style personal branches work by interpreting the special
sequence /USER/ (including the slashes) in a refname. Docs should be in
the next commit...
Currently the pattern of expand command is line anchored. This is
different than in e.g. grep, and causes extra work to add '.*' prefix
and/or suffix in many use cases.
The new semantics now mean you might get more matches than you would
have gotten earlier. However, the expand command is still totally
undocumented, so I think it is acceptable to change the functionality.
;)
This patch removes the anchoring. So for earlier behavior the specified
pattern needs be in form of '^<pattern>$'. The default pattern is also
changed from '.*' to '^', so there might be even a small speed
improvement. =)
Signed-off-by: Teemu Matilainen <teemu.matilainen@reaktor.fi>
[TODO: allow a callback for a password checking function, such as
"passwd_policy_check". Question is where the function would go.
~/.gitolite.rc is the only possible place among the current set of files
but I'd rather leave that as a list of simple name=value lines for all
sorts of reasons. So maybe something like ~/.gitolite.pm (analogous to
the "gitolite.pm" in the sources I supply), which would get "require'd"
if found, and would contain all user-defined functions like this one...
needs some thinking about]