New system. No breaking in, just putting files in /etc/mercurial-server
authorPaul Crowley <paul@lshift.net>
Thu, 19 Feb 2009 17:51:06 +0000
changeset 39 f5055ce263c7
parent 38 f1ee930c4ba8
child 40 abbb822779da
New system. No breaking in, just putting files in /etc/mercurial-server
install
setup
src/access.py
src/do-refresh-auth
src/hg-ssh
src/init/break-in/as-if-by-ssh
src/init/break-in/break-in
src/init/break-in/create-breakin-repository
src/init/break-in/do-breakin
src/init/break-in/ssh-replacement
src/init/conf/access.conf
src/init/conf/hg-ssh-wrapper
src/init/conf/refresh-auth
src/init/hgadmin-hgrc
src/refresh-auth
src/ruleset.py
--- a/install	Thu Feb 19 16:36:41 2009 +0000
+++ b/install	Thu Feb 19 17:51:06 2009 +0000
@@ -4,22 +4,22 @@
 
 install -o root -g root -d /usr/local/lib/mercurial-server
 install -o root -g root -t /usr/local/lib/mercurial-server \
+    src/hg-ssh \
+    src/do-refresh-auth
+install -o root -g root -t /usr/local/lib/mercurial-server -m 644 \
     src/access.py \
-    src/hg-ssh \
-    src/refresh-auth \
     src/ruleset.py
 install -o root -g root -d /usr/local/lib/mercurial-server/init
 install -o root -g root -t /usr/local/lib/mercurial-server/init \
-    src/init/hginit \
+    src/init/hginit
+install -o root -g root -t /usr/local/lib/mercurial-server/init -m 644 \
     src/init/hgadmin-hgrc
-install -o root -g root -d /usr/local/lib/mercurial-server/init/break-in
-install -o root -g root -t /usr/local/lib/mercurial-server/init/break-in \
-    src/init/break-in/create-breakin-repository \
-    src/init/break-in/ssh-replacement \
-    src/init/break-in/as-if-by-ssh \
-    src/init/break-in/break-in
 install -o root -g root -d /etc/mercurial-server
 install -o root -g root -t /etc/mercurial-server \
     src/init/conf/hg-ssh-wrapper \
-    src/init/conf/remote-hgrc
+    src/init/conf/refresh-auth
+install -o root -g root -t /etc/mercurial-server -m 644 \
+    src/init/conf/remote-hgrc \
+    src/init/conf/access.conf
+install -o root -g root -d /etc/mercurial-server/keys/root
 
--- a/setup	Thu Feb 19 16:36:41 2009 +0000
+++ b/setup	Thu Feb 19 17:51:06 2009 +0000
@@ -7,3 +7,4 @@
 adduser --system --shell /bin/sh --group --disabled-password \
    --gecos "Mercurial repositories" hg
 su -c /usr/local/lib/mercurial-server/init/hginit hg
+
--- a/src/access.py	Thu Feb 19 16:36:41 2009 +0000
+++ b/src/access.py	Thu Feb 19 17:51:06 2009 +0000
@@ -21,7 +21,8 @@
     def __init__(self, ui, repo):
         self.ui = ui
         self.repo = repo
