diff --git a/README.md b/README.md index 28db9e5bbe1ee7793572ced4b4c71a8a3ac215d2..c3436ce7d5792306925438020d78e6c775dbc750 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Alternate MDX research project ## ```mdsigner.py [mdfile] [mdfile] [mdfile] ...``` Reads source metadata file(s) and outputs them signed to filesystem -## ```mdserver.py [mdfile] [mdfile] [mdfile] ...``` +## ```mdserver.py``` Starts a metadata signer server. Reads source metadata files(s) from mdsigner.yaml configuration, see example. Reloads metadata on inotify CLOSE_WRITE of metadata file. @@ -28,3 +28,19 @@ MDQ Queries can then be pointed at - ```http://mdserver:5001/sign/<entityid>``` - ```http://mdproxy:5002/cache/<entityid>``` + +## Bootstrap softHSM2 +This is a very brief summary of the successive commands to initialize softHSM2 for testing. Tested on Ubuntu 21.10. +``` +# softhsm2-util --show-slots +# softhsm2-util --init-token --slot 0 --label "My token 1" --pin "secret" --so-pin "secret" +# softhsm2-util --show-slots + +# pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l -k --key-type rsa:1024 --slot-index 0 --id a1b2 --label test --pin secret +# pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l --pin secret -O + +# openssl req -new -x509 -subj "/CN=Test Signer" -engine pkcs11 -keyform engine -key label_test -passin 'pass:secret' -out hsm.crt +# openssl x509 -inform PEM -outform DER -in hsm.crt -out hsm.der + +# pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -l --slot-index 0 --id a1b2 --label test -y cert -w hsm.der --pin secret +``` \ No newline at end of file diff --git a/mdserver.py b/mdserver.py index 1384575453fff4671eb4edb79534b18248994424..a1263aeb4b02b4d4816358eb208fe5de4a094158 100755 --- a/mdserver.py +++ b/mdserver.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from utils import read_config, server, event_notifier +from utils import read_config, Resource, server from flask import Flask, Response config = read_config() @@ -24,9 +24,10 @@ def serve(domain, entity_id): for domain, values in config.items(): print(f"domain: {domain}") - conf = (values['metadir'], values['signer']) - server[domain] = conf + location = values['metadir'] + signer = values['signer'] + server[domain] = Resource(location, signer) + server.add_watch(domain, location) -event_notifier.start() app.run(host='127.0.0.1', port=5001) diff --git a/requirements.txt b/requirements.txt index 30cbf8e65de8695c7e1c33d72276de09efd471a2..b43dcbcd8f02c90307f745679af6e88e295cfcc5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,5 @@ python-dateutil isoduration pyyaml pyinotify +pyXMLSecurity +PyKCS11 diff --git a/signers.py b/signers.py index b2a0b61ee661a575bb9fc8629b8824bc5b8a0b7e..9168c7a4b086db7e12058849f4a7b57661147bc7 100644 --- a/signers.py +++ b/signers.py @@ -1,3 +1,4 @@ +import xmlsec from signxml import XMLSigner cert = open("meta.crt").read() @@ -17,10 +18,15 @@ def Signers(signer): print("Foobar signer") return XMLSigner().sign(xml, key=key, cert=cert) + def _hsm_signer(xml): + print("HSM signer") + return xmlsec.sign(xml, key_spec="pkcs11:///usr/lib/softhsm/libsofthsm2.so/test?pin=secret") + signers = { 'normal_signer': _normal_signer, 'test_signer': _test_signer, - 'foobar_signer': _foobar_signer + 'foobar_signer': _foobar_signer, + 'hsm_signer': _hsm_signer } return signers[signer] diff --git a/utils.py b/utils.py index 23cb4f29b99574983ab1a3feb11f03afb7a92f1a..cd665143accdbc544b9eb6d8bd3531c8eb5f16d0 100755 --- a/utils.py +++ b/utils.py @@ -9,8 +9,8 @@ import yaml import pyinotify from signers import Signers -watch_list = {} -watch_manager = pyinotify.WatchManager() +# watch_list = {} +# watch_manager = pyinotify.WatchManager() def read_config(): @@ -26,13 +26,6 @@ def hasher(entity_id): return sha1_digest -class EventProcessor(pyinotify.ProcessEvent): - def process_IN_CLOSE_WRITE(self, event): - domain = watch_list[event.path] - print(f"Notify {domain} {event.path}") - server[domain].walk_location(event.path) - - class Entity: def __init__(self): self.md = None @@ -60,7 +53,6 @@ class Resource: found = 0 removed = 0 old_idps = self.mdfiles[mdfile].copy() - print(f"old_idps: {old_idps}") tree = ET.ElementTree(file=mdfile) root = tree.getroot() ns = root.nsmap.copy() @@ -129,16 +121,35 @@ class Resource: return data +class EventProcessor(pyinotify.ProcessEvent): + def process_IN_CLOSE_WRITE(self, event): + server.process(event.path) + + class Server: - def __setitem__(self, domain, conf): - location, signer = conf - self.__dict__[domain] = Resource(location, signer) - watch_list[location] = domain - watch_manager.add_watch(location, pyinotify.IN_CLOSE_WRITE) + watch_list = {} + + def __init__(self): + self.watch_manager = pyinotify.WatchManager() + self.event_notifier = pyinotify.ThreadedNotifier(self.watch_manager, EventProcessor()) + self.event_notifier.start() + + def add_watch(self, domain, location): + self.watch_list[location] = domain + self.watch_manager.add_watch(location, pyinotify.IN_CLOSE_WRITE) + + def process(self, location): + domain = self.watch_list[location] + print(f"Notify {domain} {location}") + self.__dict__[domain].walk_location(location) + + def __setitem__(self, domain, resource): + self.__dict__[domain] = resource + # watch_list[location] = domain + # watch_manager.add_watch(location, pyinotify.IN_CLOSE_WRITE) def __getitem__(self, domain): return self.__dict__[domain] server = Server() -event_notifier = pyinotify.ThreadedNotifier(watch_manager, EventProcessor())