[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Monotone-commits-diffs] net.venge.monotone.contrib.usher: e7277c425674
From: |
code |
Subject: |
[Monotone-commits-diffs] net.venge.monotone.contrib.usher: e7277c425674dd747b3f4b809c56af2f488971c4 |
Date: |
Wed, 19 Jan 2011 13:57:27 GMT |
revision: e7277c425674dd747b3f4b809c56af2f488971c4
date: 2011-01-19T13:57:18
author: Timothy Brownawell <address@hidden>
branch: net.venge.monotone.contrib.usher
changelog:
merge of '200716ad68df60ea4de9b92bf20d8acd1cf20283'
and '7502a593e822d0ec5541e2682d39c9919a8d8edb'
manifest:
format_version "1"
new_manifest [2e37fafd67df2478ee31e5cc44ecb89f76286c7a]
old_revision [200716ad68df60ea4de9b92bf20d8acd1cf20283]
patch "utils/usherctl"
from [f6f4d53eb56bdec130b464c53a5c14060c248dec]
to [b29d51898d66a04f4808afa79dcac9ea24fc0279]
old_revision [7502a593e822d0ec5541e2682d39c9919a8d8edb]
add_file "release-checklist.txt"
content [305136c17d554f0b16fdab39873c5814cc64691a]
patch "NEWS"
from [a9b8cb5b3dc0ec686519bbb81dc1058d30fb1099]
to [41f6acc0681f23e164e7d8dc6be0738de13a8bf1]
patch "README"
from [b968eb93f8b8ce88d822e9ddc52b563f1742a147]
to [84610efd11606729230d94fb905e5e4695328c7b]
patch "src/channel.cc"
from [7e6b6bbae6a84041ec840bedf5816bd6e116e5ea]
to [28d584b7185308aeab9297b3c9ceae03718a9e65]
patch "src/channel.hh"
from [3a97687c17a68c983872de2792defd9e48028168]
to [21231cc383b16935ac33a349718e5aa775341c45]
patch "src/server.hh"
from [dd153b5671f0b9560be8b817849731419e5b8fe4]
to [6a57214c24d5c35c705276dcae8415dfcabf6c6e]
patch "src/server_manager.cc"
from [0abe47e13dd931c522aa1a7fb828502d63531a6e]
to [f4a5b6fe2d917f24ce56c133ee347b9b3e91e50b]
patch "src/server_manager.hh"
from [fc8ad29b28f82cae3b26955995afdad8f1276a5a]
to [1d1f3a16329bdf11b69fb7593d048d95c65edc8d]
patch "src/sock.hh"
from [0917e736d673fa6d15fcefea8f1f0e16a63b9bc2]
to [b077f32cc61674e13b9c3bc138c924c41b23ceb1]
============================================================
--- utils/usherctl f6f4d53eb56bdec130b464c53a5c14060c248dec
+++ utils/usherctl b29d51898d66a04f4808afa79dcac9ea24fc0279
@@ -21,6 +21,8 @@ MTN=/usr/bin/mtn
# (default: $USHER_CONFDIR/global.conf)
# USHER_CONFD Directory for project specific configuration files.
# (default: $USHER_CONFDIR/conf.d)
+# USHER_SKEL Directory for project skeleton files.
+# (default: $USHER_CONFDIR/skel)
# USHER_PIDFILE Usher PID file.
# (default: /var/run/usher.pid)
# USHER_LOGDIR Usher log directory.
@@ -66,6 +68,7 @@ USHER_CONFD=${USHER_CONFD:-"$USHER_CONFD
USHER_CONF=${USHER_CONF:-"$USHER_CONFDIR/usher.conf"}
USHER_GLOBALCONF=${USHER_GLOBALCONF:-"$USHER_CONFDIR/global.conf"}
USHER_CONFD=${USHER_CONFD:-"$USHER_CONFDIR/conf.d"}
+USHER_SKEL=${USHER_SKEL:-"$USHER_CONFDIR/skel"}
USHER_PIDFILE=${USHER_PIDFILE:-/var/run/usher.pid}
USHER_LOGDIR=${USHER_LOGDIR:-/var/log/usher}
USHER_PROJECTDIR=${USHER_PROJECTDIR:-/var/lib/usher/projects}
@@ -85,34 +88,49 @@ _read_pid_file () {
fi
}
-status () {
+status0 () {
if [ -z $USHER_SYSTEM_STARTUP ]; then
pid=`_read_pid_file`
if [ -n "$pid" ]; then
+ echo "$pid"
if kill -0 $pid 2>/dev/null; then
- echo "The usher process is up and running: $pid"
return 0
else
- echo "The usher process is down, but there's a PID file."
return 1
fi
else
- echo "The usher process is down."
return 2
fi
else
/etc/init.d/usher status
fi
}
+status () {
+ pid=`status0`
+ local save_rc=$?
+ case $save_rc in
+ 0 )
+ if [ -z "$pid" ]; then
+ echo "The usher process is up and running"
+ else
+ echo "The usher process is up and running: $pid"
+ fi
+ ;;
+ 1 )
+ echo "The usher process is down, but there's a PID file."
+ ;;
+ 2 )
+ echo "The usher process is down."
+ ;;
+ esac
+ return $save_rc
+}
start () {
if [ -z $USHER_SYSTEM_STARTUP ]; then
- pid=`_read_pid_file`
- if [ -n "$pid" ]; then
- if kill -0 $pid 2>/dev/null; then
- echo >&2 "Usher process already up: $pid"
- exit 1
- fi
+ if pid=`status0`; then
+ echo >&2 "Usher process already up: $pid"
+ exit 1
fi
rm -f "$USHER_PIDFILE"
$USHER -p "$USHER_PIDFILE" "$USHER_CONF" \
@@ -124,8 +142,7 @@ stop () {
stop () {
if [ -z $USHER_SYSTEM_STARTUP ]; then
- pid=`_read_pid_file`
- if [ -n "$pid" ]; then
+ if pid=`status0`; then
kill $pid
fi
else
@@ -135,12 +152,11 @@ reload () {
reload () {
if [ -z $USHER_SYSTEM_STARTUP ]; then
- pid=`_read_pid_file`
- if [ -z "$pid" ]; then
+ if pid=`status0`; then
+ kill -1 $pid
+ else
echo >&2 "No usher process present."
exit 1
- else
- kill -1 $pid
fi
else
/etc/init.d/usher reload
@@ -149,20 +165,15 @@ restart () {
restart () {
if [ -z $USHER_SYSTEM_STARTUP ]; then
- stop && start
+ stop && sleep 1 && start
else
/etc/init.d/usher restart
fi
}
restart_if_started () {
- if [ -z $USHER_SYSTEM_STARTUP ]; then
- pid=`_read_pid_file`
- if [ -n "$pid" ]; then
- restart
- fi
- elif /etc/init.c/usher status >/dev/null 2>/dev/null; then
- /etc/init.d/usher restart
+ if pid=`status0`; then
+ restart
fi
}
@@ -196,6 +207,26 @@ rebuild () {
) > "$USHER_CONF"
_maybe_set_file_owner "$USHER_CONF"
chmod 640 "$USHER_CONF"
+
+ mkdir "$USHER_SKEL" 2> /dev/null
+ _maybe_set_file_owner "$USHER_SKEL"
+ chmod 750 "$USHER_SKEL"
+ cat "$THIS" | grep '^# -----BEGIN init:.*-----$' | \
+ sed -e 's/^# -----BEGIN init://' -e 's/-----$//' | while read f; do
+ d=`dirname "$f"`
+ if [ ! -d "$USHER_SKEL/$d" ]; then
+ mkdir -p "$USHER_SKEL/$d"
+ _maybe_set_file_owner "$USHER_SKEL/$d"
+ chmod 750 "$USHER_CONF"
+ fi
+ ff="`echo "$f" | sed -e 's|/|\\\\/|g'`"
+ sed -e '1,/^# -----BEGIN init:'"$ff"'-----$/d' \
+ -e '/^# -----END init:'"$ff"'-----$/,$d' \
+ -e 's/^# //' \
+ < "$THIS" > "$USHER_SKEL/$f"
+ _maybe_set_file_owner "$USHER_SKEL/$f"
+ chmod 640 "$USHER_SKEL/$f"
+ done
}
# $1 operation
@@ -204,7 +235,7 @@ rebuild () {
# $4 pattern prefix
# $5 type (remote local)
# $6- args
-writesrv () {
+writesrv0 () {
op="$1"; shift
name="$1"; shift
host="$1"; shift
@@ -246,29 +277,39 @@ writesrv () {
_maybe_set_file_owner "$USHER_CONFD/$name.conf"
chmod 640 "$USHER_CONFD/$name.conf"
rebuild
- echo >&2 "Server '$name' $op, please reload usher to activate."
+ echo >&2 "Server '$name' $op."
}
+writesrv () {
+ writesrv0 "$@"
+ echo >&2 "Please reload usher to activate."
+}
+
# $1 server name
# $2 host prefix
# $3 pattern prefix
# $4 type (remote local)
# $5- args
-addsrv () {
+addsrv0 () {
if [ -f "$USHER_CONFD/$1.conf" ]; then
echo >&2 "There is already a server named '$1', not changing."
exit 1
fi
- writesrv added "$@"
+ writesrv0 added "$@"
}
+addsrv () {
+ addsrv0 "$@"
+ echo >&2 "Please reload usher to activate."
+}
+
# $1 server name
# $2 host prefix
# $3 pattern prefix
# $4 type (remote local)
# $5- args
-modsrv () {
+modsrv0 () {
name="$1"; shift
ohost="$1"; host="$1"; shift
opattern="$1"; pattern="$1"; shift
@@ -302,11 +343,16 @@ modsrv () {
esac
done < "$USHER_CONFD/$name.conf"
mv "$USHER_CONFD/$name.conf" "$USHER_CONFD/$name.conf~"
- writesrv modified "$name" "$host" "$pattern" "$@"
+ writesrv0 modified "$name" "$host" "$pattern" "$@"
}
+modsrv () {
+ modsrv0 "$@"
+ echo >&2 "Please reload usher to activate."
+}
+
# $1 server name
-delsrv () {
+delsrv0 () {
name="$1"
if [ ! -f "$USHER_CONFD/$name.conf" ]; then
@@ -316,9 +362,50 @@ delsrv () {
rm -f "$USHER_CONFD/$name.conf" "$USHER_CONFD/$name.conf~"
rebuild
- echo >&2 "Server '$name' deleted, please reload usher to activate."
+ echo >&2 "Server '$name' deleted."
}
+delsrv () {
+ delsrv0 "$@"
+ echo >&2 "Please reload usher to activate."
+}
+
+# $1 name
+rebuild_permissions () {
+ confdir="$USHER_PROJECTDIR/$name"
+ aconfdir="$confdir/admin"
+ amtn="$MTN --confdir \"$aconfdir\" --no-standard-rcfiles --no-workspace"
+ listenport=`cat "$USHER_CONF" | grep '^ *listenaddr' | tail -1 | \
+ cut -f2 -d'"' | cut -f2 -d:`
+
+ cp "$aconfdir/rakeys" "$confdir/remote-automate-permissions.new.$$"
+ cp "$aconfdir/rwkeys" "$confdir/write-permissions.new.$$"
+ patterns="`cat "$aconfdir/patterns" | sed -e '/^ *$/d'`"
+ if [ -z "$patterns" ]; then patterns="*"; fi
+ echo "$patterns" | while read p; do
+ echo "pattern \"$p\"";
+ if [ -f "$aconfdir/type.private" ]; then
+ cat "$aconfdir/rokeys" "$aconfdir/rwkeys" | sort | uniq | \
+ sed -e 's/^/ allow "/' -e 's/$/"/'
+ else
+ echo " allow \"*\""
+ fi
+ echo
+ done > "$confdir/read-permissions.new.$$"
+
+ mv "$confdir/read-permissions.new.$$" "$confdir/read-permissions"
+ mv "$confdir/write-permissions.new.$$" "$confdir/write-permissions"
+ mv "$confdir/remote-automate-permissions.new.$$" \
+ "$confdir/remote-automate-permissions"
+
+ _maybe_set_file_owner "$confdir/read-permissions"
+ _maybe_set_file_owner "$confdir/write-permissions"
+ _maybe_set_file_owner "$confdir/remote-automate-permissions"
+ chmod 0640 "$confdir/read-permissions"
+ chmod 0640 "$confdir/write-permissions"
+ chmod 0640 "$confdir/remote-automate-permissions"
+}
+
# $1 type
# $2 name
mkproject () {
@@ -331,6 +418,10 @@ mkproject () {
fi
confdir="$USHER_PROJECTDIR/$name"
+ aconfdir="$confdir/admin"
+
+
+ # Create protect project infrastructure
set -e
mkdir "$confdir"
mkdir "$confdir/hooks.d"
@@ -339,6 +430,35 @@ mkproject () {
_maybe_set_directory_owner "$confdir"
chmod 0750 "$confdir"
+ # Create and protect admin infrastructure
+ set -e
+ mkdir "$aconfdir"
+ set +e
+
+ _maybe_set_directory_owner "$aconfdir"
+ chmod 700 "$aconfdir"
+
+
+ # --- Usher administration ---
+ amtn="$MTN --confdir \"$aconfdir\" --no-standard-rcfiles --no-workspace"
+
+ # Generate admin key
+ (echo; echo) | eval $amtn genkey "\"$name-admin\"" > /dev/null 2> /dev/null
+ akid=`eval $amtn ls keys | grep "$name-admin\$" | tail -1 | cut -f1 -d' '`
+ _maybe_set_directory_owner "$aconfdir/keys"
+
+ # Add admin information
+ touch "$aconfdir/type.$type" # A marker for the project type
+ touch "$aconfdir/patterns" # The branch patterns handled by this
+ # project. If none, "*" is assumed.
+ touch "$aconfdir/rokeys" # r/o key identities, one per line.
+ touch "$aconfdir/rwkeys" # r/w key identities, one per line.
+ touch "$aconfdir/rakeys" # remote_automate permissions key
+ # identities, one per line.
+
+ # --- Project ---
+ mtn="$MTN -d \"$confdir/database.mtn\" --confdir \"$confdir\" --no-standard-rcfiles --ticker=dot --no-workspace"
+
# Generate name and password for the server key
skn="$name-server"
skp=`dd if=/dev/random ibs=8 count=1 2>/dev/null | \
@@ -347,101 +467,63 @@ mkproject () {
_maybe_set_file_owner "$confdir/passphrases"
chmod 400 $confdir/passphrases
- # Generate database
- mtn="$MTN -d \"$confdir/database.mtn\" --confdir \"$confdir\" --no-standard-rcfiles --ticker=dot"
+ # Generate server database
eval $mtn db init
_maybe_set_file_owner "$confdir/database.mtn"
chmod 0600 "$confdir/database.mtn"
- # Generate key
+ # Generate server key
(echo "$skp"; echo "$skp") | \
- eval $mtn genkey "$skn" > /dev/null 2> /dev/null
+ eval $mtn genkey "\"$skn\"" > /dev/null 2> /dev/null
skid=`eval $mtn ls keys | grep "$skn\$" | tail -1 | cut -f1 -d' '`
_maybe_set_directory_owner "$confdir/keys"
- sed -e '1,/^# -----BEGIN monotonerc-----$/d' \
- -e '/^# -----END monotonerc-----$/,$d' \
- -e 's/^# //' \
- < "$THIS" > "$confdir/monotonerc"
- _maybe_set_file_owner "$confdir/monotonerc"
- chmod 0640 "$confdir/monotonerc"
+ # Generate server monotonerc and other scripts, from skeleton files
+ (
+ cd "$USHER_SKEL"
+ for x in both $type; do
+ [ -d $x ] && find $x -type f
+ done
+ ) | while read f; do
+ section=`echo "$f" | sed -e 's|/.*$||'`
+ ff=`echo "$f" | sed -e 's|^'"$section"'/||'`
+ d=`dirname "$ff"`
+ b=`basename "$ff" .in`
+ if [ ! -d "$confdir/$d" ]; then
+ mkdir -p "$confdir/$d"
+ _maybe_set_file_owner "$confdir/$d"
+ chmod 750 "$confdir/$d"
+ fi
+ if [ "$d/$b" = "$ff" ]; then
+ ln -s "$USHER_SKEL/$f" "$confdir/$d/$b"
+ else
+ sed -e "s|%adminkey%|$akid|g" \
+ < "$USHER_SKEL/$f" > "$confdir/$d/$b"
+ fi
+ _maybe_set_file_owner "$confdir/$d/$b"
+ chmod 0640 "$confdir/$d/$b"
+ done
- aconfdir="$confdir/admin"
- mkdir "$aconfdir"
- _maybe_set_directory_owner "$aconfdir"
- chmod 700 "$aconfdir"
+ # --- Finalise ---
- amtn="$MTN -d \"$aconfdir/database.mtn\" --confdir \"$aconfdir\" --no-standard-rcfiles --ticker=dot"
- eval $amtn db init
- _maybe_set_file_owner "$aconfdir/database.mtn"
- chmod 0600 "$aconfdir/database.mtn"
+ # bootstrap admin key into the project database
+ eval $amtn pubkey "\"$name-admin\"" | eval $mtn read 2> /dev/null
+ echo "$akid" > "$aconfdir/rakeys"
- (echo; echo) | eval $amtn genkey "$name-admin" > /dev/null 2> /dev/null
- akid=`eval $amtn ls keys | grep "$akn\$" | tail -1 | cut -f1 -d' '`
- _maybe_set_directory_owner "$aconfdir/keys"
-
- listenport=`cat "$USHER_CONF" | grep '^ *listenaddr' | tail -1 | \
- cut -f2 -d'"' | cut -f2 -d:`
-
- case $type in
- public )
- (
- echo 'pattern "*"'
- echo ' allow "*"'
- ) > "$confdir/read-permissions"
- touch "$confdir/write-permissions"
- sed -e '1,/^# -----BEGIN pub:addclientkeys-----$/d' \
- -e '/^# -----END pub:addclientkeys-----$/,$d' \
- -e "s|%amtn%|$amtn|g" \
- -e "s|%confdir%|$confdir|g" \
- -e "s|%listenport%|$listenport|g" \
- -e "s|%name%|$name|g" \
- -e "s|%user%|$USHER_USER|g" \
- -e "s|%group%|$USHER_GROUP|g" \
- -e 's/^# //' \
- < "$THIS" > "$confdir/addclientkeys"
- ;;
- private )
- (
- echo 'pattern "*"'
- ) > "$confdir/read-permissions"
- touch "$confdir/write-permissions"
- sed -e '1,/^# -----BEGIN priv:addclientkeys-----$/d' \
- -e '/^# -----END priv:addclientkeys-----$/,$d' \
- -e "s|%amtn%|$amtn|g" \
- -e "s|%confdir%|$confdir|g" \
- -e "s|%listenport%|$listenport|g" \
- -e "s|%name%|$name|g" \
- -e "s|%user%|$USHER_USER|g" \
- -e "s|%group%|$USHER_GROUP|g" \
- -e 's/^# //' \
- < "$THIS" > "$confdir/addclientkeys"
- ;;
- esac
-
- _maybe_set_file_owner "$confdir/read-permissions"
- _maybe_set_file_owner "$confdir/write-permissions"
- _maybe_set_file_owner "$confdir/addclientkeys"
- chmod 0640 $confdir/read-permissions
- chmod 0640 $confdir/write-permissions
- chmod 0600 $confdir/addclientkeys
-
- # We need a quick bootstrap, otherwise addclientkeys won't work
- eval $amtn pubkey "$name-admin" | eval $mtn read 2> /dev/null
-
- addsrv "$name" "" "" \
+ # add project server
+ addsrv0 "$name" "" "" \
local "--confdir" "$confdir" "-d" "$confdir/database.mtn" \
"--no-standard-rcfiles" "--rcfile" "$confdir/monotonerc" \
- "--timestamps" "--ticker=dot" 2>/dev/null
+ "--timestamps" "--ticker=dot"
+
restart_if_started
- _maybe_set_file_owner "$confdir/addclientkeys"
- chmod 700 "$confdir/addclientkeys"
- eval $amtn pubkey "$name-admin" | "$confdir/addclientkeys"
+ rebuild_permissions "$name"
echo >&2 "$type project '$name' created."
}
+# $1: name
rmproject () {
name="$1"; shift
@@ -450,12 +532,104 @@ rmproject () {
exit 1
fi
- delsrv "$name" 2>/dev/null
+ delsrv0 "$name"
restart_if_started
rm -rf "$USHER_PROJECTDIR/$name"
echo >&2 "project '$name' removed."
}
+# $1: name
+# $2: type
+# stdin: public key
+addprojectkey () {
+ name="$1"; shift
+ type="$1"; shift
+ key="`cat`"
+
+ if [ ! -e "$USHER_PROJECTDIR/$name" ]; then
+ echo >&2 "There is no project named '$name'."
+ exit 1
+ fi
+
+ confdir="$USHER_PROJECTDIR/$name"
+ aconfdir="$confdir/admin"
+ amtn="$MTN --confdir \"$aconfdir\" --no-standard-rcfiles --no-workspace"
+ listenaddr=mtn://`cat "$USHER_CONF" | grep '^ *listenaddr' | tail -1 | \
+ cut -f2 -d'"' | sed -e 's|^0\.0\.0\.0:\(.*\)$|127.0.0.1:\1|'`/"$name"
+
+ # Send the public key to the project server
+ if ! eval $amtn --keydir "\"$aconfdir/keys\"" --key "$name-admin" \
+ automate remote --remote-stdio-host $listenaddr \
+ put_public_key "\"$key\"" 2> /tmp/mtn.$$.err; then
+ echo >&2 "Couldn't add public key to remote server $listenaddr"
+ echo >&2 "------------"
+ cat >&2 /tmp/mtn.$$.err
+ echo >&2 "------------"
+ exit 1
+ fi
+
+ # Figure out the key identity
+ eval $amtn --db "\"$aconfdir/throwaway.$$.mtn\"" db init
+ echo "$key" | \
+ eval $amtn --db "\"$aconfdir/throwaway.$$.mtn\"" read 2> /dev/null
+ keyid=`eval $amtn --db "\"$aconfdir/throwaway.$$.mtn\"" ls keys | \
+ sed -e '/\[private keys\]/,$d' | grep '^[0-9a-f]' | fgrep -v '(*)' | \
+ cut -f1 -d' '`
+ rm -f "$aconfdir/throwaway.$$.mtn"
+
+ # Add the key identity to the appropriate key file
+ x=$type
+ case "$type" in
+ ro )
+ echo "$aconfdir/rokeys"
+ ;;
+ rw )
+ echo "$aconfdir/rokeys"
+ echo "$aconfdir/rwkeys"
+ ;;
+ ra )
+ echo "$aconfdir/rakeys"
+ ;;
+ esac | while read keyfile; do
+ if ! grep '^'"$keyid"'$' "$keyfile" > /dev/null; then
+ echo "$keyid" >> "$keyfile"
+ fi
+ done
+
+ rebuild_permissions "$name"
+
+ echo >&2 "key '$keyid' added to project '$name'."
+}
+
+# $1: name
+# $2: branch pattern
+addprojectpattern () {
+ name="$1"; shift
+ pattern="$1"; shift
+
+ if [ ! -e "$USHER_PROJECTDIR/$name" ]; then
+ echo >&2 "There is no project named '$name'."
+ exit 1
+ fi
+
+ confdir="$USHER_PROJECTDIR/$name"
+ aconfdir="$confdir/admin"
+
+ found_pattern=false
+ while read p; do
+ if [ "$p" = "$pattern" ]; then
+ found_pattern=true
+ fi
+ done < "$aconfdir/patterns"
+ if ! $found_pattern; then
+ echo "$pattern" >> "$aconfdir/patterns"
+ fi
+
+ rebuild_permissions "$name"
+
+ echo >&2 "pattern '$pattern' added to project '$name'."
+}
+
list () {
grep '^ *server *"' "$USHER_CONF" | cut -f2 -d'"' | while read name; do
text="$name"
@@ -478,10 +652,42 @@ case $1 in
echo >&2 "Usher is already initialised."
exit 1
fi
+
+ adminuser=admin
+ adminpass=admin
+ listenaddr=0.0.0.0:4691
+ adminaddr=127.0.0.1:12345
+ TEMP=`POSIXLY_CORRECT=yes getopt -o a:l:u:p: -n "usherctl init" -- "$@"`
+ eval set -- "$TEMP"
+ while true; do
+ case "$1" in
+ -a )
+ adminaddr="$2"; shift 2
+ ;;
+ -l )
+ listenaddr="$2"; shift 2
+ ;;
+ -u )
+ adminuser="$2"; shift 2
+ ;;
+ -p )
+ adminpass="$2"; shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ done
+
mkdir "$USHER_CONFDIR" "$USHER_CONFD" "$USHER_LOGDIR"
mkdir -p "$USHER_PROJECTDIR"
sed -e '1,/^# -----BEGIN globalconf-----$/d' \
-e '/^# -----END globalconf-----$/,$d' \
+ -e "s|%adminuser%|$adminuser|g" \
+ -e "s|%adminpass%|$adminpass|g" \
+ -e "s|%listenaddr%|$listenaddr|g" \
+ -e "s|%adminaddr%|$adminaddr|g" \
-e "s|%MTN%|$MTN|g" \
-e "s|%USHER_LOGDIR%|$USHER_LOGDIR|g" \
-e 's/^# //' \
@@ -570,6 +776,46 @@ case $1 in
rmproject "$1"
;;
+ addkey )
+ shift
+ name="$1"
+ shift
+
+ type=ro
+ key=
+ TEMP=`POSIXLY_CORRECT=yes getopt -o t: -n "usherctl addkey" -- "$@"`
+ eval set -- "$TEMP"
+ while true; do
+ case "$1" in
+ -t )
+ type="$2"; shift 2
+ if [ "$type" != "ro" -a "$type" != "rw" -a "$type" != "ra" ]; then
+ echo >&2 "The type must be 'rw', 'ro' or 'ra'."
+ fi
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+ done
+
+ if [ -z "$name" ]; then
+ echo >&2 "You have to give your project a name."
+ exit 1
+ fi
+
+ addprojectkey "$name" "$type" # The key itself is on stdin
+ ;;
+
+ addpattern )
+ shift
+ name="$1"
+ pattern="$2"
+
+ addprojectpattern "$name" "$pattern"
+ ;;
+
start | stop | restart | reload | status | list )
$1
;;
@@ -584,18 +830,113 @@ exit
#### The following is sample text used to create scripts
# -----BEGIN globalconf-----
-# userpass "admin" "admin"
+# userpass "%adminuser%" "%adminpass%"
# monotone "%MTN%"
-# listenaddr "0.0.0.0:4691"
-# adminaddr "127.0.0.1:12345"
+# listenaddr "%listenaddr%"
+# adminaddr "%adminaddr%"
# logdir "%USHER_LOGDIR%"
# -----END globalconf-----
-# -----BEGIN monotonerc-----
-# ----------------------------------------------------------------------
-# ---- usherctl: this is a copy of contrib/get_passphrase_from_file.lua
-# ---- from the monotone distribution.
-# ----------------------------------------------------------------------
+# -----BEGIN init:both/monotonerc.in-----
+# ---- Load local hooks if they exist.
+# -- The way this is supposed to work is that hooks.d can contain symbolic
+# -- links to lua scripts. These links MUST have the extension .lua
+# -- If the script needs some configuration, a corresponding lua file with
+# -- the extension .conf is the right spot.
+# ----
+# -- First load the configuration of the hooks, if applicable
+# includedirpattern(get_confdir() .. "/hooks.d/","*.conf")
+# -- Then load the hooks themselves
+# includedirpattern(get_confdir() .. "/hooks.d/","*.lua")
+# -----END init:both/monotonerc.in-----
+
+# Copied from monotone: contrib/authorize_remote_automate.lua
+# -----BEGIN init:both/hooks.d/authorize_remote_automate.lua-----
+# -- Copyright (c) 2010, Thomas Keller <address@hidden>
+# -- Richard Levitte <address@hidden>
+# --
+# -- This script reads key identities from a file "remote-automate-permissions"
+# -- in the configuration directory and permits those authenticating with one
+# -- of those keys to perform dangerous (read/write) remote automate operations.
+# -- The format of the file is very simple, one key identity on every line.
+# -- Lines starting with # are ignore, as well as empty lines.
+# --
+# -- It's possible to configure this script to allow the performance of some
+# -- remote automate commands anonymously, through the variable
+# -- ARA_safe_commands, which has to be a table of commands as strings.
+# -- One example configuration, taken from the setup at code.monotone.ca, could
+# -- be this:
+# --
+# -- ARA_safe_commands = {
+# -- "get_corresponding_path", "get_content_changed", "tags", "branches",
+# -- "common_ancestors", "packet_for_fdelta", "packet_for_fdata",
+# -- "packets_for_certs", "packet_for_rdata", "get_manifest_of",
+# -- "get_revision", "select", "graph", "children", "parents", "roots",
+# -- "leaves", "ancestry_difference", "toposort", "erase_ancestors",
+# -- "descendents", "ancestors", "heads", "get_file_of", "get_file",
+# -- "interface_version", "get_attributes", "content_diff",
+# -- "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of"
+# -- }
+#
+# do
+# local _safe_commands = {}
+# if ARA_safe_commands then
+# _safe_commands = ARA_safe_commands
+# end
+#
+# local _save_get_remote_automate_permitted = get_remote_automate_permitted
+# function get_remote_automate_permitted(key_identity, command, options)
+# local permfile =
+# io.open(get_confdir() .. "/remote-automate-permissions", "r")
+# if (permfile == nil) then
+# return false
+# end
+#
+# -- See if the incoming key matches any of the key identities or
+# -- patterns found in the permissions file.
+# local matches = false
+# local line = permfile:read()
+# while (not matches and line ~= nil) do
+# if not globish_match("#*", line) then
+# local _, _, ln = string.find(line, "%s*([^%s]*)%s*")
+# if ln == "*" then matches = true end
+# if ln == key_identity.id then matches = true end
+# if globish_match(ln, key_identity.name) then matches = true end
+# line = permfile:read()
+# end
+# end
+# io.close(permfile)
+# if matches then return true end
+#
+# -- No matching key found, let's see if the command matches one the
+# -- admin allowed to be performed anonymously
+# for _,v in ipairs(_safe_commands) do
+# if (v == command[1]) then
+# return true
+# end
+# end
+#
+# -- No matches found anywhere, then don't permit this operation
+# return false
+# end
+# end
+# -----END init:both/hooks.d/authorize_remote_automate.lua-----
+
+# -----BEGIN init:public/hooks.d/authorize_remote_automate.conf-----
+# ARA_safe_commands = {
+# "get_corresponding_path", "get_content_changed", "tags", "branches",
+# "common_ancestors", "packet_for_fdelta", "packet_for_fdata",
+# "packets_for_certs", "packet_for_rdata", "get_manifest_of",
+# "get_revision", "select", "graph", "children", "parents", "roots",
+# "leaves", "ancestry_difference", "toposort", "erase_ancestors",
+# "descendents", "ancestors", "heads", "get_file_of", "get_file",
+# "interface_version", "get_attributes", "content_diff",
+# "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of"
+# }
+# -----END init:public/hooks.d/authorize_remote_automate.conf-----
+
+# Copied from monotone: contrib/get_passphrase_from_file.lua
+# -----BEGIN init:both/hooks.d/get_passphrase_from_file.lua-----
# -- This hook reads the 'passphrases' file from the confdir. It expects the
# -- file to be formatted as follows:
# --
@@ -611,120 +952,10 @@ exit
# local line = permfile:read()
# while (line ~= nil) do
# local _, _, key, passphrase = string.find(line, "%s*([^%s]*)%s*\"(.*)\"%s*")
-# if keypair_id.given_name == key then
-# return passphrase
-# end
+# if keypair_id.given_name == key then return passphrase end
# line = permfile:read()
# end
# io.close(permfile)
# return false
# end
-# ----------------------------------------------------------------------
-#
-# function get_remote_automate_permitted(key_identity, command, options)
-# -- Use the key identity from clients that may use dangerous remote commands
-# if (key_identity.id == "?????") then
-# return true
-# end
-#
-# local read_only_commands = {
-# "get_corresponding_path", "get_content_changed", "tags", "branches",
-# "common_ancestors", "packet_for_fdelta", "packet_for_fdata",
-# "packets_for_certs", "packet_for_rdata", "get_manifest_of",
-# "get_revision", "select", "graph", "children", "parents", "roots",
-# "leaves", "ancestry_difference", "toposort", "erase_ancestors",
-# "descendents", "ancestors", "heads", "get_file_of", "get_file",
-# "interface_version", "get_attributes", "content_diff",
-# "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of"
-# }
-#
-# for _,v in ipairs(read_only_commands) do
-# if (v == command[1]) then
-# return true
-# end
-# end
-#
-# return false
-# end
-#
-# ---- Load local hooks if they exist.
-# -- The way this is supposed to work is that hooks.d can contain symbolic
-# -- links to lua scripts. These links MUST have the extension .lua
-# -- If the script needs some configuration, a corresponding lua file with
-# -- the extension .conf is the right spot.
-# ----
-# -- First load the configuration of the hooks, if applicable
-# includedirpattern(get_confdir() .. "/hooks.d/","*.conf")
-# -- Then load the hooks themselves
-# includedirpattern(get_confdir() .. "/hooks.d/","*.lua")
-# -----END monotonerc-----
-
-# -----BEGIN priv:addclientkeys-----
-# #! /bin/sh
-#
-# mtn='%amtn%'
-# confdir='%confdir%'
-# listenport='%listenport%'
-# name='%name%'
-# user='%user%'
-# group='%group%'
-#
-# set -e
-# cd "$confdir"
-#
-# eval $mtn read 2> /dev/null
-# rm -f "$confdir/write-permissions"
-# touch "$confdir/write-permissions"
-# echo 'pattern "*"' > "$confdir/read-permissions"
-# chmod 0640 "$confdir/read-permissions"
-# chmod 0640 "$confdir/write-permissions"
-# eval $mtn ls keys | grep '^[0-9a-f]' | cut -f1 -d' ' | sort | uniq | \
-# while read K; do
-# echo $K >> "$confdir/write-permissions"
-# echo " allow \"$K\"" >> "$confdir/read-permissions"
-# if /etc/init.c/usher status >/dev/null 2>/dev/null; then
-# eval $mtn push mtn://127.0.0.1:$listenport/$name '"*"' \
-# --key-to-push $K 2> /dev/null
-# else
-# eval $mtn push file://$confdir/database.mtn '"*"' \
-# --key-to-push $K 2> /dev/null
-# fi
-# done
-# if [ -n "$user" -a -n "$group" ]; then
-# chown ${user}:${group} "$confdir/write-permissions"
-# chown ${user}:${group} "$confdir/read-permissions"
-# fi
-# -----END priv:addclientkeys-----
-
-# -----BEGIN pub:addclientkeys-----
-# #! /bin/sh
-#
-# mtn='%amtn%'
-# confdir='%confdir%'
-# listenport='%listenport%'
-# name='%name%'
-# user='%user%'
-# group='%group%'
-#
-# set -e
-# cd "$confdir"
-#
-# eval $mtn read 2> /dev/null
-# rm -f "$confdir/write-permissions"
-# touch "$confdir/write-permissions"
-# chmod 0640 "$confdir/write-permissions"
-# eval $mtn ls keys | grep '^[0-9a-f]' | cut -f1 -d' ' | sort | uniq | \
-# while read K; do
-# echo $K >> "$confdir/write-permissions"
-# if /etc/init.c/usher status >/dev/null 2>/dev/null; then
-# eval $mtn push mtn://127.0.0.1:$listenport/$name '"*"' \
-# --key-to-push $K 2> /dev/null
-# else
-# eval $mtn push file://$confdir/database.mtn '"*"' \
-# --key-to-push $K 2> /dev/null
-# fi
-# done
-# if [ -n "$user" -a -n "$group" ]; then
-# chown ${user}:${group} "$confdir/write-permissions"
-# fi
-# -----END pub:addclientkeys-----
+# -----END init:both/hooks.d/get_passphrase_from_file.lua-----
============================================================
--- src/channel.cc 7e6b6bbae6a84041ec840bedf5816bd6e116e5ea
+++ src/channel.cc 28d584b7185308aeab9297b3c9ceae03718a9e65
@@ -24,7 +24,7 @@ channel::channel(sock & c, server_manage
channel::channel(sock & c, server_manager &sm)
: num(++counter),
- cli(c), srv(-1),
+ cli(c),
have_routed(false), no_server(false),
manager(sm)
{
@@ -45,7 +45,7 @@ channel::~channel()
channel::~channel()
{
- if (srv && !no_server)
+ if (srv != -1 && !no_server)
manager.disconnect_from_server(srv, name);
}
============================================================
--- src/channel.hh 3a97687c17a68c983872de2792defd9e48028168
+++ src/channel.hh 21231cc383b16935ac33a349718e5aa775341c45
@@ -17,7 +17,7 @@ using boost::shared_ptr;
#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
-struct server_manager;
+class server_manager;
struct channel
{
============================================================
--- src/server.hh dd153b5671f0b9560be8b817849731419e5b8fe4
+++ src/server.hh 6a57214c24d5c35c705276dcae8415dfcabf6c6e
@@ -24,7 +24,7 @@ using boost::weak_ptr;
#include <boost/weak_ptr.hpp>
using boost::weak_ptr;
-struct server_manager;
+class server_manager;
struct serverstate
{
@@ -38,8 +38,9 @@ std::ostream & operator<<(std::ostream &
};
std::ostream & operator<<(std::ostream & os, serverstate const & ss);
-struct server
+class server
{
+ friend class server_manager;
bool enabled;
bool local;
int pid;
@@ -51,6 +52,7 @@ struct server
int last_conn_time;
server_manager &manager;
weak_ptr<server> me;
+public:
server(server_manager &sm);
~server();
serverstate get_state();
============================================================
--- src/server_manager.cc 0abe47e13dd931c522aa1a7fb828502d63531a6e
+++ src/server_manager.cc f4a5b6fe2d917f24ce56c133ee347b9b3e91e50b
@@ -20,8 +20,9 @@ using std::make_pair;
#include <boost/lexical_cast.hpp>
//#include <iostream>
-serversock::serversock(sock const &o)
- : sock(o)
+serversock::serversock() : sock(-1) { }
+serversock::serversock(sock const &o, string s)
+ : sock(o), srv(s)
{
}
@@ -309,11 +310,10 @@ server_manager::connect_to_server(string
if (!srv)
throw std::logic_error("usher internal error");
sock s = srv->connect(name);
- serversock ss(s);
map<shared_ptr<server>, serverdata>::iterator i = servers.find(srv);
if (i == servers.end())
throw std::logic_error("server_manager is inconsistent");
- ss.srv = i->second.name;
+ serversock ss(s, i->second.name);
++total_connections;
if (srv->local && srv->connection_count == 1)
{
@@ -325,7 +325,7 @@ server_manager::disconnect_from_server(s
server_manager::disconnect_from_server(serversock const &s,
string const &name)
{
- map<string, shared_ptr<server> >::iterator i = by_name.find(s.srv);
+ map<string, shared_ptr<server> >::iterator i = by_name.find(s.servername());
if (i == by_name.end())
return;
i->second->disconnect(name);
============================================================
--- src/server_manager.hh fc8ad29b28f82cae3b26955995afdad8f1276a5a
+++ src/server_manager.hh 1d1f3a16329bdf11b69fb7593d048d95c65edc8d
@@ -27,11 +27,13 @@ struct serverlist_reader;
struct serverlist_reader;
-struct serversock : public sock
+class serversock : public sock
{
string srv;
- serversock(sock const &o);
- operator bool() {return !srv.empty();}
+public:
+ serversock();
+ serversock(sock const &o, string s);
+ string const & servername() const { return srv; }
};
class server_manager
============================================================
--- src/sock.hh 0917e736d673fa6d15fcefea8f1f0e16a63b9bc2
+++ src/sock.hh b077f32cc61674e13b9c3bc138c924c41b23ceb1
@@ -15,10 +15,11 @@ struct buffer;
struct buffer;
-struct sock
+class sock
{
int *s;
static std::set<int*> all_socks;
+public:
operator int();
sock(int ss);
sock(sock const & ss);
============================================================
--- README b968eb93f8b8ce88d822e9ddc52b563f1742a147
+++ README 84610efd11606729230d94fb905e5e4695328c7b
@@ -13,4 +13,4 @@
use your new subclass instead of basic_io_serverlist_reader.
The tests use 'socat', and assume the monotone in your $PATH is at least
-version 0.45.
\ No newline at end of file
+version 0.45.
============================================================
--- NEWS a9b8cb5b3dc0ec686519bbb81dc1058d30fb1099
+++ NEWS 41f6acc0681f23e164e7d8dc6be0738de13a8bf1
@@ -1,5 +1,13 @@
-Xxx Xxx 99 99:99:99 UTC 2010
+Xxx Xxx 99 99:99:99 UTC 2011
+ 1.0 release.
+
+ General
+
+ - [put stuff here]
+
+Sat Nov 06 03:04:58 UTC 2010
+
0.99 release.
General
============================================================
--- /dev/null
+++ release-checklist.txt 305136c17d554f0b16fdab39873c5814cc64691a
@@ -0,0 +1,16 @@
+* test 'make check' or 'make distcheck' on a couple different systems
+
+* look at what's changed since the last release, and make sure there are documentation
+ updates where appropriate
+
+* make sure NEWS is filled out and presentable
+
+* make sure the date at the top of NEWS is filled out
+
+* take the "~dev" out of the version in configure.in
+
+* commit; run autoreconf -i, configure, and "make distcheck" in a clean checkout
+
+* add a tag, post the tarball, and email monotone-devel
+
+* add a new blank release date at the top of NEWS, increment the version number and add "~dev"
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Monotone-commits-diffs] net.venge.monotone.contrib.usher: e7277c425674dd747b3f4b809c56af2f488971c4,
code <=