def test_unpack_metadata_statement_uri(): s = signer[OA['sunet']] req = MetadataStatement(issuer='https://example.org/op') # Not intermediate ms = s.create_signed_metadata_statement(req, 'discovery', single=True) jb = FSJWKSBundle('', None, 'fo_jwks', key_conv={ 'to': quote_plus, 'from': unquote_plus }) mds = MetaDataStore('msd') op = Operator(jwks_bundle=jb) op.httpcli = MockHTTPClient(mds) res = op.unpack_metadata_statement(jwt_ms=ms) assert len(res.parsed_statement) == 3 loel = op.evaluate_metadata_statement(res.result) assert len(loel) == 3 assert set([l.fo for l in loel]) == { 'https://swamid.sunet.se', 'https://edugain.com', 'https://www.feide.no' }
def test_make_signed_metadata_statement_mixed(): liss = list(FO.values()) liss.extend(list(OA.values())) key_bundle = make_fs_jwks_bundle(TEST_ISS, liss, SIGN_KEYJAR, KEYDEFS, './') operator = {} for entity, _keyjar in key_bundle.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) _spec = SMS_DEF[OA['sunet']]["discovery"][FO['swamid']] mds = MetaDataStore('mds') mds.clear() sms = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert sms _spec = SMS_DEF[OA['sunet']]["discovery"][FO['edugain']] sms = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert list(sms['ms_uri'].keys()) == [FO['edugain']] # Now parse the result _md0 = unpack_using_metadata_store(sms['ms_uri'][FO['edugain']], mds) op = Operator() _res = op.evaluate_metadata_statement(_md0) assert _res[0].le =={'federation_usage':'discovery'}
def test_pack_metadata_statement_other_alg(): _keyjar = build_keyjar(KEYDEFS)[1] op = Operator(keyjar=_keyjar, iss='https://example.com/') req = MetadataStatement(issuer='https://example.org/op') sms = op.pack_metadata_statement(req, alg='ES256') assert sms # Should be a signed JWT _jwt = factory(sms) _body = json.loads(as_unicode(_jwt.jwt.part[1])) assert _body['iss'] == 'https://example.com/' # verify signature r = _jwt.verify_compact(sms, _keyjar.get_signing_key()) assert r
def test_registration_endpoint_fed(self): request = ClientMetadataStatement( redirect_uris=['https://example.com/rp']) rp = Operator(keyjar=keybundle[FO['swamid']], iss=FO['swamid']) sms = rp.pack_metadata_statement(request, alg='RS256') request = rp.extend_with_ms(request, {FO['swamid']: sms}) resp = self.op.registration_endpoint(request.to_dict()) assert isinstance(resp, Created) assert resp.status == "201 Created" clresp = json.loads(resp.message) assert list(clresp['metadata_statements'].keys()) == [FO['swamid']]
def test_get_metadata_statement(): jb = JWKSBundle('') for iss in ['https://example.org/', 'https://example.com/']: jb[iss] = build_keyjar(KEYDEFS)[1] op = Operator(keyjar=jb['https://example.com/'], iss='https://example.com/') req = MetadataStatement(foo='bar') sms = op.pack_metadata_statement(req, alg='RS256') sms_dir = {'https://example.com': sms} req['metadata_statements'] = Message(**sms_dir) ent = FederationEntity(None, fo_bundle=jb) loe = ent.get_metadata_statement(req) assert loe
def setup(keydefs, tool_iss, liss, csms_def, oa, ms_path): sig_keys = build_keyjar(keydefs)[1] key_bundle = make_fs_jwks_bundle(tool_iss, liss, sig_keys, keydefs, './') sig_keys = build_keyjar(keydefs)[1] jb = FSJWKSBundle(tool_iss, sig_keys, 'fo_jwks', key_conv={ 'to': quote_plus, 'from': unquote_plus }) # Need to save the private parts jb.bundle.value_conv['to'] = keyjar_to_jwks_private jb.bundle.sync() operator = {} for entity, _keyjar in jb.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) signers = {} for sig, sms_def in csms_def.items(): ms_dir = os.path.join(ms_path, sig) metadata_statements = FileSystem(ms_dir) for name, spec in sms_def.items(): res = make_signed_metadata_statement(spec, operator) metadata_statements[name] = res['ms'] _iss = oa[sig] signers[_iss] = Signer( InternalSigningService(_iss, operator[_iss].keyjar), ms_dir) return signers, key_bundle
def test_make_signed_metadata_statements(): mds = MetaDataStore('mds') liss = list(FO.values()) liss.extend(list(OA.values())) key_bundle = make_fs_jwks_bundle(TEST_ISS, liss, SIGN_KEYJAR, KEYDEFS, './') operator = {} for entity, _keyjar in key_bundle.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) _spec = SMS_DEF[OA['sunet']]["discovery"][FO['swamid']] ms = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert ms _spec = SMS_DEF[OA['sunet']]["discovery"][FO['edugain']] res = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert list(res['ms_uri'].keys()) == [FO['edugain']] _spec = SMS_DEF[OA['sunet']]["discovery"][FO['example']] res = make_signed_metadata_statement(_spec, operator, mds=mds, base_uri='https:/example.org/ms') assert list(res['ms'].keys()) == [FO['example']] _jws = factory(res['ms'][FO['example']]) assert _jws
def test_pack_metadata_statement(): jb = FSJWKSBundle('', None, 'fo_jwks', key_conv={'to': quote_plus, 'from': unquote_plus}) _keyjar = build_keyjar(KEYDEFS)[1] op = Operator(keyjar=_keyjar, jwks_bundle=jb, iss='https://example.com/') req = MetadataStatement(issuer='https://example.org/op') sms = op.pack_metadata_statement(req) assert sms # Should be a signed JWT _jwt = factory(sms) assert _jwt assert _jwt.jwt.headers['alg'] == 'RS256' _body = json.loads(as_unicode(_jwt.jwt.part[1])) assert _body['iss'] == op.iss assert _body['issuer'] == 'https://example.org/op' # verify signature r = _jwt.verify_compact(sms, _keyjar.get_signing_key()) assert r
def index(self, iss, jwks, ms, **kwargs): _kj = KeyJar() _kj.import_jwks(json.loads(jwks), iss) op = Operator() try: _pi = op.unpack_metadata_statement(jwt_ms=ms, keyjar=_kj, cls=MetadataStatement) response = json.dumps(_pi.result.to_dict(), sort_keys=True, indent=2, separators=(',', ': ')) cherrypy.response.headers['Content-Type'] = 'text/plain' return as_bytes(response) except (RegistrationError, ParameterError, MissingSigningKey) as err: raise cherrypy.HTTPError( 400, as_bytes('Invalid Metadata statement: {}'.format(err)))
def __init__(self, srv, iss='', keyjar=None, signer=None, fo_bundle=None): """ :param srv: A Client or Provider instance :param iss: A identifier assigned to this entity by the operator :param keyjar: Key this entity can use to sign things :param signer: A signer to use for signing documents (client registration requests/provide info response) this entity produces. :param fo_bundle: A bundle of keys that can be used to verify the root signature of a compounded metadata statement. """ Operator.__init__(self, iss=iss, keyjar=keyjar, httpcli=srv, jwks_bundle=fo_bundle) # Who can sign request from this entity self.signer = signer self.federation = None
def init(keydefs, tool_iss, liss, lifetime): sig_keys = build_keyjar(keydefs)[1] key_bundle = make_fs_jwks_bundle(tool_iss, liss, sig_keys, keydefs, './') #sig_keys = build_keyjar(keydefs)[1] operator = {} for entity, _keyjar in key_bundle.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar, lifetime=lifetime) return {'operator': operator, 'key_bundle': key_bundle}
def test_metadatastore(): mds = MetaDataStore('mds') desc = SMS_DEF[OA['sunet']]["discovery"][FO['swamid']][0] operator = {} liss = list(FO.values()) liss.extend(list(OA.values())) key_bundle = make_fs_jwks_bundle(TEST_ISS, liss, SIGN_KEYJAR, KEYDEFS, './') for entity, _keyjar in key_bundle.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) _x = make_ms(desc, False, operator) _jws = list(_x.values())[0] mds[mds.hash(_jws)] = _jws assert mds.hash(_jws) in list(mds.keys())
def init(keydefs, tool_iss, liss): sig_keys = build_keyjar(keydefs)[1] key_bundle = make_fs_jwks_bundle(tool_iss, liss, sig_keys, keydefs, './') sig_keys = build_keyjar(keydefs)[1] jb = FSJWKSBundle(tool_iss, sig_keys, 'fo_jwks', key_conv={ 'to': quote_plus, 'from': unquote_plus }) # Need to save the private parts jb.bundle.value_conv['to'] = keyjar_to_jwks_private jb.bundle.sync() operator = {} for entity, _keyjar in key_bundle.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) return {'jb': jb, 'operator': operator, 'key_bundle': key_bundle}
import argparse import json from fedoidc import MetadataStatement, read_jwks_file from fedoidc.operator import Operator parser = argparse.ArgumentParser() parser.add_argument('-j', dest='jwks') parser.add_argument('-i', dest='iss') parser.add_argument('-r', dest='req') args = parser.parse_args() kj = read_jwks_file(args.jwks) op = Operator(keyjar=kj, iss=args.iss) _req = json.loads(open(args.req).read()) req = MetadataStatement(**_req) print(op.pack_metadata_statement(req))
#!/usr/bin/env python3 import argparse import json from fedoidc import MetadataStatement, read_jwks_file from fedoidc.operator import Operator parser = argparse.ArgumentParser() parser.add_argument('-j', dest='jwks', help="A JWKS containing the signers private keys") parser.add_argument('-i', dest='iss', help='The identifier of the signer') parser.add_argument('-r', dest='req', help='The message to sign') parser.add_argument('-l', dest='lifetime', default=86400, type=int, help="The lifetime of the signature") parser.add_argument('-f', dest='fo', help="The identifier of the federation") args = parser.parse_args() kj = read_jwks_file(args.jwks) op = Operator(keyjar=kj, iss=args.iss, lifetime=args.lifetime) _req = json.loads(open(args.req).read()) req = MetadataStatement(**_req) if args.fo: print('{}:{}'.format(args.fo, op.pack_metadata_statement(req))) else: print('{}:{}'.format(args.iss, op.pack_metadata_statement(req)))
from fedoidc.test_utils import make_signed_metadata_statement_uri from fedoidc.test_utils import MetaDataStore sys.path.insert(0, ".") config = importlib.import_module(sys.argv[1]) jb = FSJWKSBundle(config.TOOL_ISS, None, 'fo_jwks', key_conv={ 'to': quote_plus, 'from': unquote_plus }) jb.bundle.sync() operator = {} for entity, _keyjar in jb.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar) mds = MetaDataStore('mds_uri') mds.reset() base_url = '{}/mds_uri/'.format(config.TOOL_ISS) for iss, sms_def in config.SMS_DEF.items(): for context, spec in sms_def.items(): for fo, _desc in spec.items(): res = make_signed_metadata_statement_uri(_desc, operator, mds, base_url)
parser = argparse.ArgumentParser() parser.add_argument('-j', dest='jwks', help="A JWKS file that contains the federation operators public keys") parser.add_argument('-r', dest='req_jws', help="The message as a JWS") parser.add_argument('-R', dest='req_json', help="The message as a JSON doc") parser.add_argument('-f', dest='fo', help='The identifier of the Federation') parser.add_argument('-l', dest='flatten', action='store_true', help="Flatten the compounded metadata statement") args = parser.parse_args() kj = read_jwks_file(args.jwks) _bundle = JWKSBundle('') _bundle[args.fo] = kj op = Operator(jwks_bundle=_bundle) if args.req_jws: _fo, _req = open(args.req_jws).read().rsplit(':', 1) _bundle[_fo] = kj res = op.unpack_metadata_statement(jwt_ms=_req.strip()) elif args.req_json: _req = json.loads(open(args.req_json).read()) res = op.unpack_metadata_statement(json_ms=_req) else: raise Exception('Need one of -r or -R') print(res.result) loe = op.evaluate_metadata_statement(res.result)
"use": ["sig"] }] KEYS = {} ISSUER = {} OPERATOR = {} for entity in ['fo', 'fo1', 'org', 'inter', 'admin', 'ligo', 'op']: fname = os.path.join(BASE_PATH, "{}.key".format(entity)) _keydef = KEYDEFS[:] _keydef[0]['key'] = fname _jwks, _keyjar, _kidd = build_keyjar(_keydef) KEYS[entity] = {'jwks': _jwks, 'keyjar': _keyjar, 'kidd': _kidd} ISSUER[entity] = 'https://{}.example.org'.format(entity) OPERATOR[entity] = Operator(keyjar=_keyjar, iss=ISSUER[entity]) FOP = OPERATOR['fo'] FOP.jwks_bundle = JWKSBundle(FOP.iss) FOP.jwks_bundle[FOP.iss] = FOP.keyjar FO1P = OPERATOR['fo1'] FO1P.jwks_bundle = JWKSBundle(FO1P.iss) FO1P.jwks_bundle[FO1P.iss] = FO1P.keyjar ORGOP = OPERATOR['org'] ADMINOP = OPERATOR['admin'] INTEROP = OPERATOR['inter'] LIGOOP = OPERATOR['ligo'] OPOP = OPERATOR['ligo']
def fo_member(*args): _jb = JWKSBundle('https://sunet.se/op') for fo in args: _jb[fo.iss] = fo.signing_keys_as_jwks() return Operator(jwks_bundle=_jb)
import json from fedoidc import read_jwks_file from fedoidc.operator import Operator parser = argparse.ArgumentParser() parser.add_argument('-j', dest='jwks', help="A JWKS containing the signing keys for this entity") parser.add_argument( '-r', dest='req', help= "The basic message to which should be added the signing keys and metadata statements" ) parser.add_argument('-m', dest='ms', action='append', help="Metadata statements to add the basic message") args = parser.parse_args() kj = read_jwks_file(args.jwks) op = Operator(keyjar=kj) _req = json.loads(open(args.req).read()) _req['signing_keys'] = op.keyjar.export_jwks() if args.ms: _req["metadata_statements"] = dict( [open(m).read().strip().rsplit(':', 1) for m in args.ms]) print(json.dumps(_req))
#!/usr/bin/env python3 import argparse import json from fedoidc import MetadataStatement, read_jwks_file from fedoidc.operator import Operator parser = argparse.ArgumentParser() parser.add_argument('-j', dest='jwks', help="A JWKS containing the signers private keys") parser.add_argument('-i', dest='iss', help='The identifier of the signer') parser.add_argument('-r', dest='req', help='The message to sign') parser.add_argument('-l', dest='lifetime', default=86400, type=int, help="The lifetime of the signature") parser.add_argument('-f', dest='fo', help="The identifier of the federation") args = parser.parse_args() kj = read_jwks_file(args.jwks) op = Operator(keyjar=kj, iss=args.iss, lifetime=args.lifetime) _req = json.loads(open(args.req).read()) req = MetadataStatement(**_req) print(op.pack_metadata_statement(req))
import argparse from fedoidc import read_jwks_file from fedoidc.bundle import JWKSBundle from fedoidc.operator import Operator parser = argparse.ArgumentParser() parser.add_argument( '-j', dest='jwks', help="A JWKS file that contains the federation operators public keys") parser.add_argument('-r', dest='req', help="The message") parser.add_argument('-f', dest='fo', help='The identifier of the Federation') parser.add_argument('-l', dest='flatten', action='store_true', help="Flatten the compounded metadata statement") args = parser.parse_args() kj = read_jwks_file(args.jwks) _bundle = JWKSBundle('') _bundle[args.fo] = kj op = Operator(jwks_bundle=_bundle) _fo, _req = open(args.req).read().rsplit(':', 1) res = op.unpack_metadata_statement(jwt_ms=_req.strip()) print(res.result)
#!/usr/bin/env python3 import os import shutil from urllib.parse import quote_plus, unquote_plus from fedoidc.bundle import FSJWKSBundle from fedoidc.operator import Operator from fedoidc.test_utils import setup_ms import fo_conf jb = FSJWKSBundle('', fdir='fo_jwks', key_conv={ 'to': quote_plus, 'from': unquote_plus }) operator = {} for entity, _keyjar in jb.items(): operator[entity] = Operator(iss=entity, keyjar=_keyjar, lifetime=86400) # Clear out old stuff for d in ['mds', 'ms']: if os.path.isdir(d): shutil.rmtree(d) setup_ms(fo_conf.SMS_DEF, fo_conf.MS_PATH, fo_conf.MDS_DIR, fo_conf.BASE_URL, operator)