Compare commits
No commits in common. "master" and "ssh-certificates" have entirely different histories.
master
...
ssh-certif
28 changed files with 169 additions and 242 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -5,5 +5,3 @@
|
||||||
/apidocs
|
/apidocs
|
||||||
/gitosis/test/tmp
|
/gitosis/test/tmp
|
||||||
/.coverage
|
/.coverage
|
||||||
.idea
|
|
||||||
venv
|
|
89
README.rst
89
README.rst
|
@ -24,17 +24,7 @@ more information.
|
||||||
|
|
||||||
You can get ``gitosis`` via ``git`` by saying::
|
You can get ``gitosis`` via ``git`` by saying::
|
||||||
|
|
||||||
This repositories are from jakob@schuerz.at, support python3 and ssh-certificates
|
git clone https://github.com/tv42/gitosis.git
|
||||||
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::
|
And install it via::
|
||||||
|
|
||||||
|
@ -85,12 +75,6 @@ it to running ``gitosis-serve``. Run::
|
||||||
sudo -H -u git gitosis-init <FILENAME.pub
|
sudo -H -u git gitosis-init <FILENAME.pub
|
||||||
# (or just copy-paste the public key when prompted)
|
# (or just copy-paste the public key when prompted)
|
||||||
|
|
||||||
If you want to use ssh-certificates with principals, you need a file with
|
|
||||||
your admin-user in it. Name it adminuser.txt, only one line with your admins
|
|
||||||
username in it and run::
|
|
||||||
|
|
||||||
sudo -H -u git gitosis-init <adminuser.txt
|
|
||||||
|
|
||||||
then just ``git clone git@SERVER:gitosis-admin.git``, and you get a
|
then just ``git clone git@SERVER:gitosis-admin.git``, and you get a
|
||||||
repository with SSH keys as ``keys/USER.pub`` and a ``gitosis.conf``
|
repository with SSH keys as ``keys/USER.pub`` and a ``gitosis.conf``
|
||||||
where you can configure who has access to what.
|
where you can configure who has access to what.
|
||||||
|
@ -206,75 +190,6 @@ Note that this short snippet is not a substitute for reading and
|
||||||
understanding the relevant documentation.
|
understanding the relevant documentation.
|
||||||
|
|
||||||
|
|
||||||
Using ssh-certificates and principals
|
|
||||||
=====================================
|
|
||||||
|
|
||||||
``ssh certificates`` are a new feature of openssh, where you setup your own ssh-CA
|
|
||||||
and you sign all you host- and user-pubkeys.
|
|
||||||
|
|
||||||
If you want to use certificates ans principals, please visit THIS_ and THIS_ website.
|
|
||||||
To find out more about the AuthorizedPrincipalCommand in sshd_config, please consult GITLABS_
|
|
||||||
documentation for it.
|
|
||||||
|
|
||||||
.. _THIS: https://ef.gy/hardening-ssh
|
|
||||||
.. _THIS: https://framkant.org/2017/07/scalable-access-control-using-openssh-certificates/
|
|
||||||
.. _GITLABS: https://docs.gitlab.com/ee/administration/operations/ssh_certificates.html
|
|
||||||
|
|
||||||
To use principals and ssh-certificates with this fork of gitosis, please add this snippet to your sshd_config on your git-server::
|
|
||||||
|
|
||||||
Match User git
|
|
||||||
AuthorizedPrincipalsCommandUser git
|
|
||||||
AuthorizedPrincipalsCommand /usr/local/bin/gitosis-authorized-principals %i
|
|
||||||
|
|
||||||
And for all users except git, use only principal-files::
|
|
||||||
|
|
||||||
Match User !git,*
|
|
||||||
AuthorizedPrincipalsFile /etc/ssh/userprincipals/%u
|
|
||||||
|
|
||||||
|
|
||||||
This will run the command as user "git", which will you have installed, when you serve your gitrepos with gitosis.
|
|
||||||
%i is the key-identity of your certificate, which will you give on your sign-process to the user-certificate.
|
|
||||||
|
|
||||||
Then you need an additional line in your gitosis.conf in the [gitosis]-section::
|
|
||||||
|
|
||||||
[gitosis]
|
|
||||||
...
|
|
||||||
allowedPrincipals = git gitosis-admin
|
|
||||||
|
|
||||||
In the members-line of your gitosis.conf, you have to write down the key-identity (which is passed as %i in you sshd_config). If you are not sure,
|
|
||||||
what the identity is, try::
|
|
||||||
|
|
||||||
ssh-keygen -L -f ~/.ssh/id_rsa-cert.pub
|
|
||||||
|
|
||||||
/home/myusername/.ssh/id_rsa-cert.pub:
|
|
||||||
Type: ssh-rsa-cert-v01@openssh.com user certificate
|
|
||||||
Public key: RSA-CERT SHA256:cjLH4l45G32zOaJBjv8Udnr7bkwHRNB3nAz0a6SCOl0
|
|
||||||
Signing CA: ED25519 SHA256:9bMENs+blen§naslr§BJEN421I5ckbu4mvpnktiHdUs (using ssh-ed25519)
|
|
||||||
Key ID: "myusername"
|
|
||||||
Serial: 4
|
|
||||||
Valid: from 2019-08-02T02:29:00 to 2020-08-01T02:30:20
|
|
||||||
Principals:
|
|
||||||
myusername
|
|
||||||
principal2
|
|
||||||
git
|
|
||||||
gitosis-admin
|
|
||||||
Critical Options: (none)
|
|
||||||
Extensions:
|
|
||||||
permit-X11-forwarding
|
|
||||||
permit-agent-forwarding
|
|
||||||
permit-port-forwarding
|
|
||||||
permit-pty
|
|
||||||
permit-user-rc
|
|
||||||
|
|
||||||
from your principals in the key, only git and gitosis-admin are allowed. You must have at least one of this allowed principals in your key, to get access to your gitosis-served repos.
|
|
||||||
Access is only given, if you have one of the allowed principals in your certificate, and your key ID is listed as member in the repo
|
|
||||||
|
|
||||||
Parallel use of principals/certificates an pubkeys
|
|
||||||
--------------------------------------------------
|
|
||||||
|
|
||||||
It is possible, to use pubkeys in parallel to these principals from certificates. Just as described above. If you have a user, which has no certificate from your ssh-CA, just add his
|
|
||||||
public-sshkey in the keydir. (not tested now)
|
|
||||||
|
|
||||||
|
|
||||||
Contact
|
Contact
|
||||||
=======
|
=======
|
||||||
|
@ -282,7 +197,5 @@ Contact
|
||||||
You can email the author at ``tv@eagain.net``, or hop on
|
You can email the author at ``tv@eagain.net``, or hop on
|
||||||
``irc.freenode.net`` channel ``#git`` and hope for the best.
|
``irc.freenode.net`` channel ``#git`` and hope for the best.
|
||||||
|
|
||||||
For ssh-certificates and principals, please contact wertstoffe@xundeenergie.at
|
|
||||||
|
|
||||||
There will be more, keep an eye on http://eagain.net/ and/or the git
|
There will be more, keep an eye on http://eagain.net/ and/or the git
|
||||||
mailing list.
|
mailing list.
|
||||||
|
|
4
TODO.rst
4
TODO.rst
|
@ -40,9 +40,9 @@
|
||||||
|
|
||||||
- can't trust "~"::
|
- can't trust "~"::
|
||||||
|
|
||||||
[0 tv@musti ~]$ sudo python -c 'import os; print(os.path.expanduser("~"))'
|
[0 tv@musti ~]$ sudo python -c 'import os; print os.path.expanduser("~")'
|
||||||
/home/tv
|
/home/tv
|
||||||
[0 tv@musti ~]$ sudo -H python -c 'import os; print(os.path.expanduser("~"))'
|
[0 tv@musti ~]$ sudo -H python -c 'import os; print os.path.expanduser("~")'
|
||||||
/root
|
/root
|
||||||
|
|
||||||
- command line options
|
- command line options
|
||||||
|
|
|
@ -18,12 +18,6 @@ daemon = no
|
||||||
## Logging level, one of DEBUG, INFO, WARNING, ERROR, CRITICAL
|
## Logging level, one of DEBUG, INFO, WARNING, ERROR, CRITICAL
|
||||||
loglevel = DEBUG
|
loglevel = DEBUG
|
||||||
|
|
||||||
## If you use ssh-certificates with principals, you need this option
|
|
||||||
## If commented, allowedPrincipals defaults to "git". At least, your certificates of the users
|
|
||||||
## which want to use this repos, must have at least "git" as principal in their
|
|
||||||
## certificates
|
|
||||||
allowedPrincipals = git
|
|
||||||
|
|
||||||
[group quux]
|
[group quux]
|
||||||
members = jdoe wsmith @anothergroup
|
members = jdoe wsmith @anothergroup
|
||||||
writable = foo bar baz/thud
|
writable = foo bar baz/thud
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import os, logging
|
import os, logging
|
||||||
from configparser import NoSectionError, NoOptionError
|
from ConfigParser import NoSectionError, NoOptionError
|
||||||
|
|
||||||
from gitosis import group
|
from gitosis import group
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import sys
|
||||||
import logging
|
import logging
|
||||||
import optparse
|
import optparse
|
||||||
import errno
|
import errno
|
||||||
import configparser
|
import ConfigParser
|
||||||
|
|
||||||
log = logging.getLogger('gitosis.app')
|
log = logging.getLogger('gitosis.app')
|
||||||
|
|
||||||
|
@ -31,14 +31,14 @@ class App(object):
|
||||||
cfg = self.create_config(options)
|
cfg = self.create_config(options)
|
||||||
try:
|
try:
|
||||||
self.read_config(options, cfg)
|
self.read_config(options, cfg)
|
||||||
except CannotReadConfigError as e:
|
except CannotReadConfigError, e:
|
||||||
log.error(str(e))
|
log.error(str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.setup_logging(cfg)
|
self.setup_logging(cfg)
|
||||||
self.handle_args(parser, cfg, options, args)
|
self.handle_args(parser, cfg, options, args)
|
||||||
|
|
||||||
def setup_basic_logging(self):
|
def setup_basic_logging(self):
|
||||||
logging.basicConfig(filename='/home/git/gitosis.log')
|
logging.basicConfig(filename='gitosis.log', level=10)
|
||||||
|
|
||||||
def create_parser(self):
|
def create_parser(self):
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
|
@ -53,13 +53,13 @@ class App(object):
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def create_config(self, options):
|
def create_config(self, options):
|
||||||
cfg = configparser.RawConfigParser()
|
cfg = ConfigParser.RawConfigParser()
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
def read_config(self, options, cfg):
|
def read_config(self, options, cfg):
|
||||||
try:
|
try:
|
||||||
conffile = open(options.config)
|
conffile = file(options.config)
|
||||||
except (IOError, OSError) as e:
|
except (IOError, OSError), e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
# special case this because gitosis-init wants to
|
# special case this because gitosis-init wants to
|
||||||
# ignore this particular error case
|
# ignore this particular error case
|
||||||
|
@ -74,12 +74,12 @@ class App(object):
|
||||||
def setup_logging(self, cfg):
|
def setup_logging(self, cfg):
|
||||||
try:
|
try:
|
||||||
loglevel = cfg.get('gitosis', 'loglevel')
|
loglevel = cfg.get('gitosis', 'loglevel')
|
||||||
except (configparser.NoSectionError,
|
except (ConfigParser.NoSectionError,
|
||||||
configparser.NoOptionError):
|
ConfigParser.NoOptionError):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
symbolic = logging._nameToLevel[loglevel]
|
symbolic = logging._levelNames[loglevel]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.warning(
|
log.warning(
|
||||||
'Ignored invalid loglevel configuration: %r',
|
'Ignored invalid loglevel configuration: %r',
|
||||||
|
|
|
@ -2,7 +2,7 @@ import errno
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from configparser import NoSectionError, NoOptionError
|
from ConfigParser import NoSectionError, NoOptionError
|
||||||
|
|
||||||
log = logging.getLogger('gitosis.gitdaemon')
|
log = logging.getLogger('gitosis.gitdaemon')
|
||||||
|
|
||||||
|
@ -14,13 +14,13 @@ def export_ok_path(repopath):
|
||||||
|
|
||||||
def allow_export(repopath):
|
def allow_export(repopath):
|
||||||
p = export_ok_path(repopath)
|
p = export_ok_path(repopath)
|
||||||
open(p, 'a').close()
|
file(p, 'a').close()
|
||||||
|
|
||||||
def deny_export(repopath):
|
def deny_export(repopath):
|
||||||
p = export_ok_path(repopath)
|
p = export_ok_path(repopath)
|
||||||
try:
|
try:
|
||||||
os.unlink(p)
|
os.unlink(p)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -27,7 +27,7 @@ To plug this into ``gitweb``, you have two choices.
|
||||||
|
|
||||||
import os, urllib, logging
|
import os, urllib, logging
|
||||||
|
|
||||||
from configparser import NoSectionError, NoOptionError
|
from ConfigParser import NoSectionError, NoOptionError
|
||||||
|
|
||||||
from gitosis import util
|
from gitosis import util
|
||||||
|
|
||||||
|
@ -91,9 +91,8 @@ def generate_project_list_fp(config, fp):
|
||||||
else:
|
else:
|
||||||
response.append(owner)
|
response.append(owner)
|
||||||
|
|
||||||
line = ' '.join([urllib.parse.quote_plus(s) for s in response])
|
line = ' '.join([urllib.quote_plus(s) for s in response])
|
||||||
#print >>fp, line
|
print >>fp, line
|
||||||
print(line, end="", file=fp)
|
|
||||||
|
|
||||||
def generate_project_list(config, path):
|
def generate_project_list(config, path):
|
||||||
"""
|
"""
|
||||||
|
@ -107,7 +106,7 @@ def generate_project_list(config, path):
|
||||||
"""
|
"""
|
||||||
tmp = '%s.%d.tmp' % (path, os.getpid())
|
tmp = '%s.%d.tmp' % (path, os.getpid())
|
||||||
|
|
||||||
f = open(tmp, 'w')
|
f = file(tmp, 'w')
|
||||||
try:
|
try:
|
||||||
generate_project_list_fp(config=config, fp=f)
|
generate_project_list_fp(config=config, fp=f)
|
||||||
finally:
|
finally:
|
||||||
|
@ -158,10 +157,9 @@ def set_descriptions(config):
|
||||||
'description',
|
'description',
|
||||||
)
|
)
|
||||||
tmp = '%s.%d.tmp' % (path, os.getpid())
|
tmp = '%s.%d.tmp' % (path, os.getpid())
|
||||||
f = open(tmp, 'w')
|
f = file(tmp, 'w')
|
||||||
try:
|
try:
|
||||||
#print >>f, description
|
print >>f, description
|
||||||
print(description, end="", file=f)
|
|
||||||
finally:
|
finally:
|
||||||
f.close()
|
f.close()
|
||||||
os.rename(tmp, path)
|
os.rename(tmp, path)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
from configparser import NoSectionError, NoOptionError
|
from ConfigParser import NoSectionError, NoOptionError
|
||||||
|
|
||||||
def _getMembership(config, user, seen):
|
def _getMembership(config, user, seen):
|
||||||
log = logging.getLogger('gitosis.group.getMembership')
|
log = logging.getLogger('gitosis.group.getMembership')
|
||||||
|
|
|
@ -9,8 +9,8 @@ import sys
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from pkg_resources import resource_filename
|
from pkg_resources import resource_filename
|
||||||
from io import StringIO
|
from cStringIO import StringIO
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
from gitosis import repository
|
from gitosis import repository
|
||||||
from gitosis import run_hook
|
from gitosis import run_hook
|
||||||
|
@ -68,7 +68,7 @@ def symlink_config(git_dir):
|
||||||
tmp = '%s.%d.tmp' % (dst, os.getpid())
|
tmp = '%s.%d.tmp' % (dst, os.getpid())
|
||||||
try:
|
try:
|
||||||
os.unlink(tmp)
|
os.unlink(tmp)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -94,18 +94,15 @@ def init_admin_repository(
|
||||||
|
|
||||||
# can't rely on setuptools and all kinds of distro packaging to
|
# can't rely on setuptools and all kinds of distro packaging to
|
||||||
# have kept our templates executable, it seems
|
# have kept our templates executable, it seems
|
||||||
os.chmod(os.path.join(git_dir, 'hooks', 'post-update'), 0o755)
|
os.chmod(os.path.join(git_dir, 'hooks', 'post-update'), 0755)
|
||||||
|
|
||||||
if not repository.has_initial_commit(git_dir):
|
if not repository.has_initial_commit(git_dir):
|
||||||
log.info('Making initial commit...')
|
log.info('Making initial commit...')
|
||||||
# ConfigParser does not guarantee order, so jump through hoops
|
# ConfigParser does not guarantee order, so jump through hoops
|
||||||
# to make sure [gitosis] is first
|
# to make sure [gitosis] is first
|
||||||
cfg_file = StringIO()
|
cfg_file = StringIO()
|
||||||
print('[gitosis]', file=cfg_file)
|
print >>cfg_file, '[gitosis]'
|
||||||
#print('', end="", file=cfg_file)
|
print >>cfg_file
|
||||||
|
|
||||||
#print >>cfg_file, '[gitosis]'
|
|
||||||
#print >>cfg_file
|
|
||||||
cfg = RawConfigParser()
|
cfg = RawConfigParser()
|
||||||
cfg.add_section('group gitosis-admin')
|
cfg.add_section('group gitosis-admin')
|
||||||
cfg.set('group gitosis-admin', 'members', user)
|
cfg.set('group gitosis-admin', 'members', user)
|
||||||
|
@ -136,7 +133,7 @@ class Main(app.App):
|
||||||
def handle_args(self, parser, cfg, options, args):
|
def handle_args(self, parser, cfg, options, args):
|
||||||
super(Main, self).handle_args(parser, cfg, options, args)
|
super(Main, self).handle_args(parser, cfg, options, args)
|
||||||
|
|
||||||
os.umask(0o022)
|
os.umask(0022)
|
||||||
|
|
||||||
log.info('Reading SSH public key...')
|
log.info('Reading SSH public key...')
|
||||||
pubkey = read_ssh_pubkey()
|
pubkey = read_ssh_pubkey()
|
||||||
|
@ -161,7 +158,7 @@ class Main(app.App):
|
||||||
user=user,
|
user=user,
|
||||||
)
|
)
|
||||||
log.info('Running post-update hook...')
|
log.info('Running post-update hook...')
|
||||||
util.mkdir(os.path.expanduser('~/.ssh'), 0o700)
|
util.mkdir(os.path.expanduser('~/.ssh'), 0700)
|
||||||
run_hook.post_update(cfg=cfg, git_dir=admin_repository)
|
run_hook.post_update(cfg=cfg, git_dir=admin_repository)
|
||||||
log.info('Symlinking ~/.gitosis.conf to repository...')
|
log.info('Symlinking ~/.gitosis.conf to repository...')
|
||||||
symlink_config(git_dir=admin_repository)
|
symlink_config(git_dir=admin_repository)
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
"""
|
|
||||||
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.')
|
|
|
@ -36,7 +36,7 @@ def init(
|
||||||
if _git is None:
|
if _git is None:
|
||||||
_git = 'git'
|
_git = 'git'
|
||||||
|
|
||||||
util.mkdir(path, 0o750)
|
util.mkdir(path, 0750)
|
||||||
args = [
|
args = [
|
||||||
_git,
|
_git,
|
||||||
'--git-dir=.',
|
'--git-dir=.',
|
||||||
|
@ -131,7 +131,7 @@ class GitCheckoutIndexError(GitExportError):
|
||||||
def export(git_dir, path):
|
def export(git_dir, path):
|
||||||
try:
|
try:
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.EEXIST:
|
if e.errno == errno.EEXIST:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -185,7 +185,7 @@ def has_initial_commit(git_dir):
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
close_fds=True,
|
close_fds=True,
|
||||||
)
|
)
|
||||||
got = child.stdout.read().decode('utf-8')
|
got = child.stdout.read()
|
||||||
returncode = child.wait()
|
returncode = child.wait()
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
raise GitRevParseError('exit status %d' % returncode)
|
raise GitRevParseError('exit status %d' % returncode)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import shutil
|
||||||
|
|
||||||
from gitosis import repository
|
from gitosis import repository
|
||||||
from gitosis import ssh
|
from gitosis import ssh
|
||||||
|
from gitosis import ssh_principals
|
||||||
from gitosis import gitweb
|
from gitosis import gitweb
|
||||||
from gitosis import gitdaemon
|
from gitosis import gitdaemon
|
||||||
from gitosis import app
|
from gitosis import app
|
||||||
|
@ -19,7 +20,7 @@ def post_update(cfg, git_dir):
|
||||||
export = os.path.join(git_dir, 'gitosis-export')
|
export = os.path.join(git_dir, 'gitosis-export')
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(export)
|
shutil.rmtree(export)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -47,6 +48,11 @@ def post_update(cfg, git_dir):
|
||||||
path=authorized_keys,
|
path=authorized_keys,
|
||||||
keydir=os.path.join(export, 'keydir'),
|
keydir=os.path.join(export, 'keydir'),
|
||||||
)
|
)
|
||||||
|
principals = util.getSSHPrincipalsPath(config=cfg)
|
||||||
|
ssh_principals.writePrincipals(
|
||||||
|
path=principals,
|
||||||
|
principals=os.path.join(export, 'keydir/principals'),
|
||||||
|
)
|
||||||
|
|
||||||
class Main(app.App):
|
class Main(app.App):
|
||||||
def create_parser(self):
|
def create_parser(self):
|
||||||
|
@ -63,18 +69,16 @@ class Main(app.App):
|
||||||
parser.error('Missing argument HOOK.')
|
parser.error('Missing argument HOOK.')
|
||||||
|
|
||||||
log = logging.getLogger('gitosis.run_hook')
|
log = logging.getLogger('gitosis.run_hook')
|
||||||
os.umask(0o022)
|
os.umask(0022)
|
||||||
|
|
||||||
git_dir = os.environ.get('GIT_DIR')
|
git_dir = os.environ.get('GIT_DIR')
|
||||||
if git_dir is None:
|
if git_dir is None:
|
||||||
log.error('Must have GIT_DIR set in enviroment')
|
log.error('Must have GIT_DIR set in enviroment')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
|
||||||
log.debug("GIT_DIR %s".format(git_dir))
|
|
||||||
|
|
||||||
if hook == 'post-update':
|
if hook == 'post-update':
|
||||||
log.info('Running hook %s'.format(hook))
|
log.info('Running hook %s', hook)
|
||||||
post_update(cfg, git_dir)
|
post_update(cfg, git_dir)
|
||||||
log.info('Done.')
|
log.info('Done.')
|
||||||
else:
|
else:
|
||||||
log.warning('Ignoring unknown hook: %r'.format(hook))
|
log.warning('Ignoring unknown hook: %r', hook)
|
||||||
|
|
|
@ -141,7 +141,7 @@ def serve(
|
||||||
p = topdir
|
p = topdir
|
||||||
for segment in repopath.split(os.sep)[:-1]:
|
for segment in repopath.split(os.sep)[:-1]:
|
||||||
p = os.path.join(p, segment)
|
p = os.path.join(p, segment)
|
||||||
util.mkdir(p, 0o750)
|
util.mkdir(p, 0750)
|
||||||
|
|
||||||
repository.init(path=fullpath)
|
repository.init(path=fullpath)
|
||||||
gitweb.set_descriptions(
|
gitweb.set_descriptions(
|
||||||
|
@ -178,7 +178,7 @@ class Main(app.App):
|
||||||
parser.error('Missing argument USER.')
|
parser.error('Missing argument USER.')
|
||||||
|
|
||||||
main_log = logging.getLogger('gitosis.serve.main')
|
main_log = logging.getLogger('gitosis.serve.main')
|
||||||
os.umask(0o022)
|
os.umask(0022)
|
||||||
|
|
||||||
cmd = os.environ.get('SSH_ORIGINAL_COMMAND', None)
|
cmd = os.environ.get('SSH_ORIGINAL_COMMAND', None)
|
||||||
if cmd is None:
|
if cmd is None:
|
||||||
|
@ -197,7 +197,7 @@ class Main(app.App):
|
||||||
user=user,
|
user=user,
|
||||||
command=cmd,
|
command=cmd,
|
||||||
)
|
)
|
||||||
except ServingError as e:
|
except ServingError, e:
|
||||||
main_log.error('%s', e)
|
main_log.error('%s', e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ def readKeys(keydir):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
path = os.path.join(keydir, filename)
|
path = os.path.join(keydir, filename)
|
||||||
f = open(path)
|
f = file(path)
|
||||||
for line in f:
|
for line in f:
|
||||||
line = line.rstrip('\n')
|
line = line.rstrip('\n')
|
||||||
yield (basename, line)
|
yield (basename, line)
|
||||||
|
@ -62,27 +62,24 @@ def filterAuthorizedKeys(fp):
|
||||||
|
|
||||||
def writeAuthorizedKeys(path, keydir):
|
def writeAuthorizedKeys(path, keydir):
|
||||||
tmp = '%s.%d.tmp' % (path, os.getpid())
|
tmp = '%s.%d.tmp' % (path, os.getpid())
|
||||||
log.debug("writeAuthorizedKeys " + str(tmp) )
|
|
||||||
try:
|
try:
|
||||||
in_ = open(path)
|
in_ = file(path)
|
||||||
except IOError as e:
|
except IOError, e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
in_ = None
|
in_ = None
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
try:
|
try:
|
||||||
out = open(tmp, 'w')
|
out = file(tmp, 'w')
|
||||||
try:
|
try:
|
||||||
if in_ is not None:
|
if in_ is not None:
|
||||||
for line in filterAuthorizedKeys(in_):
|
for line in filterAuthorizedKeys(in_):
|
||||||
#print >>out, line
|
print >>out, line
|
||||||
print(line, file=out)
|
|
||||||
|
|
||||||
keygen = readKeys(keydir)
|
keygen = readKeys(keydir)
|
||||||
for line in generateAuthorizedKeys(keygen):
|
for line in generateAuthorizedKeys(keygen):
|
||||||
#print >>out, line
|
print >>out, line
|
||||||
print(line, file=out)
|
|
||||||
|
|
||||||
os.fsync(out)
|
os.fsync(out)
|
||||||
finally:
|
finally:
|
||||||
|
|
82
gitosis/ssh_principals.py
Normal file
82
gitosis/ssh_principals.py
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
import os, errno, re
|
||||||
|
import logging
|
||||||
|
|
||||||
|
log = logging.getLogger('gitosis.ssh')
|
||||||
|
|
||||||
|
_ACCEPTABLE_USER_RE = re.compile(r'^[a-zA-Z][a-zA-Z0-9_.-]*(@[a-zA-Z][a-zA-Z0-9.-]*)?$')
|
||||||
|
|
||||||
|
def isSafeUsername(user):
|
||||||
|
match = _ACCEPTABLE_USER_RE.match(user)
|
||||||
|
return (match is not None)
|
||||||
|
|
||||||
|
def readPrincipals(principals):
|
||||||
|
"""
|
||||||
|
Read SSH principals from ``principals``
|
||||||
|
"""
|
||||||
|
f = file(principals)
|
||||||
|
for line in f:
|
||||||
|
if not isSafeUsername(line):
|
||||||
|
log.warn('Unsafe SSH username in principalfile: %r', line)
|
||||||
|
continue
|
||||||
|
line = line.rstrip('\n')
|
||||||
|
yield (line)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
COMMENT = '### autogenerated by gitosis, DO NOT EDIT'
|
||||||
|
|
||||||
|
def generatePrincipals(keys):
|
||||||
|
TEMPLATE=('command="gitosis-serve %(user)s",no-port-forwarding,'
|
||||||
|
+'no-X11-forwarding,no-agent-forwarding,no-pty %(user)s')
|
||||||
|
|
||||||
|
yield COMMENT
|
||||||
|
for (user) in keys:
|
||||||
|
log.debug(TEMPLATE % dict(user=user))
|
||||||
|
yield TEMPLATE % dict(user=user)
|
||||||
|
|
||||||
|
_COMMAND_RE = re.compile('^command="(/[^ "]+/)?gitosis-serve [^"]+",no-port-forw'
|
||||||
|
+'arding,no-X11-forwarding,no-agent-forwardi'
|
||||||
|
+'ng,no-pty .*')
|
||||||
|
|
||||||
|
def filterPrincipals(fp):
|
||||||
|
"""
|
||||||
|
Read lines from ``fp``, filter out autogenerated ones.
|
||||||
|
|
||||||
|
Note removes newlines.
|
||||||
|
"""
|
||||||
|
|
||||||
|
for line in fp:
|
||||||
|
line = line.rstrip('\n')
|
||||||
|
if line == COMMENT:
|
||||||
|
continue
|
||||||
|
if _COMMAND_RE.match(line):
|
||||||
|
continue
|
||||||
|
yield line
|
||||||
|
|
||||||
|
def writePrincipals(path, principals):
|
||||||
|
tmp = '%s.%d.tmp' % (path, os.getpid())
|
||||||
|
try:
|
||||||
|
in_ = file(path)
|
||||||
|
except IOError, e:
|
||||||
|
if e.errno == errno.ENOENT:
|
||||||
|
in_ = None
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
out = file(tmp, 'w')
|
||||||
|
try:
|
||||||
|
if in_ is not None:
|
||||||
|
for line in filterPrincipals(in_):
|
||||||
|
print >>out, line
|
||||||
|
|
||||||
|
keygen = readPrincipals(principals)
|
||||||
|
for line in generatePrincipals(keygen):
|
||||||
|
print >>out, line
|
||||||
|
|
||||||
|
os.fsync(out)
|
||||||
|
finally:
|
||||||
|
out.close()
|
||||||
|
finally:
|
||||||
|
if in_ is not None:
|
||||||
|
in_.close()
|
||||||
|
os.rename(tmp, path)
|
|
@ -1,7 +1,7 @@
|
||||||
from nose.tools import eq_ as eq
|
from nose.tools import eq_ as eq
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
from gitosis import access
|
from gitosis import access
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from nose.tools import eq_ as eq
|
from nose.tools import eq_ as eq
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
from gitosis import gitdaemon
|
from gitosis import gitdaemon
|
||||||
from gitosis.test.util import maketemp, writeFile
|
from gitosis.test.util import maketemp, writeFile
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from nose.tools import eq_ as eq
|
from nose.tools import eq_ as eq
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
from io import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
from gitosis import gitweb
|
from gitosis import gitweb
|
||||||
from gitosis.test.util import mkdir, maketemp, readFile, writeFile
|
from gitosis.test.util import mkdir, maketemp, readFile, writeFile
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from nose.tools import eq_ as eq, assert_raises
|
from nose.tools import eq_ as eq, assert_raises
|
||||||
|
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
from gitosis import group
|
from gitosis import group
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ from nose.tools import eq_ as eq
|
||||||
from gitosis.test.util import assert_raises, maketemp
|
from gitosis.test.util import assert_raises, maketemp
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
from gitosis import init
|
from gitosis import init
|
||||||
from gitosis import repository
|
from gitosis import repository
|
||||||
|
@ -113,7 +113,7 @@ def test_init_admin_repository():
|
||||||
'hooks',
|
'hooks',
|
||||||
'post-update',
|
'post-update',
|
||||||
)
|
)
|
||||||
util.check_mode(hook, 0o755, is_file=True)
|
util.check_mode(hook, 0755, is_file=True)
|
||||||
got = util.readFile(hook).splitlines()
|
got = util.readFile(hook).splitlines()
|
||||||
assert 'gitosis-run-hook post-update' in got
|
assert 'gitosis-run-hook post-update' in got
|
||||||
export_dir = os.path.join(tmp, 'export')
|
export_dir = os.path.join(tmp, 'export')
|
||||||
|
|
|
@ -23,17 +23,17 @@ def test_init_simple():
|
||||||
tmp = maketemp()
|
tmp = maketemp()
|
||||||
path = os.path.join(tmp, 'repo.git')
|
path = os.path.join(tmp, 'repo.git')
|
||||||
repository.init(path)
|
repository.init(path)
|
||||||
check_mode(path, 0o750, is_dir=True)
|
check_mode(path, 0750, is_dir=True)
|
||||||
check_bare(path)
|
check_bare(path)
|
||||||
|
|
||||||
def test_init_exist_dir():
|
def test_init_exist_dir():
|
||||||
tmp = maketemp()
|
tmp = maketemp()
|
||||||
path = os.path.join(tmp, 'repo.git')
|
path = os.path.join(tmp, 'repo.git')
|
||||||
mkdir(path, 0o710)
|
mkdir(path, 0710)
|
||||||
check_mode(path, 0o710, is_dir=True)
|
check_mode(path, 0710, is_dir=True)
|
||||||
repository.init(path)
|
repository.init(path)
|
||||||
# my weird access mode is preserved
|
# my weird access mode is preserved
|
||||||
check_mode(path, 0o710, is_dir=True)
|
check_mode(path, 0710, is_dir=True)
|
||||||
check_bare(path)
|
check_bare(path)
|
||||||
|
|
||||||
def test_init_exist_git():
|
def test_init_exist_git():
|
||||||
|
@ -41,7 +41,7 @@ def test_init_exist_git():
|
||||||
path = os.path.join(tmp, 'repo.git')
|
path = os.path.join(tmp, 'repo.git')
|
||||||
repository.init(path)
|
repository.init(path)
|
||||||
repository.init(path)
|
repository.init(path)
|
||||||
check_mode(path, 0o750, is_dir=True)
|
check_mode(path, 0750, is_dir=True)
|
||||||
check_bare(path)
|
check_bare(path)
|
||||||
|
|
||||||
def test_init_templates():
|
def test_init_templates():
|
||||||
|
@ -53,7 +53,7 @@ def test_init_templates():
|
||||||
)
|
)
|
||||||
|
|
||||||
# for reproducibility
|
# for reproducibility
|
||||||
os.umask(0o022)
|
os.umask(0022)
|
||||||
|
|
||||||
repository.init(path, template=templatedir)
|
repository.init(path, template=templatedir)
|
||||||
repository.init(path)
|
repository.init(path)
|
||||||
|
@ -61,7 +61,7 @@ def test_init_templates():
|
||||||
eq(got, 'i should show up\n')
|
eq(got, 'i should show up\n')
|
||||||
check_mode(
|
check_mode(
|
||||||
os.path.join(path, 'hooks', 'post-update'),
|
os.path.join(path, 'hooks', 'post-update'),
|
||||||
0o755,
|
0755,
|
||||||
is_file=True,
|
is_file=True,
|
||||||
)
|
)
|
||||||
got = readFile(os.path.join(path, 'hooks', 'post-update'))
|
got = readFile(os.path.join(path, 'hooks', 'post-update'))
|
||||||
|
@ -91,7 +91,7 @@ PATH="${PATH#*:}"
|
||||||
|
|
||||||
exec git "$@"
|
exec git "$@"
|
||||||
''')
|
''')
|
||||||
os.chmod(mockgit, 0o755)
|
os.chmod(mockgit, 0755)
|
||||||
magic_cookie = '%d' % random.randint(1, 100000)
|
magic_cookie = '%d' % random.randint(1, 100000)
|
||||||
good_path = os.environ['PATH']
|
good_path = os.environ['PATH']
|
||||||
try:
|
try:
|
||||||
|
@ -130,7 +130,7 @@ PATH="${PATH#*:}"
|
||||||
|
|
||||||
exec git "$@"
|
exec git "$@"
|
||||||
''')
|
''')
|
||||||
os.chmod(mockgit, 0o755)
|
os.chmod(mockgit, 0755)
|
||||||
magic_cookie = '%d' % random.randint(1, 100000)
|
magic_cookie = '%d' % random.randint(1, 100000)
|
||||||
good_path = os.environ['PATH']
|
good_path = os.environ['PATH']
|
||||||
try:
|
try:
|
||||||
|
@ -226,7 +226,7 @@ PATH="${PATH#*:}"
|
||||||
|
|
||||||
exec git "$@"
|
exec git "$@"
|
||||||
''')
|
''')
|
||||||
os.chmod(mockgit, 0o755)
|
os.chmod(mockgit, 0755)
|
||||||
repository.init(path=git_dir)
|
repository.init(path=git_dir)
|
||||||
repository.fast_import(
|
repository.fast_import(
|
||||||
git_dir=git_dir,
|
git_dir=git_dir,
|
||||||
|
@ -301,7 +301,7 @@ PATH="${PATH#*:}"
|
||||||
|
|
||||||
exec git "$@"
|
exec git "$@"
|
||||||
''')
|
''')
|
||||||
os.chmod(mockgit, 0o755)
|
os.chmod(mockgit, 0755)
|
||||||
repository.init(path=tmp)
|
repository.init(path=tmp)
|
||||||
repository.fast_import(
|
repository.fast_import(
|
||||||
git_dir=tmp,
|
git_dir=tmp,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from nose.tools import eq_ as eq
|
from nose.tools import eq_ as eq
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
from io import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
from gitosis import init, repository, run_hook
|
from gitosis import init, repository, run_hook
|
||||||
from gitosis.test.util import maketemp, readFile
|
from gitosis.test.util import maketemp, readFile
|
||||||
|
|
|
@ -3,8 +3,8 @@ from gitosis.test.util import assert_raises
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from io import StringIO
|
from cStringIO import StringIO
|
||||||
from configparser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
from gitosis import serve
|
from gitosis import serve
|
||||||
from gitosis import repository
|
from gitosis import repository
|
||||||
|
@ -354,7 +354,7 @@ def test_push_inits_subdir_parent_missing():
|
||||||
)
|
)
|
||||||
eq(os.listdir(repositories), ['foo'])
|
eq(os.listdir(repositories), ['foo'])
|
||||||
foo = os.path.join(repositories, 'foo')
|
foo = os.path.join(repositories, 'foo')
|
||||||
util.check_mode(foo, 0o750, is_dir=True)
|
util.check_mode(foo, 0750, is_dir=True)
|
||||||
eq(os.listdir(foo), ['bar.git'])
|
eq(os.listdir(foo), ['bar.git'])
|
||||||
assert os.path.isfile(os.path.join(repositories, 'foo', 'bar.git', 'HEAD'))
|
assert os.path.isfile(os.path.join(repositories, 'foo', 'bar.git', 'HEAD'))
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ def test_push_inits_subdir_parent_exists():
|
||||||
os.mkdir(repositories)
|
os.mkdir(repositories)
|
||||||
foo = os.path.join(repositories, 'foo')
|
foo = os.path.join(repositories, 'foo')
|
||||||
# silly mode on purpose; not to be touched
|
# silly mode on purpose; not to be touched
|
||||||
os.mkdir(foo, 0o751)
|
os.mkdir(foo, 0751)
|
||||||
cfg.set('gitosis', 'repositories', repositories)
|
cfg.set('gitosis', 'repositories', repositories)
|
||||||
generated = os.path.join(tmp, 'generated')
|
generated = os.path.join(tmp, 'generated')
|
||||||
os.mkdir(generated)
|
os.mkdir(generated)
|
||||||
|
@ -380,7 +380,7 @@ def test_push_inits_subdir_parent_exists():
|
||||||
command="git-receive-pack 'foo/bar.git'",
|
command="git-receive-pack 'foo/bar.git'",
|
||||||
)
|
)
|
||||||
eq(os.listdir(repositories), ['foo'])
|
eq(os.listdir(repositories), ['foo'])
|
||||||
util.check_mode(foo, 0o751, is_dir=True)
|
util.check_mode(foo, 0751, is_dir=True)
|
||||||
eq(os.listdir(foo), ['bar.git'])
|
eq(os.listdir(foo), ['bar.git'])
|
||||||
assert os.path.isfile(os.path.join(repositories, 'foo', 'bar.git', 'HEAD'))
|
assert os.path.isfile(os.path.join(repositories, 'foo', 'bar.git', 'HEAD'))
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from nose.tools import eq_ as eq, assert_raises
|
from nose.tools import eq_ as eq, assert_raises
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from io import StringIO
|
from cStringIO import StringIO
|
||||||
|
|
||||||
from gitosis import ssh
|
from gitosis import ssh
|
||||||
from gitosis.test.util import mkdir, maketemp, writeFile, readFile
|
from gitosis.test.util import mkdir, maketemp, writeFile, readFile
|
||||||
|
@ -171,7 +171,7 @@ class WriteAuthorizedKeys_Test(object):
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
tmp = maketemp()
|
tmp = maketemp()
|
||||||
path = os.path.join(tmp, 'authorized_keys')
|
path = os.path.join(tmp, 'authorized_keys')
|
||||||
f = open(path, 'w')
|
f = file(path, 'w')
|
||||||
try:
|
try:
|
||||||
f.write('''\
|
f.write('''\
|
||||||
# foo
|
# foo
|
||||||
|
|
|
@ -9,7 +9,7 @@ import sys
|
||||||
def mkdir(*a, **kw):
|
def mkdir(*a, **kw):
|
||||||
try:
|
try:
|
||||||
os.mkdir(*a, **kw)
|
os.mkdir(*a, **kw)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.EEXIST:
|
if e.errno == errno.EEXIST:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -27,7 +27,7 @@ def maketemp():
|
||||||
tmp = os.path.join(tmp, name)
|
tmp = os.path.join(tmp, name)
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(tmp)
|
shutil.rmtree(tmp)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.ENOENT:
|
if e.errno == errno.ENOENT:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -37,7 +37,7 @@ def maketemp():
|
||||||
|
|
||||||
def writeFile(path, content):
|
def writeFile(path, content):
|
||||||
tmp = '%s.tmp' % path
|
tmp = '%s.tmp' % path
|
||||||
f = open(tmp, 'w')
|
f = file(tmp, 'w')
|
||||||
try:
|
try:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
finally:
|
finally:
|
||||||
|
@ -45,7 +45,7 @@ def writeFile(path, content):
|
||||||
os.rename(tmp, path)
|
os.rename(tmp, path)
|
||||||
|
|
||||||
def readFile(path):
|
def readFile(path):
|
||||||
f = open(path)
|
f = file(path)
|
||||||
try:
|
try:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
finally:
|
finally:
|
||||||
|
@ -58,7 +58,7 @@ def assert_raises(excClass, callableObj, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
callableObj(*args, **kwargs)
|
callableObj(*args, **kwargs)
|
||||||
except excClass as e:
|
except excClass, e:
|
||||||
return e
|
return e
|
||||||
else:
|
else:
|
||||||
if hasattr(excClass,'__name__'): excName = excClass.__name__
|
if hasattr(excClass,'__name__'): excName = excClass.__name__
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import errno
|
import errno
|
||||||
import os
|
import os
|
||||||
from configparser import NoSectionError, NoOptionError
|
from ConfigParser import NoSectionError, NoOptionError
|
||||||
|
|
||||||
def mkdir(*a, **kw):
|
def mkdir(*a, **kw):
|
||||||
try:
|
try:
|
||||||
os.mkdir(*a, **kw)
|
os.mkdir(*a, **kw)
|
||||||
except OSError as e:
|
except OSError, e:
|
||||||
if e.errno == errno.EEXIST:
|
if e.errno == errno.EEXIST:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
@ -41,10 +41,3 @@ def getSSHPrincipalsPath(config):
|
||||||
except (NoSectionError, NoOptionError):
|
except (NoSectionError, NoOptionError):
|
||||||
path = os.path.expanduser('~/.ssh/principals')
|
path = os.path.expanduser('~/.ssh/principals')
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def getAllowedSSHPrincipals(config):
|
|
||||||
try:
|
|
||||||
principals = config.get('gitosis', 'allowedPrincipals')
|
|
||||||
except (NoSectionError, NoOptionError):
|
|
||||||
principals = "git"
|
|
||||||
return principals
|
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -45,7 +45,6 @@ arbitrary commands.
|
||||||
'gitosis-serve = gitosis.serve:Main.run',
|
'gitosis-serve = gitosis.serve:Main.run',
|
||||||
'gitosis-run-hook = gitosis.run_hook:Main.run',
|
'gitosis-run-hook = gitosis.run_hook:Main.run',
|
||||||
'gitosis-init = gitosis.init:Main.run',
|
'gitosis-init = gitosis.init:Main.run',
|
||||||
'gitosis-authorized-principals = gitosis.principals:Main.run',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue