I got tired of being told "TL;DR". Now the online versions of most documents fit on a page or two, or at least most of them do. The rest has been split out (and you can see the links to the split out sections right where the text is in the raw Markdown). This is much more pleasant to read, and I've improved the linking so it's much less effort for me to keep the links correct.
8.2 KiB
F=ADCs admin defined commands
ADC background
The admin-defined commands (ADCs) feature allows controlled access to specific, "safe", programs or scripts, without giving users full shell access.
WARNING: regardless of what you read below, the security of the code in
the commands or scripts you install as ADCs is your responsibility. The
sample ADCs shipped with gitolite (in contrib/adc
) should be safe enough,
but an extra pair of eyes never hurt, so please review before use.
Although this is a generic way to allow pretty much any command to be run, most of the examples and sample ADCs pertain to allowing users to manage their "own" repos. If that's your use case, please read the [wildcard repositories][wild] doc before you continue here.
ADC details
installing ADCs
ADCs can only be installed by someone with shell access to the server; merely having push rights to the admin repo is not enough.
-
edit
~/.gitolite.rc
and set$GL_ADC_PATH
to a directory that is not in$PATH
. -
add your "safe" executables to this directory.
Warning: An ADC can hide (or override) gitolite's built-in commands like 'info', 'expand', 'setperms', or even 'git-receive-pack' or 'git-upload-pack'! This is by design. So be careful what you name your scripts.
However, it is perfectly ok, and may even be necessary in some cases, to name them after system executables (like 'rsync').
user invocation
If you have a command called "foo" in that directory, then a user can invoke it by saying:
ssh git@server foo argument list
checking authorisation inside an ADC
Once an ADC is installed, all users can run it. But sometimes you want only some people to be able to do so.
While you cannot prevent the ADC from running at all, you can start the ADC with code that checks the user's access to any arbitrary repo. For example, you can bail out if the user does not have "W" access to the "gitolite-admin" repo, which is an easy way of making sure an ADC is only run by admins.
See the section on "the anatomy of a command" later for this and many more details.
checking arguments
Gitolite will call an ADC only if the arguments passed to it match a very
strict pattern (see $ADC_CMD_ARGS_PATT
in src/gitolite_rc.pm
). This
reduces the risk of various kinds of shell-meta related compromises.
passing unchecked arguments
Some commands need arguments with a broader range of characters than
$ADC_CMD_ARGS_PATT
will allow. As long as you are sure those commands are
doing their own argument checking and sanitisation, you can place such
commands in $GL_ADC_PATH/ua
and they will be run with no checks on the
arguments.
The "ua" stand for "unchecked arguments". Consider this your last warning ;-)
"fake" repos and access control for non-git programs
A "fake" repo is a repo that exists in the config file but is specially named (starts with "EXTCMD/") so that gitolite will not create an actual repo on disk for it. It serves as a place holder for different sets of rules.
If you install the 'rsync' ADC, you can use a fake repo called 'EXTCMD/rsync'
to collect a set of rules that specify what user is allowed to read/write what
files using the rsync command on his workstation. See contrib/adc/rsync
for
more on this.
Any non-git program can be similarly access controlled, as long as the command line that the client attempts to execute on the server has sufficient information to decide. Protocols where the command line is just one word and everything else happens in the conversation later cannot be helped by this mechanism.
anatomy of a command
You can do whatever you want in an ADC! It's upto you to check the
permissions of each repo that the user is manipulating using your ADC --
your code can rm -rf $GL_REPO_BASE_ABS
if you like and gitolite wouldn't
stop you.
The current directory ($PWD
) will be set to the $HOME
of git@server
(or
whatever id you're using). It won't be any specific repo, it won't even be
the base directory of all the repos.
Gitolite defines a few environment variables, as well as allows you to directly query the ownership and access permissions of any repository.
The environment variables available are:
GL_USER
-- the name of the user invoking the commandGL_BINDIR
-- the directory containing all the binaries (in particular,gitolite.pm
, which is all we really care about here)GL_REPO_BASE_ABS
-- the absolute path of the base directory containing all the repos
There are a few other variables also available but the above are the only ones you should rely on. Please treat any other variables you notice as being internal/undocumented/subject to change.
[Implementation note: some of the distro packagers don't seem to like
GL_BINDIR
. I have not tested this in those scenarios, but they probably put
gitolite.pm
somewhere in perl's lib path anyway, so it ought to work].
You can query ownership and permissions for the current user (which may not necessarily be the owner). This is done loosely as follows (don't use this exact code yet though):
perl -I$GL_BINDIR -Mgitolite -e "cli_repo_rights('reponame')"
which will print two space-separated words: permissions and owner. Something
like _____R__W u1
or maybe ____@R_@W <gitolite>
. (The u1
indicates the
queried repo is a wildcard repo created by user u1
; for meanings of the "@"
see doc/report-output.mkd)
But that's cumbersome. There's a bash shell function called
get_rights_and_owner
in contrib/adc/adc.common-functions
that is much more
convenient. See any of the other samples for how to use it.
If you prefer perl, there is a nicely commented example in
contrib/adc/get-rights-and-owner.in-perl
.
example uses and sample commands in contrib/adc
#fork the 'fork' ADC
A user would use the fork command like this:
ssh git@server fork from to
where "from" is a repo to which the user invoking the fork has "R" access, and "to" is a repo that does not yet exist and to which he has "C" access.
(Reminder: these access checks are done by the "fork" script, not within gitolite -- once again, you are responsible for making sure your scripts maintain the security of the system!)
Strictly speaking this command is not really needed. Even without all this "admin-defined commands" setup you could still do the following, purely from the client side:
git clone git@server:from
cd from
git remote add new git@server:to
git push new refs/*:refs/*
or some such incantation.
deleting/trashing repos
See the [repo-deletion document][wild_repodel] for details about this.
#able enable/disable push access temporarily
If you want to disable push access to gitolite temporarily (maybe for maintenance), anyone with write access to the gitolite-admin repo can do this:
ssh git@server able dis @all # able dis ==> dis able
To re-enable after the maint work is done:
ssh git@server able en @all # able en ==> en able
You can also do this for one or more individual repos; in place of @all
,
just use a space separated list of reponames (exactly as they would appear in
the config file). Wildcards are not supported; patches welcome ;-)
Note: please see [this][disable] for more on this.
how the ADC feature came about
Gitolite was named to be short for "gitosis-lite". Someone now wants to turn it into a "github-lite" :-) and even had some code to start me off thinking.
Since my first impulse on being asked for a feature is to say no, I was casting about for a reason when he gave me one: he first made some noises about perl, then said something about rewriting it all in scheme. Nice... I resisted the urge to point him to this, told him that's a great idea and he should go for it, mentally blessing him for letting me off the hook on coding it ;-) Laziness is the first virtue you know!
And that was that. For a couple of days.
Soon, though, I realised that there could be a pretty big bonus in this for tightly controlled setups, so I went and coded it all anyway. See the section on "restricted admin" for what's really exciting about this for me.