aboutsummaryrefslogtreecommitdiff
path: root/gitosis/ssh.py
diff options
context:
space:
mode:
Diffstat (limited to 'gitosis/ssh.py')
-rw-r--r--gitosis/ssh.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/gitosis/ssh.py b/gitosis/ssh.py
new file mode 100644
index 0000000..21f351a
--- /dev/null
+++ b/gitosis/ssh.py
@@ -0,0 +1,104 @@
+import os, errno, re
+
+def readKeys(keydir):
+ """
+ Read SSH public keys from ``keydir/*.pub``
+ """
+ for filename in os.listdir(keydir):
+ if filename.startswith('.'):
+ continue
+ basename, ext = os.path.splitext(filename)
+ if ext != '.pub':
+ continue
+
+ path = os.path.join(keydir, filename)
+ f = file(path)
+ try:
+ line = f.readline()
+ finally:
+ f.close()
+ line = line.rstrip('\n')
+ yield (basename, line)
+
+COMMENT = '### autogenerated by gitosis, DO NOT EDIT'
+
+def generateAuthorizedKeys(keys):
+ TEMPLATE=('command="gitosis-serve %(user)s",no-port-forwarding,'
+ +'no-X11-forwarding,no-agent-forwarding,no-pty %(key)s')
+
+ yield COMMENT
+ for (user, key) in keys:
+ yield TEMPLATE % dict(user=user, key=key)
+
+_COMMAND_RE = re.compile('^command="(/[^ "]+/)?gitosis-serve [^"]+",no-port-forw'
+ +'arding,no-X11-forwarding,no-agent-forwardi'
+ +'ng,no-pty .*')
+
+def filterAuthorizedKeys(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 writeAuthorizedKeys(path, keydir):
+ 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 filterAuthorizedKeys(in_):
+ print >>out, line
+
+ keygen = readKeys(keydir)
+ for line in generateAuthorizedKeys(keygen):
+ print >>out, line
+
+ os.fsync(out)
+ finally:
+ out.close()
+ finally:
+ if in_ is not None:
+ in_.close()
+ os.rename(tmp, path)
+
+def _getParser():
+ import optparse
+ parser = optparse.OptionParser(
+ usage="%prog [--authkeys=FILE] KEYDIR")
+ parser.set_defaults(
+ authkeys=os.path.expanduser('~/.ssh/authorized_keys'),
+ )
+ parser.add_option(
+ "--authkeys",
+ help="path to SSH authorized keys file")
+ return parser
+
+def main():
+ parser = _getParser()
+ (options, args) = parser.parse_args()
+
+ if len(args) != 1:
+ parser.error('Need one argument on the command line.')
+
+ keydir, = args
+
+ writeAuthorizedKeys(
+ path=options.authkeys,
+ keydir=keydir)