added ssh-principals

This commit is contained in:
Jakobus Schürz 2019-07-31 09:46:03 +02:00
parent f7c1a0e219
commit a6c329e7be
3 changed files with 94 additions and 0 deletions

View file

@ -10,6 +10,7 @@ import shutil
from gitosis import repository
from gitosis import ssh
from gitosis import ssh_principals
from gitosis import gitweb
from gitosis import gitdaemon
from gitosis import app
@ -47,6 +48,11 @@ def post_update(cfg, git_dir):
path=authorized_keys,
keydir=os.path.join(export, 'keydir'),
)
principals = util.getSSHPrincipalsPath(config=cfg)
ssh.writePrincipals(
path=principals,
principals=os.path.join(export, 'principals'),
)
class Main(app.App):
def create_parser(self):

81
gitosis/ssh_principals.py Normal file
View file

@ -0,0 +1,81 @@
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:
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)

View file

@ -34,3 +34,10 @@ 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