summaryrefslogtreecommitdiff
path: root/tools/readconfig.py
blob: 69531caefd272b3131b843eee0b99307200c0006 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import io
import ecdsa
import hashlib
import yaml
import base64
import sys

class ErrorHandlingDict(dict):
    def __init__(self, filename, path):
        self._filename = filename
        self._path = path
        dict.__init__({})
    def __missing__(self, key):
        if self._path:
            path = ", ".join(self._path)
        else:
            path = "the top level"
        print >>sys.stderr, "error: could not find configuration key '%s' at %s in %s" % (key, path, self._filename)
        sys.exit(1)

def errorhandlify(term, filename, path=[]):
    if isinstance(term, basestring):
        return term
    elif isinstance(term, int):
        return term
    elif isinstance(term, dict):
        result = ErrorHandlingDict(filename, path)
        for k, v in term.items():
            result[k] = errorhandlify(v, filename, path + [k])
        return result
    elif isinstance(term, list):
        return [errorhandlify(e, filename, path + ["item %d" % i]) for i, e in enumerate(term, start=1)]
    else:
        print "unknown type", type(term)
        sys.exit(1)

def verify_config(rawconfig, signature, publickey_base64, filename):
    publickey = base64.decodestring(publickey_base64)

    try:
        vk = ecdsa.VerifyingKey.from_der(publickey)
        vk.verify(signature, rawconfig, hashfunc=hashlib.sha256,
                sigdecode=ecdsa.util.sigdecode_der)
    except ecdsa.keys.BadSignatureError:
        print >>sys.stderr, "error: configuration file %s did not have a correct signature" % (filename,)
        sys.exit(1)

    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)