diff --git a/README.rst b/README.rst index 65d58f8..3266bfb 100644 --- a/README.rst +++ b/README.rst @@ -24,7 +24,17 @@ more information. You can get ``gitosis`` via ``git`` by saying:: - git clone https://github.com/tv42/gitosis.git + This repositories are from jakob@schuerz.at, support python3 and ssh-certificates + git clone git@codeberg.org:xundeenergie/gitosis.git (fetch) + git clone git@github.com:xundeenergie/gitosis.git (fetch) + git clone git@git.schuerz.at:public/gitosis.git (fetch) + + This repository translates gitosis to python3, but not fully. + git clone git@github.com:mgukov/gitosis.git (push) + + Original repository seems unmaintained + git clone git@github.com:tv42/gitosis.git (fetch) + And install it via:: @@ -75,6 +85,12 @@ it to running ``gitosis-serve``. Run:: sudo -H -u git gitosis-init >fp, line + line = ' '.join([urllib.parse.quote_plus(s) for s in response]) + #print >>fp, line + print(line, end="", file=fp) def generate_project_list(config, path): """ @@ -159,7 +160,8 @@ def set_descriptions(config): tmp = '%s.%d.tmp' % (path, os.getpid()) f = open(tmp, 'w') try: - print >>f, description + #print >>f, description + print(description, end="", file=f) finally: f.close() os.rename(tmp, path) diff --git a/gitosis/init.py b/gitosis/init.py index d81ceed..7d512c1 100644 --- a/gitosis/init.py +++ b/gitosis/init.py @@ -6,6 +6,7 @@ import logging import os import sys +import re from pkg_resources import resource_filename from io import StringIO @@ -32,19 +33,32 @@ def __str__(self): return '%s: %s' % (self.__doc__, ': '.join(self.args)) def ssh_extract_user(pubkey): - _, user = pubkey.rsplit(None, 1) + if not bool(re.search(r"\s", pubkey)): + _, user = pubkey.rsplit(None, 1) + else: + user = pubkey.strip() if ssh.isSafeUsername(user): return user else: raise InsecureSSHKeyUsername(repr(user)) def initial_commit(git_dir, cfg, pubkey, user): + log.debug('create initial commit') + log.info('User: ' + user) + if pubkey is None: + keyfile = 'keydir/principals' + content = user + else: + keyfile = 'keydir/%s.pub' % user + content = pubkey + log.debug('keyfile' + keyfile) + log.debug('content' + content) repository.fast_import( git_dir=git_dir, commit_msg='Automatic creation of gitosis repository.', committer='Gitosis Admin <%s>' % user, files=[ - ('keydir/%s.pub' % user, pubkey), + (keyfile, content), ('gitosis.conf', cfg), ], ) @@ -127,6 +141,9 @@ def handle_args(self, parser, cfg, options, args): log.info('Reading SSH public key...') pubkey = read_ssh_pubkey() user = ssh_extract_user(pubkey) + if not " " in pubkey: + pubkey = None + log.debug("pubkey: %s", pubkey) if user is None: log.error('Cannot parse user from SSH public key.') sys.exit(1) diff --git a/gitosis/principals.py b/gitosis/principals.py new file mode 100644 index 0000000..4339afe --- /dev/null +++ b/gitosis/principals.py @@ -0,0 +1,48 @@ +""" +Perform gitosis actions for a git hook. +""" + +import errno +import logging +import os +import sys +import shutil + +from gitosis import repository +from gitosis import ssh +from gitosis import gitweb +from gitosis import gitdaemon +from gitosis import app +from gitosis import util + + +def serve_principal(cfg, sshUser, principals): + + TEMPLATE=('command="gitosis-serve %(user)s",no-port-forwarding,' + +'no-X11-forwarding,no-agent-forwarding,no-pty %(principals)s') + + for p in util.getAllowedSSHPrincipals(config=cfg).split() : + print(TEMPLATE % dict(user=sshUser.partition('@')[0], principals=p)) + +class Main(app.App): + def create_parser(self): + parser = super(Main, self).create_parser() + parser.set_usage('%prog [OPTS] sshUser principal principal ...') + parser.set_description( + 'Serves principals as AuthorizedPrincipalsCommand ') + return parser + + def handle_args(self, parser, cfg, options, args): + try: + sshUser = args.pop(0) + principals = ' '.join(args) + except ValueError: + parser.error('Missing argument sshUsers and/or principals.') + + log = logging.getLogger('gitosis.principals') + + if sshUser != "": + log.info('Running serve_principal for user %s', sshUser) + #log.debug('serve_principal: %s', serve_principal(cfg, sshUser, principals)) + serve_principal(cfg, sshUser, principals) + log.info('Done.') diff --git a/gitosis/run_hook.py b/gitosis/run_hook.py index ca35801..52716e8 100644 --- a/gitosis/run_hook.py +++ b/gitosis/run_hook.py @@ -69,10 +69,12 @@ def handle_args(self, parser, cfg, options, args): if git_dir is None: log.error('Must have GIT_DIR set in enviroment') sys.exit(1) + else: + log.debug("GIT_DIR %s".format(git_dir)) if hook == 'post-update': - log.info('Running hook %s', hook) + log.info('Running hook %s'.format(hook)) post_update(cfg, git_dir) log.info('Done.') else: - log.warning('Ignoring unknown hook: %r', hook) + log.warning('Ignoring unknown hook: %r'.format(hook)) diff --git a/gitosis/ssh.py b/gitosis/ssh.py index 37c9fec..33b3f2a 100644 --- a/gitosis/ssh.py +++ b/gitosis/ssh.py @@ -62,6 +62,7 @@ def filterAuthorizedKeys(fp): def writeAuthorizedKeys(path, keydir): tmp = '%s.%d.tmp' % (path, os.getpid()) + log.debug("writeAuthorizedKeys " + str(tmp) ) try: in_ = open(path) except IOError as e: @@ -75,11 +76,13 @@ def writeAuthorizedKeys(path, keydir): try: if in_ is not None: for line in filterAuthorizedKeys(in_): - print >>out, line + #print >>out, line + print(line, file=out) keygen = readKeys(keydir) for line in generateAuthorizedKeys(keygen): - print >>out, line + #print >>out, line + print(line, file=out) os.fsync(out) finally: diff --git a/gitosis/util.py b/gitosis/util.py index f4bf05f..59cd625 100644 --- a/gitosis/util.py +++ b/gitosis/util.py @@ -34,3 +34,17 @@ def getSSHAuthorizedKeysPath(config): except (NoSectionError, NoOptionError): path = os.path.expanduser('~/.ssh/authorized_keys') return path + +def getSSHPrincipalsPath(config): + try: + path = config.get('gitosis', 'ssh-principals-path') + except (NoSectionError, NoOptionError): + path = os.path.expanduser('~/.ssh/principals') + return path + +def getAllowedSSHPrincipals(config): + try: + principals = config.get('gitosis', 'allowedPrincipals') + except (NoSectionError, NoOptionError): + principals = "git" + return principals diff --git a/setup.py b/setup.py index 30eb9a5..4635d87 100755 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ def subdir_contents(path): 'gitosis-serve = gitosis.serve:Main.run', 'gitosis-run-hook = gitosis.run_hook:Main.run', 'gitosis-init = gitosis.init:Main.run', + 'gitosis-authorized-principals = gitosis.principals:Main.run', ], },