Skip to content
Snippets Groups Projects
Commit 83b52854 authored by Martin van Es's avatar Martin van Es
Browse files

Rename mdserver to mdsigner and (mdsiger to mdwriter)

parent c3fd0f94
No related branches found
No related tags found
No related merge requests found
......@@ -8,5 +8,5 @@ meta.key
hsm.crt
hsm.der
*.xml
mdserver.yaml
mdsigner.yaml
mdproxy.yaml
......@@ -12,10 +12,10 @@ Alternate MDX research project
- Download metadata file(s)
- Run one or more of the tools below
## ```mdsigner.py [mdfile] [mdfile] [mdfile] ...```
## ```mdwriter.py [mdfile] [mdfile] [mdfile] ...```
Reads source metadata file(s) and outputs them signed to filesystem
## ```mdserver.py```
## ```mdsigner.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.
......@@ -23,12 +23,12 @@ Serves and caches signed by realm signer from memory, on request
## ```mdproxy.py```
Reads config from mdproxy.yaml configuration, see example.
Caches signed and cached ```mdserver.py``` metadata requests
Caches signed and cached ```mdsigner.py``` metadata requests
## Queries
MDQ Queries can then be pointed at
- ```http://mdserver:5001/<realm>/entities/<entityid>```
- ```http://mdsigner:5001/<realm>/entities/<entityid>```
- ```http://mdproxy:5002/<realm>/entities/<entityid>```
## Bootstrap softHSM2
......
#!/usr/bin/env python
from utils import read_config, Realm, Server
from flask import Flask, Response
from datetime import datetime
from dateutil import tz
from email.utils import formatdate
from time import mktime
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
config = read_config('mdserver.yaml')
app = Flask(__name__)
server = Server()
@app.route('/<realm>/entities',
strict_slashes=False,
methods=['GET'])
def serve_all(realm):
print(f"all in {realm}")
response = Response()
response.headers['Content-Type'] = "application/samlmetadata+xml"
response.headers['Content-Disposition'] = "filename = \"metadata.xml\""
data = server[realm].all_entities()
response.data = data.md
max_age = int((data.valid_until -
datetime.now(tz.tzutc())).total_seconds())
response.headers['Cache-Control'] = f"max-age={max_age}"
response.headers['Last-Modified'] = formatdate(
timeval=mktime(data.last_modified.timetuple()),
localtime=False,
usegmt=True)
return response
@app.route('/<realm>/entities/<path:entity_id>',
strict_slashes=False,
methods=['GET'])
def serve_one(realm, entity_id):
print(f"entity_id: {entity_id}")
response = Response()
response.headers['Content-Type'] = "application/samlmetadata+xml"
response.headers['Content-Disposition'] = "filename = \"metadata.xml\""
try:
data = server[realm][entity_id]
response.data = data.md
max_age = data.max_age
last_modified = data.last_modified
except Exception:
response.data = "No valid metadata\n"
response.headers['Content-type'] = "text/html"
response.status = 404
max_age = 60
last_modified = datetime.now(tz.tzutc())
response.headers['Cache-Control'] = f"max-age={max_age}"
response.headers['Last-Modified'] = formatdate(
timeval=mktime(last_modified.timetuple()),
localtime=False,
usegmt=True)
return response
for realm, values in config.items():
print(f"realm: {realm}")
location = values['metadir']
signer = values['signer']
server[realm] = Realm(location, signer)
if __name__ == "__main__":
app.run(host='127.0.0.1', port=5001, debug=False)
#!/usr/bin/env python
import sys
import copy
from concurrent.futures import ThreadPoolExecutor
from utils import read_config, Realm, Server
from flask import Flask, Response
from datetime import datetime
from dateutil import tz
from email.utils import formatdate
from time import mktime
from lxml import etree as ET
# import traceback
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
from utils import hasher
from signers import Signers
config = read_config('mdsigner.yaml')
app = Flask(__name__)
server = Server()
# Find all IdP's in edugain metadata
idps = []
success = 0
failed = 0
maxthreads = 8
signer = Signers('normal_signer')
@app.route('/<realm>/entities',
strict_slashes=False,
methods=['GET'])
def serve_all(realm):
print(f"all in {realm}")
response = Response()
response.headers['Content-Type'] = "application/samlmetadata+xml"
response.headers['Content-Disposition'] = "filename = \"metadata.xml\""
data = server[realm].all_entities()
response.data = data.md
max_age = int((data.valid_until -
datetime.now(tz.tzutc())).total_seconds())
response.headers['Cache-Control'] = f"max-age={max_age}"
response.headers['Last-Modified'] = formatdate(
timeval=mktime(data.last_modified.timetuple()),
localtime=False,
usegmt=True)
return response
@app.route('/<realm>/entities/<path:entity_id>',
strict_slashes=False,
methods=['GET'])
def serve_one(realm, entity_id):
print(f"entity_id: {entity_id}")
response = Response()
response.headers['Content-Type'] = "application/samlmetadata+xml"
response.headers['Content-Disposition'] = "filename = \"metadata.xml\""
def sign(xml, name):
global success, failed, cert, key
# print("Signer")
try:
sha1 = hasher(name)
signed = signer(xml)
out = ET.tostring(signed, pretty_print=True).decode()
# XMLVerifier().verify(out, x509_cert=cert)
with open(f'output/{sha1}.xml', 'w') as f:
f.write(out)
success += 1
except Exception as e:
print(name)
print(f" {e}")
# traceback.print_exc()
failed += 1
with ThreadPoolExecutor(max_workers=maxthreads) as executor:
for mdfile in sys.argv[1:]:
tree = ET.ElementTree(file=mdfile)
root = tree.getroot()
ns = copy.deepcopy(root.nsmap)
ns['xml'] = 'http://www.w3.org/XML/1998/namespace'
for idp in root.findall('md:EntityDescriptor', ns):
entityID = idp.attrib.get('entityID', 'none')
if entityID not in idps:
idps.append(entityID)
executor.submit(sign, idp, entityID)
print(f"Succeeded: {success}")
print(f"Failed: {failed}")
data = server[realm][entity_id]
response.data = data.md
max_age = data.max_age
last_modified = data.last_modified
except Exception:
response.data = "No valid metadata\n"
response.headers['Content-type'] = "text/html"
response.status = 404
max_age = 60
last_modified = datetime.now(tz.tzutc())
response.headers['Cache-Control'] = f"max-age={max_age}"
response.headers['Last-Modified'] = formatdate(
timeval=mktime(last_modified.timetuple()),
localtime=False,
usegmt=True)
return response
for realm, values in config.items():
print(f"realm: {realm}")
location = values['metadir']
signer = values['signer']
server[realm] = Realm(location, signer)
if __name__ == "__main__":
app.run(host='127.0.0.1', port=5001, debug=False)
[Unit]
Description=MDServer
Description=MDSigner
After=syslog.target network.target
[Service]
Type=simple
WorkingDirectory=/opt/alternate-mdx
ExecStart=/opt/alternate-mdx/bin/python -u mdserver.py
ExecStart=/opt/alternate-mdx/bin/python -u mdsigner.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=10
SyslogIdentifier=mdserver
SyslogIdentifier=mdsigner
[Install]
WantedBy=multi-user.target
#!/usr/bin/env python
import sys
import copy
from concurrent.futures import ThreadPoolExecutor
from lxml import etree as ET
# import traceback
from utils import hasher
from signers import Signers
# Find all IdP's in edugain metadata
idps = []
success = 0
failed = 0
maxthreads = 8
signer = Signers('normal_signer')
def sign(xml, name):
global success, failed, cert, key
# print("Signer")
try:
sha1 = hasher(name)
signed = signer(xml)
out = ET.tostring(signed, pretty_print=True).decode()
# XMLVerifier().verify(out, x509_cert=cert)
with open(f'output/{sha1}.xml', 'w') as f:
f.write(out)
success += 1
except Exception as e:
print(name)
print(f" {e}")
# traceback.print_exc()
failed += 1
with ThreadPoolExecutor(max_workers=maxthreads) as executor:
for mdfile in sys.argv[1:]:
tree = ET.ElementTree(file=mdfile)
root = tree.getroot()
ns = copy.deepcopy(root.nsmap)
ns['xml'] = 'http://www.w3.org/XML/1998/namespace'
for idp in root.findall('md:EntityDescriptor', ns):
entityID = idp.attrib.get('entityID', 'none')
if entityID not in idps:
idps.append(entityID)
executor.submit(sign, idp, entityID)
print(f"Succeeded: {success}")
print(f"Failed: {failed}")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment