It would be great to support git-annex in ikiwiki-hosting. One of the things that would need to change would be the iki-git-shell
command, which currently doesn't allow git-annex-shell
to run, which breaks git-annex
. I tried setting the annex-shell
variable on the client side to git annex-shell
to try to workaround the issue, but it still fails with:
fatal: unrecognized command 'git-annex-shell '/home/w-...'' ...
The client then sets the annex-ignore
variable and ignores that remote. And of course we'd also need ikiwiki itself to support git-annex but that's another story - at least allowing uploads would be a nice start.
The workaround, of course, is to set git-annex-shell
as the command in the authorized_keys
file instead of iki-git-shell
... but that doesn't quite work because the remote URLs change completely.
So one solution is to exploit the git-shell-commands
extension of git-shell
, which allows running arbitrary commands from git-shell
. Since git-annex
starts with git
, it will clear the iki-git-shell
checks - but it fails in git-shell
because it's not a recognized git command. To fix this, we need to add the following script in $HOME/git-shell-commands/git-annex-shell
:
#!/usr/bin/python import os import re import shlex import sys try: # original command is like: # "git-annex-shell 'configlist' '/'" # argv is expected to be: # ['git-shell-commands/git-annex-shell', '/home/.../source.git/'] # the last argument is the sanitized repo path from iki-git-shell # so parse the original command string into an array safely orig_argv = shlex.split(os.environ['SSH_ORIGINAL_COMMAND']) # construct the command with the original command and the safe repo path cmd = ['git-annex-shell', '-c', orig_argv[1], sys.argv[1]] # if we have more arguments, shove them in (skipping unsafe path) cmd += orig_argv[3:] # restrict git-shell to known commands os.environ['GIT_ANNEX_SHELL_LIMITED'] = 'true' # restrict git-annex to the sanitized repository os.environ['GIT_ANNEX_SHELL_DIRECTORY'] = sys.argv[1] # keep all commands as readonly, disabled #os.environ['GIT_ANNEX_SHELL_READONLY'] = 'true' # split into that new command os.execlp('git-annex-shell', *cmd) except Exception as e: print "git-annex-shell wrapper improperly called: %s" % e
This will not work out of the box with iki-git-shell
because the C code garbles the SSH_ORIG_COMMAND
with strtok
. The following patch is also necessary to carry the command down below:
diff --git a/iki-git-shell.c b/iki-git-shell.c index 70250ad..37639a2 100644 --- a/iki-git-shell.c +++ b/iki-git-shell.c @@ -74,6 +74,10 @@ int main (int argc, char **argv) { fprintf(stderr, "error: SSH_ORIGINAL_COMMAND not set\n"); exit(1); } + if (asprintf(&command, command) == -1) { + perror("asprintf"); + exit(1); + } s=strtok(command, " -"); /* handle "git-" and "git " */ if (! s) {
That way the tokenizer operates on a copy of the string instead of garbling the environment directly.
Now, I know that:
- this is clunky
- it's python (heretic! burn! burn!)
- there's more comments than code (but I took a while to figure that stuff out, so better to share)
- it doesn't solve git-annex support in ikiwiki (ie. the objects won't get pushed to the source repo)
- it's 1h30AM on a friday
But:
- it's a start!
- it works (ie. it will drop keys, share configs, etc)
- it should be fairly secure
Your feedback would be greatly appreciated here. At the very least I think the patch on iki-git-shell can't hurt, unless hiding the original git command was deliberate.
Thanks! -- anarcat