diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/compileconfig.py | 13 | ||||
-rwxr-xr-x | tools/genconfig.sh | 43 | ||||
-rwxr-xr-x | tools/getconfig.py | 68 | ||||
-rwxr-xr-x | tools/getconfig.sh | 29 | ||||
-rwxr-xr-x | tools/loginfo.py | 1 | ||||
-rw-r--r-- | tools/readconfig.py | 13 |
6 files changed, 162 insertions, 5 deletions
diff --git a/tools/compileconfig.py b/tools/compileconfig.py index b5e5053..28d01b0 100755 --- a/tools/compileconfig.py +++ b/tools/compileconfig.py @@ -365,6 +365,7 @@ def gen_config(nodename, config, localconfig): (Symbol("allowed_clients"), list(allowed_clients)), (Symbol("allowed_servers"), list(allowed_servers)), (Symbol("apikeys"), apikeys), + (Symbol("version"), config["version"]), ] erlangconfig = [ @@ -405,12 +406,21 @@ def gen_testmakefile(config, testmakefile, machines, shellvars=False): configfile.close() +def printnodenames(config): + frontendnodenames = set([node["name"] for node in config["frontendnodes"]]) + storagenodenames = set([node["name"] for node in config["storagenodes"]]) + signingnodenames = set([node["name"] for node in config["signingnodes"]]) + mergenodenames = set([node["name"] for node in config["mergenodes"]]) + + print " ".join(frontendnodenames|storagenodenames|signingnodenames|mergenodenames) + def main(): parser = argparse.ArgumentParser(description="") parser.add_argument('--config', help="System configuration", required=True) parser.add_argument('--localconfig', help="Local configuration") parser.add_argument("--testmakefile", metavar="file", help="Generate makefile variables for test") parser.add_argument("--testshellvars", metavar="file", help="Generate shell variable file for test") + parser.add_argument("--getnodenames", action='store_true', help="Get list of node names") parser.add_argument("--machines", type=int, metavar="n", help="Number of machines") args = parser.parse_args() @@ -420,6 +430,9 @@ def main(): elif args.testshellvars and args.machines: config = readconfig.read_config(args.config) gen_testmakefile(config, args.testshellvars, args.machines, shellvars=True) + elif args.getnodenames: + config = readconfig.read_config(args.config) + printnodenames(config) elif args.localconfig: localconfig = readconfig.read_config(args.localconfig) config = readconfig.verify_and_read_config(args.config, localconfig["logadminkey"]) diff --git a/tools/genconfig.sh b/tools/genconfig.sh new file mode 100755 index 0000000..89bcd85 --- /dev/null +++ b/tools/genconfig.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# usage: genconfig.sh <template> <apikeydir> <logpublickeyfile> <cacertfile> <logadminkey> <destination> + +BINDIR=$(dirname $0) + +template=$1 +apikeydir=$2 +logpublickeyfile=$3 +cacertfile=$4 +logadminkey=$5 +destination=$6 + +nodenames=$($BINDIR/compileconfig.py --config=${template} --getnodenames) + +cat ${template} > ${destination} + +echo "apikeys:" >> ${destination} + +for node in ${nodenames}; do \ + apipk=$(grep -v '^-----' ${apikeydir}/${node}.pem | tr '\n' ' ') + echo " - nodename: ${node}" >> ${destination} + echo " publickey: ${apipk}" >> ${destination} +done + +if [ -f ${destination}.version ]; then + oldversion=$(cat ${destination}.version) + version=$(expr $oldversion + 1) +else + version=1 +fi + +echo ${version} > ${destination}.version + +cafingerprint=$(openssl x509 -in ${cacertfile} -noout -sha256 -fingerprint | sed -e 's/.*=//' -e 's/://g') + +logpk=$(grep -v '^-----' ${logpublickeyfile} | tr '\n' ' ') +echo "logpublickey: ${logpk}" >> ${destination} +echo "cafingerprint: ${cafingerprint}" >> ${destination} +echo "version: ${version}" >> ${destination} + +openssl dgst -sha256 -sign ${logadminkey} -out ${destination}.sig ${destination} + diff --git a/tools/getconfig.py b/tools/getconfig.py new file mode 100755 index 0000000..92cde1f --- /dev/null +++ b/tools/getconfig.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2017, NORDUnet A/S. +# See LICENSE for licensing information. + +import sys +import argparse +import readconfig +from certtools import create_ssl_context, get_sth, mv_file +import os +import errno + +def get_file(configurl): + if configurl.startswith("https://") or configurl.startswith("http://"): + result = urlget(configurl) + result.raise_for_status() + return result + elif configurl.startswith("file:///"): + path = configurl[8:] + path = path.replace("CURRENTWORKINGDIRECTORY", os.getcwd()) + return open(path).read() + +def write_file(fn, data): + tempname = fn + ".new" + open(tempname, 'w').write(data) + mv_file(tempname, fn) + +def get_config_version(filename, logadminkey): + try: + config = readconfig.verify_and_read_config(filename, logadminkey) + return config["version"] + except IOError, e: + if e.errno == errno.ENOENT: + return -1 + raise e + +def main(): + parser = argparse.ArgumentParser(description="") + parser.add_argument('--dest', help="Where to write the verified system configuration", + required=True) + parser.add_argument('--localconfig', help="Local configuration", + required=True) + args = parser.parse_args() + + localconfig = readconfig.read_config(args.localconfig) + + old_config_version = get_config_version(args.dest, localconfig["logadminkey"]) + + configurl = localconfig["configurl"] + unverified_config = get_file(configurl) + unverified_config_sig = get_file(configurl + ".sig") + new_config = readconfig.verify_config(unverified_config, unverified_config_sig, localconfig["logadminkey"], configurl) + verified_config = unverified_config + verified_config_sig = unverified_config_sig + + new_config_version = new_config["version"] + + if new_config_version > old_config_version: + write_file(args.dest, verified_config) + write_file(args.dest + ".sig", verified_config_sig) + print "newconfig" + + elif new_config_version < old_config_version: + print >>sys.stderr, "The version of the configuration on the admin server is older than the version we have, refusing update" + sys.exit(1) + +main() diff --git a/tools/getconfig.sh b/tools/getconfig.sh new file mode 100755 index 0000000..f73cf1b --- /dev/null +++ b/tools/getconfig.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# usage: getconfig.sh <localconfig> <globalconfig> <plopcontrolfile> + +set -o nounset +set -o errexit + +BINDIR=$(dirname $0) + +localconfig=$1 +globalconfig=$2 +plopcontrolfile=$3 + +plopcontrolport=$(cat ${plopcontrolfile}) +configversion=$(echo "configversion" | nc 127.0.0.1 ${plopcontrolport}) +echo "version before reload: $configversion" +getconfigresult=$(${BINDIR}/getconfig.py --localconfig ${localconfig} --dest ${globalconfig}) +if [ "$getconfigresult" == "newconfig" ]; then + ${BINDIR}/compileconfig.py --localconfig ${localconfig} --config ${globalconfig} + reloadresult=$(echo "reload" | nc 127.0.0.1 ${plopcontrolport}) + echo $reloadresult + if [ "$reloadresult" != "reload completed" ]; then + exit 1 + fi + configversion=$(echo "configversion" | nc 127.0.0.1 ${plopcontrolport}) + echo "version after reload: $configversion" +else + echo "reload not needed" +fi diff --git a/tools/loginfo.py b/tools/loginfo.py index 1537c5e..c742b33 100755 --- a/tools/loginfo.py +++ b/tools/loginfo.py @@ -21,7 +21,6 @@ def main(): help="Print tree size") parser.add_argument('--signature', action='store_true', help="Print signature") - parser.add_argument('--config', help="System configuration", required=True) parser.add_argument('--localconfig', help="Local configuration", required=True) parser.add_argument('baseurl', help="Log base URL") diff --git a/tools/readconfig.py b/tools/readconfig.py index 5079691..69531ca 100644 --- a/tools/readconfig.py +++ b/tools/readconfig.py @@ -34,10 +34,7 @@ def errorhandlify(term, filename, path=[]): print "unknown type", type(term) sys.exit(1) -def verify_and_read_config(filename, publickey_base64): - rawconfig = open(filename).read() - signature = open(filename + ".sig").read() - +def verify_config(rawconfig, signature, publickey_base64, filename): publickey = base64.decodestring(publickey_base64) try: @@ -50,5 +47,13 @@ def verify_and_read_config(filename, publickey_base64): return errorhandlify(yaml.load(io.BytesIO(rawconfig), yaml.SafeLoader), filename) +def verify_and_read_config(filename, publickey_base64): + rawconfig = open(filename).read() + signature = open(filename + ".sig").read() + + verify_config(rawconfig, signature, publickey_base64, filename) + + return errorhandlify(yaml.load(io.BytesIO(rawconfig), yaml.SafeLoader), filename) + def read_config(filename): return errorhandlify(yaml.load(open(filename), yaml.SafeLoader), filename) |