85da5572b2
- support for ADCs with unchecked arguments - rsync, htpasswd, and svnserve gone from core; turned into ADCs Backward compat breakage and fix: Please see documentation for details, but if you're using gitolite to control rsync you will now need to setup ADCs (admin defined commands), and install at least the new "rsync" ADC. ---- Thanks to Joey Hess (see commit prior to this) for forcing me to stop being lazy and get this out of my long term todo list.
268 lines
10 KiB
Markdown
268 lines
10 KiB
Markdown
## admin defined commands
|
|
|
|
----
|
|
|
|
In this document:
|
|
|
|
* <a href="#_background">background</a>
|
|
* <a href="#_details">details</a>
|
|
* <a href="#_installing_ADCs">installing ADCs</a>
|
|
* <a href="#_user_invocation">user invocation</a>
|
|
* <a href="#_checking_authorisation">checking authorisation</a>
|
|
* <a href="#_checking_arguments">checking arguments</a>
|
|
* <a href="#_passing_unchecked_arguments">passing unchecked arguments</a>
|
|
* <a href="#_fake_repos_and_access_control_for_non_git_programs">"fake" repos and access control for non-git programs</a>
|
|
* <a href="#_anatomy_of_a_command">anatomy of a command</a>
|
|
* <a href="#_example_uses_and_sample_commands_in_contrib_adc_">example uses and sample commands in `contrib/adc`</a>
|
|
* <a href="#_fork">fork</a>
|
|
* <a href="#_deleting_trashing_repos">deleting/trashing repos</a>
|
|
* <a href="#_enable_disable_push_access_temporarily">enable/disable push access temporarily</a>
|
|
* <a href="#_how_this_feature_came_about">how this feature came about</a>
|
|
|
|
----
|
|
|
|
<a name="_background"></a>
|
|
|
|
### 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.
|
|
|
|
<font color="gray">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
|
|
[doc/wildcard-repositories.mkd][wild] before you continue here.</font>
|
|
|
|
[wild]: http://sitaramc.github.com/gitolite/doc/wildcard-repositories.html
|
|
|
|
<a name="_details"></a>
|
|
|
|
### details
|
|
|
|
<a name="_installing_ADCs"></a>
|
|
|
|
#### 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').
|
|
|
|
<a name="_user_invocation"></a>
|
|
|
|
#### 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
|
|
|
|
<a name="_checking_authorisation"></a>
|
|
|
|
#### checking authorisation
|
|
|
|
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.
|
|
|
|
<a name="_checking_arguments"></a>
|
|
|
|
#### 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.
|
|
|
|
<a name="_passing_unchecked_arguments"></a>
|
|
|
|
#### 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 ;-)
|
|
|
|
<a name="_fake_repos_and_access_control_for_non_git_programs"></a>
|
|
|
|
### "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.
|
|
|
|
<font color="gray">*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.</font>
|
|
|
|
<a name="_anatomy_of_a_command"></a>
|
|
|
|
### 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 command
|
|
* `GL_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`.
|
|
|
|
<a name="_example_uses_and_sample_commands_in_contrib_adc_"></a>
|
|
|
|
### example uses and sample commands in `contrib/adc`
|
|
|
|
<a name="_fork"></a>
|
|
|
|
#### fork
|
|
|
|
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.
|
|
|
|
<a name="rmrepo"></a>
|
|
|
|
<a name="_deleting_trashing_repos"></a>
|
|
|
|
#### deleting/trashing repos
|
|
|
|
See the [repo-deletion document][rdR] for details about this.
|
|
|
|
[rdR]: http://sitaramc.github.com/gitolite/contrib/adc/repo-deletion.html
|
|
|
|
<a name="_enable_disable_push_access_temporarily"></a>
|
|
|
|
#### 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][diswr] for more on this.
|
|
|
|
[diswr]: http://sitaramc.github.com/gitolite/doc/3-faq-tips-etc.html#_disabling_write_access_to_take_backups
|
|
|
|
----
|
|
|
|
<a name="_how_this_feature_came_about"></a>
|
|
|
|
### how this feature came about
|
|
|
|
<font color="gray">
|
|
|
|
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][xkcd224], 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][lazy] *is* the first virtue you know!
|
|
|
|
[xkcd224]: http://xkcd.com/224/
|
|
[lazy]: http://c2.com/cgi/wiki?LazinessImpatienceHubris
|
|
|
|
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*.
|
|
|
|
</font>
|