-        self.rules = ruleset.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE'])
+        
+        self.rules = ruleset.rules_from_env()
         self.rules.set(user = os.environ['REMOTE_USER'])
         self.rules.set(repo = os.environ['HG_REPO_PATH'])
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/do-refresh-auth	Thu Feb 19 17:51:06 2009 +0000
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+# WARNING
+# This script completely destroys your ~/.ssh/authorized_keys
+# file every time it is run
+# WARNING
+
+import sys
+import os
+import os.path
+import ruleset
+import subprocess
+
+if len(sys.argv) <= 3:
+    sys.stderr.write("refresh-auth: wrong number of arguments (%s)\n" % sys.argv)
+    sys.exit(-1)
+
+akeyfile = sys.argv[1]
+wrappercommand = sys.argv[2]
+prefix='no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command='
+
+if os.path.exists(akeyfile):
+    f = open(akeyfile)
+    try:
+        for l in f:
+            if not l.startswith(prefix):
+                raise Exception("Safety check failed, delete %s to continue" % akeyfile)
+    finally:
+        f.close()
+
+akeys = open(akeyfile + "_new", "w")
+for keyroot in sys.argv[3:]:
+    kr = keyroot + "/"
+    #print "Processing keyroot", keyroot
+    for root, dirs, files in os.walk(keyroot):
+        for fn in files:
+            ffn = os.path.join(root, fn)
+            if not ffn.startswith(kr):
+                print "Weird, walk returned unexpected result"
+                continue
+            #print "Processing file", ffn
+            keyname = ffn[len(kr):]
+            if not ruleset.goodpath(keyname):
+                # ignore any path that contains dodgy characters
+                #print "Ignoring file", ffn
+                continue
+            p = subprocess.Popen(("ssh-keygen", "-i", "-f", ffn), 
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            newkey = p.communicate()[0]
+            if p.wait() == 0:
+                klines = [l.strip() for l in newkey.split("\n")]
+            else:
+                # Conversion failed, read it directly.
+                kf = open(ffn)
+                try:
+                    klines = [l.strip() for l in kf]
+                finally:
+                    kf.close()
+            for l in klines:
+                if len(l):
+                    akeys.write('%s"%s %s" %s\n' % (prefix, wrappercommand, keyname, l))
+
+akeys.close()
+
+os.rename(akeyfile + "_new", akeyfile)
+
--- a/src/hg-ssh	Thu Feb 19 16:36:41 2009 +0000
+++ b/src/hg-ssh	Thu Feb 19 17:51:06 2009 +0000
@@ -17,7 +17,7 @@
 This script is called by hg-ssh-wrapper with no arguments - everything
 should be in enviroment variables:
 
-HG_ACCESS_RULES_FILE identifies the path to the rules file
+HG_ACCESS_RULES_PATH identifies the paths to the rule files
 REMOTE_USER the remote user (which is the key used by ssh)
 SSH_ORIGINAL_COMMAND the command the user was trying to run
 
@@ -68,7 +68,7 @@
     fail("hg-ssh must have no arguments (%s)" 
         % sys.argv)
 
-rules = ruleset.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE'])
+rules = ruleset.rules_from_env()
 rules.set(user = getpath(os.environ['REMOTE_USER']))
 rules.set(branch = None, file = None)
 todispatch = get_cmd(rules, 
--- a/src/init/break-in/as-if-by-ssh	Thu Feb 19 16:36:41 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-#!/bin/sh
-# Used only for break-ins
-
-set -e
-SSH_ORIGINAL_COMMAND=$1
-echo "SSH_ORIGINAL_COMMAND=$SSH_ORIGINAL_COMMAND" >&2
-export SSH_ORIGINAL_COMMAND
-cd
-exec /etc/mercurial-server/hg-ssh-wrapper root
-
--- a/src/init/break-in/break-in	Thu Feb 19 16:36:41 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-set -e
-
-user=$(whoami)
-
-/usr/local/lib/mercurial-server/init/break-in/create-breakin-repository
-cd hgadmin
-mkdir -p keys
-ssh-add -L > keys/$user
-echo "init user=$user" > hg-ssh-access.conf
-hg add keys/$user hg-ssh-access.conf
-hg commit -m "Give all access only to user $user"
-hg push
--- a/src/init/break-in/create-breakin-repository	Thu Feb 19 16:36:41 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-set -e
-
-hg clone -e /usr/local/lib/mercurial-server/init/break-in/ssh-replacement ssh://localhost/hgadmin
-cd hgadmin
-cat >> .hg/hgrc << __END__
-[ui]
-ssh = /usr/local/lib/mercurial-server/init/break-in/ssh-replacement
-__END__
-echo "cd to hgadmin, make changes and commit"
-
--- a/src/init/break-in/do-breakin	Thu Feb 19 16:36:41 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#!/bin/sh
-
-set -e
-
-HOME=~hg
-export HOME
-cd
-
-rm -rf temporary-breakin-repo
-mkdir temporary-breakin-repo
-cd temporary-breakin-repo
-hg clone ~/repos/hgadmin .
-if [ $(echo *) != "" ] ; then
- DIRNAME=retry
-  while [ $DIRNAME = retry ] ; do
-    DIRNAME=$(date -u +"%F_%T.%N")
-    mkdir $DIRNAME || DIRNAME=retry
-  done
-  hg mv * $DIRNAME
-  hg mv -f $DIRNAME old
-fi
-hg echo "init user=initkey" > hg-ssh-access.conf
-mkdir keys
-cat > keys/initkey
-hg add hg-ssh-access.conf keys/initkey
-hg commit -m "Reset access to a single key via break-in script"
-SSH_ORIGINAL_COMMAND= /etc/mercurial-server/hg-ssh-wrapper root
-
--- a/src/init/break-in/ssh-replacement	Thu Feb 19 16:36:41 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-#!/bin/sh
-# Used only for break-ins
-
-echo "arg: $2" >&2
-
-exec sudo -H -u hg /usr/local/lib/mercurial-server/init/break-in/as-if-by-ssh "$2"
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/init/conf/access.conf	Thu Feb 19 17:51:06 2009 +0000
@@ -0,0 +1,2 @@
+init user=root/**
+
--- a/src/init/conf/hg-ssh-wrapper	Thu Feb 19 16:36:41 2009 +0000
+++ b/src/init/conf/hg-ssh-wrapper	Thu Feb 19 17:51:06 2009 +0000
@@ -24,7 +24,7 @@
 export REMOTE_USER
 
 cd repos
-HG_ACCESS_RULES_FILE=$(pwd)/hgadmin/hg-ssh-access.conf
-export HG_ACCESS_RULES_FILE
+HG_ACCESS_RULES_PATH=/etc/mercurial-server/access.conf:$(pwd)/hgadmin/access.conf
+export HG_ACCESS_RULES_PATH
 exec /usr/local/lib/mercurial-server/hg-ssh
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/init/conf/refresh-auth	Thu Feb 19 17:51:06 2009 +0000
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# This file should live in /etc/mercurial-server.
+# If your repository is laid out differently you may need to modify
+# this file.
+
+set -e
+
+if [ `whoami` != 'hg' ] ; then
+    echo "Must be run as hg user"
+    return -1
+else
+    /usr/local/lib/mercurial-server/do-refresh-auth \
+        ~hg/.ssh/authorized_keys \
+        /etc/mercurial-server/hg-ssh-wrapper \
+        /etc/mercurial-server/keys \
+        ~hg/repos/hgadmin/keys
+fi
--- a/src/init/hgadmin-hgrc	Thu Feb 19 16:36:41 2009 +0000
+++ b/src/init/hgadmin-hgrc	Thu Feb 19 17:51:06 2009 +0000
@@ -4,5 +4,5 @@
 [hooks]
 changegroup.aaaaa_update = hg update -C default > /dev/null
 changegroup.aaaab_purge = hg purge --all > /dev/null
-changegroup.refreshauth = /usr/local/lib/mercurial-server/refresh-auth ~/.ssh/authorized_keys /etc/mercurial-server/hg-ssh-wrapper
+changegroup.refreshauth = /etc/mercurial-server/refresh-auth
 
--- a/src/refresh-auth	Thu Feb 19 16:36:41 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-#!/usr/bin/env python
-
-# WARNING
-# This script completely destroys your ~/.ssh/authorized_keys
-# file every time it is run
-# WARNING
-
-import sys
-import os
-import os.path
-import ruleset
-import subprocess
-
-if len(sys.argv) != 3:
-    sys.stderr.write("refresh-auth: wrong number of arguments (%s)\n" % sys.argv)
-    sys.exit(-1)
-
-akeyfile = sys.argv[1]
-wrappercommand = sys.argv[2]
-prefix='no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command='
-
-if os.path.exists(akeyfile):
-    f = open(akeyfile)
-    try:
-        for l in f:
-            if not l.startswith(prefix):
-                raise Exception("Safety check failed, delete %s to continue" % akeyfile)
-    finally:
-        f.close()
-
-akeys = open(akeyfile + "_new", "w")
-for root, dirs, files in os.walk("keys"):
-    for fn in files:
-        ffn = os.path.join(root, fn)
-        if not ruleset.goodpath(ffn):
-            # ignore any path that contains dodgy characters
-            continue
-        keyname = ffn[5:]
-        if keyname == "root":
-            # No key can claim root privileges
-            continue
-        p = subprocess.Popen(("ssh-keygen", "-i", "-f", ffn), 
-            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-        newkey = p.communicate()[0]
-        if p.wait() == 0:
-            klines = [l.strip() for l in newkey.split("\n")]
-        else:
-            # Conversion failed, read it directly.
-            kf = open(ffn)
-            try:
-                klines = [l.strip() for l in kf]
-            finally:
-                kf.close()
-        for l in klines:
-            if len(l):
-                akeys.write('%s"%s %s" %s\n' % (prefix, wrappercommand, keyname, l))
-
-akeys.close()
-
-os.rename(akeyfile + "_new", akeyfile)
-
--- a/src/ruleset.py	Thu Feb 19 16:36:41 2009 +0000
+++ b/src/ruleset.py	Thu Feb 19 17:51:06 2009 +0000
@@ -7,6 +7,8 @@
 
 import sys
 import re
+import os
+import os.path
 
 allowedchars = "A-Za-z0-9_-"
 
@@ -74,9 +76,7 @@
         a = self.matchrule(**kw)
         return a in self.levels and self.levels.index(a) <= self.levels.index(level)
     
-    @classmethod
-    def readfile(cls, fn):
-        res = cls()
+    def readfile(self, fn):
         try:
             f = open(fn)
             try:
@@ -85,11 +85,16 @@
                     if len(l) == 0 or l.startswith("#"):
                         continue
                     l = l.split()
-                    res.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
+                    self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
             finally:
                 f.close()
         except Exception, e:
             print >> sys.stderr, "Failure reading rules file:", e
-            return cls()
-        return res
 
+def rules_from_env():
+    res = Ruleset()
+    for f in os.environ['HG_ACCESS_RULES_PATH'].split(os.pathsep):
+        if os.path.isfile(f):
+            res.readfile(f)
+    return res
+