def test_remove_after(): # initial keyjar keyjar = build_keyjar(KEYDEFS)[1] _old = [k.kid for k in keyjar.get_issuer_keys('') if k.kid] assert len(_old) == 2 # rotate_keys = create new keys + make the old as inactive keyjar = build_keyjar(KEYDEFS, keyjar=keyjar)[1] keyjar.remove_after = 1 # None are remove since none are marked as inactive yet keyjar.remove_outdated() _interm = [k.kid for k in keyjar.get_issuer_keys('') if k.kid] assert len(_interm) == 4 # Now mark the keys to be inactivated _now = time.time() for k in keyjar.get_issuer_keys(''): if k.kid in _old: if not k.inactive_since: k.inactive_since = _now with freeze_time(dt.now()) as frozen: # this should remove all the old ones frozen.tick(delta=timedelta(seconds=2)) keyjar.remove_outdated() # The remainder are the new keys _new = [k.kid for k in keyjar.get_issuer_keys('') if k.kid] assert len(_new) == 2 # should not be any overlap between old and new assert set(_new).intersection(set(_old)) == set()
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 rotate_keys(self, keyconf=None): _old = [k.kid for k in self.keyjar.get_issuers_keys('') if k.kid] if keyconf: self.keyjar = build_keyjar(keyconf, keyjar=self.keyjar)[1] else: self.keyjar = build_keyjar(self.keyconf, keyjar=self.keyjar)[1] for k in self.keyjar.get_issuers_keys(''): if k.kid in _old: if not k.inactive_since: k.inactive_since = time.time()
def create_federation_entity(iss, conf, fos, sup, entity=''): _keybundle = FSJWKSBundle('', fdir=conf.JWKS_DIR, key_conv={ 'to': quote_plus, 'from': unquote_plus }) # Organisation information _kj = _keybundle[sup] fname = os.path.join(conf.MS_DIR, quote_plus(sup)) signer = Signer(InternalSigningService(sup, _kj), fname) # And then the FOs jb = JWKSBundle('') for fo in fos: jb[fo] = _keybundle[fo] # The OPs own signing keys _keys = build_keyjar(conf.SIG_DEF_KEYS)[1] return FederationEntity(entity, iss=iss, keyjar=_keys, signer=signer, fo_bundle=jb)
def test_dump_private_jwks(): keys = [ { "type": "RSA", "use": ["enc", "sig"] }, { "type": "EC", "crv": "P-256", "use": ["sig"] }, ] jwks, keyjar, kidd = build_keyjar(keys) kbl = keyjar.issuer_keys[''] dump_jwks(kbl, 'foo.jwks', private=True) kb_public = KeyBundle(source='file://./foo.jwks') # All RSA keys for k in kb_public.keys(): if k.kty == 'RSA': assert k.d assert k.p assert k.q else: # MUST be 'EC' assert k.d
def rotate_keys(self, keyconf=None): _old = [k.kid for k in self.keyjar.get_issuer_keys('') if k.kid] if keyconf: self.keyjar = build_keyjar(keyconf, keyjar=self.keyjar)[1] else: self.keyjar = build_keyjar(self.keyconf, keyjar=self.keyjar)[1] self.keyjar.remove_after = self.remove_after self.keyjar.remove_outdated() _now = time.time() for k in self.keyjar.get_issuer_keys(''): if k.kid in _old: if not k.inactive_since: k.inactive_since = _now
def test_dump_public_jwks(): keys = [ { "type": "RSA", "use": ["enc", "sig"] }, { "type": "EC", "crv": "P-256", "use": ["sig"] }, ] jwks, keyjar, kidd = build_keyjar(keys) kbl = keyjar.issuer_keys[""] dump_jwks(kbl, "foo.jwks") kb_public = KeyBundle(source="file://./foo.jwks") # All RSA keys for k in kb_public.keys(): if k.kty == "RSA": assert not k.d assert not k.p assert not k.q else: # MUST be 'EC' assert not k.d
def __init__(self, keyjar=None, fo_keyjar=None, httpcli=None, jwks_file='', iss=None, keyconf=None, bundle_sign_alg='RS256'): Operator.__init__(self, keyjar=keyjar, fo_keyjar=fo_keyjar, httpcli=httpcli, iss=iss, jwks_file=jwks_file) if self.keyjar is None: self.keyjar = build_keyjar(keyconf)[1] if jwks_file: fp = open(jwks_file, 'w') fp.write(json.dumps(self.keyjar.export_jwks(private=True))) fp.close() self.keyconf = keyconf self.bundle_sign_alg = bundle_sign_alg self.jb = JWKSBundle(iss, self.keyjar)
def test_client_registration_with_software_statement(self): jwks, keyjar, kidd = build_keyjar(KEYS) fed_operator = 'https://fedop.example.org' self.provider.keyjar[fed_operator] = keyjar[''] ss = make_software_statement(keyjar, fed_operator, client_id='foxtrot') args = { "redirect_uris": [ "https://client.example.org/callback", "https://client.example.org/callback2" ], "client_name": "XYZ Service B", "token_endpoint_auth_method": "client_secret_basic", "scope": "read write dolphin", 'software_statement': ss } request = RegistrationRequest(**args) resp = self.provider.registration_endpoint(request=request.to_json(), environ={}) cli_resp = ClientInfoResponse().from_json(resp.message) assert cli_resp
def test_get_cert_key(): port = "8565" iss = "https://localhost:{}/static/keys/key.pub".format(port) sws_data = {"iss": iss, "redirect_uris": ["https://example.com"]} key = [ {"type": "RSA", "key": os.path.join(PATH, "keys/private.key"), "use": ["enc", "sig"]}, ] jwks, keyjar, _ = build_keyjar(key) responses.add(responses.GET, iss, body=json.dumps(jwks), status=200, content_type='application/json') trusted_domains = ["https://localhost:8565"] sws_m = SWSMessage(trusted_domains=trusted_domains, verify_signer_ssl=False, **sws_data) downloaded_key = sws_m._get_cert_key(iss) assert downloaded_key == keyjar.get_verify_key(owner="") with pytest.raises(SchemeError): sws_m._get_cert_key("http://example.com") trusted_domains = ["http://localhost:8565"] sws_m = SWSMessage(trusted_domains=trusted_domains, verify_signer_ssl=False, **sws_data) with pytest.raises(UntrustedDomainException): sws_m._get_cert_key(iss)
def test_key_rotation(): _keyjar = build_keyjar(KEYDEFS)[1] fo = FederationOperator(iss='https://example.com/op', keyjar=_keyjar, keyconf=KEYDEFS, remove_after=1) fo.rotate_keys() assert len(fo.keyjar.get_issuer_keys('')) == 4 time.sleep(1) fo.rotate_keys() assert len(fo.keyjar.get_issuer_keys('')) == 4
def test_build_keyjar_missing(tmpdir): keys = [{"type": "RSA", "key": os.path.join(tmpdir.dirname, "missisng_file"), "use": ["enc", "sig"]}] jwks, keyjar, kidd = build_keyjar(keys) assert len(keyjar[""]) == 1 assert "RSA" in kidd["enc"] assert "RSA" in kidd["sig"]
def test_ace(): jb = JWKSBundle('') for iss in ['https://example.org/', 'https://example.com/']: jb[iss] = build_keyjar(KEYDEFS)[1] kj = build_keyjar(KEYDEFS)[1] sign_serv = InternalSigningService('https://signer.example.com', signing_keys=kj) signer = Signer(sign_serv) signer.metadata_statements['response'] = { 'https://example.org/': 'https://example.org/sms1' } ent = FederationEntity(None, keyjar=kj, signer=signer, fo_bundle=jb) req = MetadataStatement(foo='bar') ent.ace(req, ['https://example.org/'], 'response') assert 'metadata_statements' in req assert 'signing_keys' not in req
def create_software_statement(sws_data): sws_data["iss"] = "https://{host}:{port}/static/jwks.json".format(host=HOST, port=PORT) sws = SWSMessage() sws.from_dict(sws_data) _, keyjar, _ = build_keyjar(KEYS) alg = 'RS256' ckey = keyjar.get_signing_key(alg2keytype(alg), "", alg=alg) return sws.to_jwt(key=ckey, algorithm=alg)
def test_static_jwk(): _info = setup_conv() oper = AsyncAuthn(_info['conv'], _info['io'], None) oper.conv.entity.keyjar = build_keyjar(KEYDEFS)[1] oper.req_args["jwks_uri"] = 'https://example.org/jwks_uri' args = None static_jwk(oper, args) assert 'jwks_uri' not in oper.req_args assert 'jwks' in oper.req_args
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 get_signing_keys(iss, keydef, key_file): if os.path.isfile(key_file): kj = KeyJar() kj.import_jwks(json.loads(open(key_file, 'r').read()), iss) else: kj = build_keyjar(keydef)[1] # make it know under both names fp = open(key_file, 'w') fp.write(json.dumps(kj.export_jwks())) fp.close() kj.issuer_keys[iss] = kj.issuer_keys[''] return kj
def own_sign_keys(sigkey_name, issuer, sig_def_keys): try: jwks = json.loads(open(sigkey_name, 'r').read()) sign_kj = KeyJar() sign_kj.import_jwks(jwks, issuer) except FileNotFoundError: jwks, sign_kj, _ = build_keyjar(sig_def_keys) sign_kj.issuer_keys[issuer] = sign_kj.issuer_keys[''] fp = open(sigkey_name, 'w') fp.write(json.dumps(sign_kj.export_jwks(private=True, issuer=issuer))) fp.close() return sign_kj
def test_create_verify(): sign_keyjar = build_keyjar(KEYDEFS)[1] jb = make_jwks_bundle('https://example.com', ['fo0', 'fo1', 'fo2', 'fo3'], sign_keyjar, KEYDEFS) _jws = jb.create_signed_bundle() _jwks = sign_keyjar.export_jwks() kj = KeyJar() kj.import_jwks(_jwks, 'https://example.com') bundle = verify_signed_bundle(_jws, kj) assert bundle
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}
def authenticate(self, uid): #TODO: Why did I have to do this? I am not sure this is correct keys = [ {"type": "RSA", "key": "keys/key.pem", "use": ["enc", "sig"]}, ] _, keyjar, _ = build_keyjar(keys) cherrypy.session["client"] = Client(verify_ssl=self.verify_ssl, keyjar=keyjar) # webfinger+registration self.rp.register_with_dynamic_provider(cherrypy.session, uid) # auth req redirect_url = self.rp.make_authentication_request(cherrypy.session) raise cherrypy.HTTPRedirect(redirect_url, 303)
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_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 authenticate(self, uid): #TODO: Why did I have to do this? I am not sure this is correct keys = [ {"type": "RSA", "key": "../simple_op/keys/key.pem", "use": ["enc", "sig"]}, ] _, keyjar, _ = build_keyjar(keys) cherrypy.session["client"] = Client(verify_ssl=self.verify_ssl, keyjar=keyjar) # webfinger+registration self.rp.register_with_dynamic_provider(cherrypy.session, uid) # auth req redirect_url = self.rp.make_authentication_request(cherrypy.session) raise cherrypy.HTTPRedirect(redirect_url, 303)
def main_setup(log): from oidctest import profiles from oidctest import oper parser = argparse.ArgumentParser() parser.add_argument('-f', dest='flows') parser.add_argument('-l', dest="log_name") parser.add_argument('-p', dest="profile") parser.add_argument(dest="config") cargs = parser.parse_args() if "/" in cargs.flows: head, tail = os.path.split(cargs.flows) sys.path.insert(0, head) FLOWS = importlib.import_module(tail) else: FLOWS = importlib.import_module(cargs.flows) CONF = importlib.import_module(cargs.config) if cargs.log_name: setup_logger(log, cargs.log_name) else: setup_logger(log) # Add own keys for signing/encrypting JWTs try: jwks, keyjar, kidd = build_keyjar(CONF.keys) except KeyError: raise else: # export JWKS p = urlparse(CONF.KEY_EXPORT_URL) with open("." + p.path, "w") as f: f.write(json.dumps(jwks)) jwks_uri = p.geturl() return { "base_url": CONF.BASE, "kidd": kidd, "jwks_uri": jwks_uri, "flows": FLOWS.FLOWS, "conf": CONF, "cinfo": CONF.INFO, "orddesc": FLOWS.ORDDESC, "profiles": profiles, "operations": oper, "profile": cargs.profile }
def test_build_keyjar(): keys = [ {"type": "RSA", "use": ["enc", "sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, ] jwks, keyjar, kidd = build_keyjar(keys) for key in jwks["keys"]: assert "d" not in key # the JWKS shouldn't contain the private part of the keys assert len(keyjar[""]) == 2 # 1 with RSA keys and 1 with EC key assert "RSA" in kidd["enc"] assert "RSA" in kidd["sig"] assert "EC" in kidd["sig"]
def make_client(**kw_args): _, _keyjar, _ = build_keyjar(kw_args["conf"].keys) _cli = Client(client_authn_method=CLIENT_AUTHN_METHOD, keyjar=_keyjar) _cli.kid = kw_args["kidd"] _cli.jwks_uri = kw_args["jwks_uri"] try: _cli_info = kw_args["conf"].INFO["client"] except KeyError: pass else: for arg, val in _cli_info.items(): setattr(_cli, arg, val) return _cli
def make_bundle(tool_iss, fo_iss, sign_keyjar, keydefs, base_path=''): _operator = {} for entity in fo_iss: fname = quote_plus(os.path.join(base_path, "{}.key".format(entity))) _keydef = keydefs[:] _keydef[0]['key'] = fname _jwks, _keyjar, _kidd = build_keyjar(_keydef) _operator[entity] = _jwks jb = JWKSBundle(tool_iss, sign_keyjar) for iss, jwks in _operator.items(): jb[iss] = jwks return jb
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 fed_setup(iss, provider, conf): bundle = FSJWKSBundle(iss, fdir=conf.JWKS_DIR, key_conv={ 'to': quote_plus, 'from': unquote_plus }) sig_keys = build_keyjar(conf.SIG_KEYS)[1] provider.federation_entity = FederationEntity( provider, iss=iss, keyjar=sig_keys, fo_bundle=bundle, signed_metadata_statements_dir=conf.SMS_DIR) provider.fo_priority = conf.FO_PRIORITY
def get_jwks(path, private_path): if os.path.isfile(private_path): _jwks = open(path, 'r').read() _kj = KeyJar() _kj.import_jwks(json.loads(_jwks), '') else: _kj = build_keyjar(config.ENT_KEYS)[1] jwks = _kj.export_jwks(private=True) fp = open(private_path, 'w') fp.write(json.dumps(jwks)) fp.close() jwks = _kj.export_jwks() # public part fp = open(path, 'w') fp.write(json.dumps(jwks)) fp.close() return _kj
def test_dump_private_jwks(): keys = [ {"type": "RSA", "use": ["enc", "sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, ] jwks, keyjar, kidd = build_keyjar(keys) kbl = keyjar.issuer_keys[''] dump_jwks(kbl, 'foo.jwks', private=True) kb_public = KeyBundle(source='file://./foo.jwks') # All RSA keys for k in kb_public.keys(): if k.kty == 'RSA': assert k.d assert k.p assert k.q else: # MUST be 'EC' assert k.d
def main_setup(log): from oidctest import profiles from oidctest import oper parser = argparse.ArgumentParser() parser.add_argument('-f', dest='flows') parser.add_argument('-l', dest="log_name") parser.add_argument('-p', dest="profile") parser.add_argument(dest="config") cargs = parser.parse_args() if "/" in cargs.flows: head, tail = os.path.split(cargs.flows) sys.path.insert(0, head) FLOWS = importlib.import_module(tail) else: FLOWS = importlib.import_module(cargs.flows) CONF = importlib.import_module(cargs.config) if cargs.log_name: setup_logger(log, cargs.log_name) else: setup_logger(log) # Add own keys for signing/encrypting JWTs try: jwks, keyjar, kidd = build_keyjar(CONF.keys) except KeyError: raise else: # export JWKS p = urlparse(CONF.KEY_EXPORT_URL) with open("." + p.path, "w") as f: f.write(json.dumps(jwks)) jwks_uri = p.geturl() return {"base_url": CONF.BASE, "kidd": kidd, "jwks_uri": jwks_uri, "flows": FLOWS.FLOWS, "conf": CONF, "cinfo": CONF.INFO, "orddesc": FLOWS.ORDDESC, "profiles": profiles, "operations": oper, "profile": cargs.profile}
def test_client_registration_with_software_statement(self): jwks, keyjar, kidd = build_keyjar(KEYS) fed_operator = 'https://fedop.example.org' self.provider.keyjar[fed_operator] = keyjar[''] ss = make_software_statement(keyjar, fed_operator, client_id='foxtrot') args = { "redirect_uris": ["https://client.example.org/callback", "https://client.example.org/callback2"], "client_name": "XYZ Service B", "token_endpoint_auth_method": "client_secret_basic", "scope": "read write dolphin", 'software_statement': ss } request = RegistrationRequest(**args) resp = self.provider.registration_endpoint(request=request.to_json(), environ={}) cli_resp = ClientInfoResponse().from_json(resp.message) assert cli_resp
def create_provider(self): sunet_op = 'https://www.sunet.se/op' _kj = build_keyjar(KEYDEFS)[1] fed_ent = FederationEntity(None, keyjar=_kj, iss=sunet_op, signer=signer[OA['sunet']], fo_bundle=keybundle) self.op = Provider(sunet_op, SessionDB(sunet_op), {}, AUTHN_BROKER, USERINFO, AUTHZ, client_authn=verify_client, symkey=SYMKEY, federation_entity=fed_ent) self.op.baseurl = self.op.name self.op.signer = signer[OA['sunet']]
def create_federation_entity(iss, jwks_dir, sup='', fo_jwks=None, ms_dir='', entity=None, sig_keys=None, sig_def_keys=None): fname = os.path.join(ms_dir, quote_plus(sup)) if fo_jwks: _keybundle = FSJWKSBundle('', fdir=fo_jwks, key_conv={ 'to': quote_plus, 'from': unquote_plus }) # Organisation information _kj = _keybundle[sup] signer = Signer(InternalSigningService(sup, _kj), ms_dir=fname) else: signer = Signer(ms_dir=fname) # And then the FOs public keys _public_keybundle = FSJWKSBundle('', fdir=jwks_dir, key_conv={ 'to': quote_plus, 'from': unquote_plus }) # The OPs own signing keys if sig_keys is None: sig_keys = build_keyjar(sig_def_keys)[1] return FederationEntity(entity, iss=iss, keyjar=sig_keys, signer=signer, fo_bundle=_public_keybundle)
def test_valid_signature(): sig_pem_file = open(os.path.join(PATH, "keys/private.key")) signing_pem = sig_pem_file.read() sig_pem_file.close() key = [ {"type": "RSA", "key": os.path.join(PATH, "keys/private.key"), "use": ["enc", "sig"]}, ] jwks, _, _ = build_keyjar(key) iss = "https://test.com" trusted_domains = [iss] sws_data = {"iss": iss, "redirect_uris": ["https://example.com"]} signed_sws_jwt = _create_sig_sws(sws_data, signing_pem) responses.add(responses.GET, iss, body=json.dumps(jwks), status=200, content_type='application/json') sws_m = SWSMessage(trusted_domains=trusted_domains) sws_m.from_jwt(signed_sws_jwt)
def make_jwks_bundle(iss, fo_liss, sign_keyjar, keydefs, base_path=''): """ Given a list of Federation identifiers creates a FSJWKBundle containing all the signing keys. :param iss: The issuer ID of the entity owning the JWKSBundle :param fo_liss: List of federation identifiers :param sign_keyjar: Keys that the JWKSBundel owner can use to sign an export version of the JWKS bundle. :param keydefs: What type of keys that should be created for each federation. The same for all of them. :return: A JWKSBundle instance. """ jb = JWKSBundle(iss, sign_keyjar) for entity in fo_liss: _keydef = copy.deepcopy(keydefs) _jwks, _keyjar, _kidd = build_keyjar(_keydef) jb[entity] = _keyjar return jb
__author__ = 'rohe0002' keys = [ {"type": "RSA", "use": ["sig"]}, {"type": "RSA", "use": ["enc"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["enc"]}, ] keym = [ {"type": "RSA", "use": ["sig"]}, {"type": "RSA", "use": ["sig"]}, {"type": "RSA", "use": ["sig"]}, ] KEYJAR = build_keyjar(keys)[1] IKEYJAR = build_keyjar(keys)[1] IKEYJAR.issuer_keys['issuer'] = IKEYJAR.issuer_keys[''] del IKEYJAR.issuer_keys[''] KEYJARS = {} for iss in ['A', 'B', 'C']: _kj = build_keyjar(keym)[1] _kj.issuer_keys[iss] = _kj.issuer_keys[''] del _kj.issuer_keys[''] KEYJARS[iss] = _kj def url_compare(url1, url2): url1 = urlparse(url1) url2 = urlparse(url2)
def create_provider(self): jwks, keyjar, kidd = build_keyjar(KEYS) self.keyjar = keyjar self.issuer = 'https://fedop.example.org'
def construct_app_args(args, oper, func, default_profiles): """ :param args: Command arguments, argparse instance :param oper: Operations module :param func: Functions module :param default_profiles: The default profiles module :return: Application arguments """ sys.path.insert(0, ".") CONF = importlib.import_module(args.config) #setup_logging("%s/rp_%s.log" % (SERVER_LOG_FOLDER, CONF.PORT), logger) fdef = {'Flows': {}, 'Order': [], 'Desc': {}} cls_factories = {'': oper.factory} func_factory = func.factory for flow_def in args.flows: spec = parse_yaml_conf(flow_def, cls_factories, func_factory) fdef['Flows'].update(spec['Flows']) fdef['Desc'].update(spec['Desc']) fdef['Order'].extend(spec['Order']) if args.profiles: profiles = importlib.import_module(args.profiles) else: profiles = default_profiles try: if args.operations: operations = importlib.import_module(args.operations) else: operations = oper except AttributeError: operations = oper # Add own keys for signing/encrypting JWTs jwks, keyjar, kidd = build_keyjar(CONF.KEYS) try: if args.staticdir: _sdir = args.staticdir else: _sdir = 'static' except AttributeError: _sdir = 'static' # If this instance is behind a reverse proxy or on its own if CONF.BASE.endswith('/'): CONF.BASE = CONF.BASE[:-1] if args.path2port: ppmap = read_path2port_map(args.path2port) _path = ppmap[str(CONF.PORT)] if args.xport: _port = CONF.PORT _base = '{}:{}/{}/'.format(CONF.BASE, str(CONF.PORT), _path) else: _base = '{}/{}/'.format(CONF.BASE, _path) if args.tls: _port = 443 else: _port = 80 else: _port = CONF.PORT if _port not in [443, 80]: _base = '{}:{}'.format(CONF.BASE, _port) else: _base = CONF.BASE _path = '' # -------- JWKS --------------- if args.path2port: jwks_uri = "{}{}/jwks_{}.json".format(_base, _sdir, _port) f = open('{}/jwks_{}.json'.format(_sdir, _port), "w") elif _port not in [443, 80]: jwks_uri = "{}:{}/{}/jwks_{}.json".format(CONF.BASE, _port, _sdir, _port) f = open('{}/jwks_{}.json'.format(_sdir, _port), "w") else: jwks_uri = "{}/{}/jwks.json".format(CONF.BASE, _sdir) f = open('{}/jwks.json'.format(_sdir), "w") f.write(json.dumps(jwks)) f.close() # -------- MAKO setup ----------- try: if args.makodir: _dir = args.makodir if not _dir.endswith("/"): _dir += "/" else: _dir = "./" except AttributeError: _dir = './' LOOKUP = TemplateLookup(directories=[_dir + 'templates', _dir + 'htdocs'], module_directory=_dir + 'modules', input_encoding='utf-8', output_encoding='utf-8') _client_info = CONF.CLIENT # Now when the basci URL for the RP is constructed update the # redirect_uris and the post_logout_redirect_uris try: ri = _client_info['registration_info'] except KeyError: pass else: ri['redirect_uris'] = [r.format(_base) for r in ri['redirect_uris']] try: ri['post_logout_redirect_uris'] = [r.format(_base) for r in ri['post_logout_redirect_uris']] except KeyError: pass _base += '/' _client_info.update( {"base_url": _base, 'client_id': _base, "kid": kidd, "keyjar": keyjar, "jwks_uri": jwks_uri} ) if args.insecure: _client_info['verify_ssl'] = False # Test profile either as a command line argument or if not that # from the configuration file if args.profile: _profile = args.profile else: _profile = CONF.TOOL['profile'] # Application arguments app_args = { "flows": fdef['Flows'], "conf": CONF, "client_info": _client_info, "order": fdef['Order'], "profiles": profiles, "operation": operations, "cache": {}, "profile": _profile, "lookup": LOOKUP, "desc": fdef['Desc'], } return _path, app_args
# created, with their type, name and usage (encryption of signature) key = create_and_store_rsa_key_pair("foo", size=4096) key2 = create_and_store_rsa_key_pair("foo2", size=4096) rsa = RSAKey().load_key(key) print "--- JWK ---" print json.dumps(rsa.serialize(), sort_keys=True, indent=4, separators=(',', ': ')) print ######################################################## keys = KEYS() keys.wrap_add(key, use="sig", kid="rsa1") keys.wrap_add(key2, use="enc", kid="rsa1") print "--- JWKS---" print keys.dump_jwks() print ######################################################## key_conf = [ {"type": "RSA", "name": "rsa_key", "use": ["enc", "sig"]}, {"type": "EC", "name": "elliptic_curve_1", "crv": "P-256", "use": ["sig"]}, {"type": "EC", "name": "elliptic_curve_2", "crv": "P-256", "use": ["enc"]} ] jwks, keyjar, kdd = build_keyjar(key_conf, "m%d", None, None) print "--- JWKS from keyjar ---" print jwks
def print_private_key(keyjar, headline): _jwks = keyjar.issuer_keys[""][0].jwks(private=True) # Only one bundle print(70 * "-") print(headline) print(70 * "-") print_lines(json.dumps(json.loads(_jwks), sort_keys=True, indent=2, separators=(",", ": "))) key_conf = [{"type": "RSA", "use": ["sig"]}] # ----------------------------------------------------------------------------- # FO get's its key pair # ----------------------------------------------------------------------------- fo_jwks, fo_keyjar = build_keyjar(key_conf)[:-1] print_private_key(fo_keyjar, "FO's key pair") # ----------------------------------------------------------------------------- # Create initial RP key pair (A) # ----------------------------------------------------------------------------- pub_jwks, a_keyjar, kdd = build_keyjar(key_conf) print_private_key(a_keyjar, "Primary signing key") # ----------------------------------------------------------------------------- # -- construct JSON document to be signed by FO # -----------------------------------------------------------------------------
print(70 * "-") print(headline) print(70 * "-") print_lines(json.dumps(json.loads(_jwks), sort_keys=True, indent=2, separators=(',', ': '))) key_conf = [ {"type": "RSA", "use": ["sig"]}, ] # ----------------------------------------------------------------------------- # FO get's its key pair # ----------------------------------------------------------------------------- swamid_issuer = 'https://swamid.sunet.se/' swamid_jwks, swamid_keyjar = build_keyjar(key_conf)[:-1] print_private_key(swamid_keyjar, "SWAMID's key pair") incommon_issuer = 'https://www.incommon.org' incommon_jwks, incommon_keyjar = build_keyjar(key_conf)[:-1] print_private_key(incommon_keyjar, "InCommon's key pair") # ----------------------------------------------------------------------------- # Create initial Developer key pair (A) # ----------------------------------------------------------------------------- dev_swamid_jwks, dev_swamid_keyjar, _ = build_keyjar(key_conf) print_private_key(dev_swamid_keyjar, "Developers SWAMID signing key")
] def create_software_statement(sws_data): sws_data["iss"] = "https://{host}:{port}/static/jwks.json".format(host=HOST, port=PORT) sws = SWSMessage() sws.from_dict(sws_data) _, keyjar, _ = build_keyjar(KEYS) alg = 'RS256' ckey = keyjar.get_signing_key(alg2keytype(alg), "", alg=alg) return sws.to_jwt(key=ckey, algorithm=alg) if __name__ == '__main__': if not os.path.exists("static"): os.makedirs("static") JWKS, _, _ = build_keyjar(KEYS) JWKS_PATH = "static/jwks.json" F = open(JWKS_PATH, "w") F.write(json.dumps(JWKS)) F.close() HTTPD = HTTPServer((HOST, PORT), SimpleHTTPRequestHandler) HTTPD.socket = ssl.wrap_socket(HTTPD.socket, certfile='cp_keys/cert.pem', server_side=True, keyfile="cp_keys/key.pem") print("serving at port", PORT) HTTPD.serve_forever()
'session.auto': True, 'session.timeout': 900 } FLOWS = importlib.import_module(cargs.flows) CONF = importlib.import_module(cargs.config) SERVER_ENV.update({"template_lookup": LOOKUP, "base_url": CONF.BASE}) SRV = wsgiserver.CherryPyWSGIServer(('0.0.0.0', CONF.PORT), SessionMiddleware(application, session_opts)) # Add own keys for signing/encrypting JWTs try: jwks, KEYJAR, KIDD = build_keyjar(CONF.keys) except KeyError: pass else: # export JWKS p = urlparse(CONF.KEY_EXPORT_URL) f = open("."+p.path, "w") f.write(json.dumps(jwks)) f.close() JWKS_URI = p.geturl() if CONF.BASE.startswith("https"): from cherrypy.wsgiserver import ssl_pyopenssl SRV.ssl_adapter = ssl_pyopenssl.pyOpenSSLAdapter( CONF.SERVER_CERT, CONF.SERVER_KEY, CONF.CA_BUNDLE)
client_reg["redirect_uris"]] session_opts = { 'session.type': 'memory', 'session.cookie_expires': True, 'session.auto': True, 'session.key': "{}.beaker.session.id".format( urlparse(_conf.BASE).netloc.replace(":", ".")) } try: key_spec = _conf.KEY_SPECIFICATION except AttributeError: jwks_info = {} else: jwks, keyjar, kidd = build_keyjar(key_spec) jwks_info = { 'jwks_uri': '{}static/jwks_uri.json'.format(_base), 'keyjar': keyjar, 'kid': kidd } f = open('static/jwks_uri.json', 'w') f.write(json.dumps(jwks)) f.close() try: ctype = _conf.CLIENT_TYPE except KeyError: ctype = 'OIDC' if ctype == 'OIDC':
# dealing with authorization AUTHZ = AuthzHandling() SYMKEY = rndstr(16) # symmetric key used to encrypt cookie info USERINFO = UserInfo(USERDB) 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], jwks=_jwks) FOP = OPERATOR['fo'] FOP.fo_keyjar = FOP.keyjar FO1P = OPERATOR['fo1'] FO1P.fo_keyjar = FO1P.keyjar ORGOP = OPERATOR['org'] ADMINOP = OPERATOR['admin'] INTEROP = OPERATOR['inter'] LIGOOP = OPERATOR['ligo'] OPOP = OPERATOR['op']
def create_db(self): self.uas = UmaAS() self.uas.keyjar = build_keyjar(KEYDEF)[1]
parser.add_argument(dest="config") cargs = parser.parse_args() cls_factories = {'': oper.factory} func_factory = func.factory FLOWS = parse_yaml_conf(cargs.yaml_flows, cls_factories, func_factory) CONF = importlib.import_module(cargs.config) if cargs.log_name: setup_logger(logger, cargs.log_name) else: setup_logger(logger) # Add own keys for signing/encrypting JWTs jwks, keyjar, kidd = build_keyjar(CONF.KEYS) # export JWKS p = urlparse(CONF.KEY_EXPORT_URL) f = open("." + p.path, "w") f.write(json.dumps(jwks)) f.close() jwks_uri = p.geturl() _client_info = CONF.CLIENT _client_info.update( { "base_url": CONF.BASE, "kidd": kidd, "keyjar": keyjar, "jwks_uri": jwks_uri, }) if cargs.insecure:
if tail.endswith(".py"): tail = tail[:-3] FLOWS = importlib.import_module(tail) else: FLOWS = importlib.import_module(cargs.flows) CONF = importlib.import_module(cargs.config) if cargs.log_name: setup_logger(logger, cargs.log_name) else: setup_logger(logger) # Add own keys for signing/encrypting JWTs try: jwks, keyjar, kidd = build_keyjar(CONF.keys) except KeyError: pass else: # export JWKS p = urlparse(CONF.KEY_EXPORT_URL) f = open("."+p.path, "w") f.write(json.dumps(jwks)) f.close() jwks_uri = p.geturl() kwargs = {"base_url": CONF.BASE, "kidd": kidd, "keyjar": keyjar, "jwks_uri": jwks_uri, "flows": FLOWS.FLOWS, "conf": CONF, "cinfo": CONF.INFO, "orddesc": FLOWS.ORDDESC, "profiles": profiles, "operations": oper, "profile": cargs.profile}
from oic.utils.jwt import JWT from oic.utils.keyio import build_keyjar from utils_for_tests import _eq __author__ = 'roland' BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "data/keys")) keys = [ {"type": "RSA", "key": os.path.join(BASE_PATH, "cert.key"), "use": ["enc", "sig"]}, {"type": "EC", "crv": "P-256", "use": ["sig"]}, {"type": "EC", "crv": "P-256", "use": ["enc"]} ] jwks, keyjar, kidd = build_keyjar(keys) issuer = 'https://fedop.example.org' def test_jwt_pack(): _jwt = JWT(keyjar, lifetime=3600, iss=issuer).pack() assert _jwt assert len(_jwt.split('.')) == 3 def test_jwt_pack_and_unpack(): srv = JWT(keyjar, iss=issuer) _jwt = srv.pack(sub='sub') info = srv.unpack(_jwt)
def construct_app_args(args, conf, operations, func, default_profiles, inst_conf, display_order=None): """ :param args: Command arguments, argparse instance :param conf: Service configuration :param operations: Operations module :param func: Functions module :param default_profiles: The default profiles module :param inst_conf: Test instance configuration :return: Application arguments """ sys.path.insert(0, ".") # setup_logging("%s/rp_%s.log" % (SERVER_LOG_FOLDER, _port), logger) if args.flowdir: _flowdir = args.flowdir else: _flowdir = conf.FLOWDIR cls_factories = {'': operations.factory} func_factory = func.factory try: profiles = importlib.import_module(conf.PROFILES) except AttributeError: profiles = default_profiles if display_order is None: display_order = OP_ORDER flow_state = FlowState(_flowdir, profile_handler=ProfileHandler, cls_factories=cls_factories, func_factory=func_factory, display_order=display_order) # Add own keys for signing/encrypting JWTs jwks, keyjar, kidd = build_keyjar(conf.KEYS) try: if args.staticdir: _sdir = args.staticdir else: _sdir = 'jwks' except AttributeError: _sdir = 'jwks' # If this instance is behind a reverse proxy or on its own _port = args.port if conf.BASE.endswith('/'): conf.BASE = conf.BASE[:-1] if args.path2port: ppmap = read_path2port_map(args.path2port) try: _path = ppmap[str(_port)] except KeyError: print('Port not in path2port map file {}'.format(args.path2port)) sys.exit(-1) # if args.xport: # _base = '{}:{}/{}/'.format(conf.BASE, str(_port), _path) # else: _base = '{}/{}/'.format(conf.BASE, _path) else: if _port not in [443, 80]: _base = '{}:{}'.format(conf.BASE, _port) else: _base = conf.BASE _path = '' if not _base.endswith('/'): _base += '/' # -------- JWKS --------------- if args.path2port: jwks_uri = "{}{}/jwks_{}.json".format(_base, _sdir, _port) f = open('{}/jwks_{}.json'.format(_sdir, _port), "w") elif _port not in [443, 80]: jwks_uri = "{}:{}/{}/jwks_{}.json".format(conf.BASE, _port, _sdir, _port) f = open('{}/jwks_{}.json'.format(_sdir, _port), "w") else: jwks_uri = "{}/{}/jwks.json".format(conf.BASE, _sdir) f = open('{}/jwks.json'.format(_sdir), "w") f.write(json.dumps(jwks)) f.close() # -------- MAKO setup ----------- try: if args.makodir: _dir = args.makodir if not _dir.endswith("/"): _dir += "/" else: _dir = "./" except AttributeError: _dir = './' LOOKUP = TemplateLookup(directories=[_dir + 'templates', _dir + 'htdocs'], module_directory=_dir + 'modules', input_encoding='utf-8', output_encoding='utf-8') _client_info = inst_conf['client'] # Now when the basic URL for the RP is constructed update the # redirect_uris and the post_logout_redirect_uris try: ri = _client_info['registration_info'] except KeyError: pass else: ri['redirect_uris'] = [r.format(_base) for r in ri['redirect_uris']] try: ri['post_logout_redirect_uris'] = [r.format(_base) for r in ri['post_logout_redirect_uris']] except KeyError: pass _client_info.update( {"base_url": _base, "kid": kidd, "keyjar": keyjar, "jwks_uri": jwks_uri} ) # try: # _client_info['client_id'] = _client_info['registration_response'][ # 'client_id'] # except KeyError: # pass if args.insecure: _client_info['verify_ssl'] = False # Test profile either as a command line argument or if not that # from the configuration file # if args.profile: # _profile = args.profile # else: # _profile = inst_conf['tool']['profile'] # Application arguments app_args = { "flow_state": flow_state, "conf": conf, "base_url": _base, "client_info": _client_info, "profiles": profiles, "operation": operations, "cache": {}, # "profile": _profile, "lookup": LOOKUP, 'tool_conf': inst_conf['tool'], "profile_handler": ProfileHandler } return _path, app_args
client_reg = client_conf["client_registration"] client_reg["redirect_uris"] = [url.format(base=conf.BASE) for url in client_reg["redirect_uris"]] global ACR_VALUES ACR_VALUES = conf.ACR_VALUES session_opts = { 'session.type': 'memory', 'session.cookie_expires': True, 'session.auto': True, 'session.key': "{}.beaker.session.id".format( urlparse.urlparse(conf.BASE).netloc.replace(":", ".")) } jwks, keyjar, _ = build_keyjar(conf.keys) NEW_NAME = "static/jwks.json" F = open(NEW_NAME, "w") F.write(json.dumps(jwks)) F.close() sws_data = conf.ME.copy() sws_data["redirect_uri"] = conf.ME["redirect_uris"][0] sws_data["jwks_uri"] = conf.BASE + NEW_NAME software_statement = create_software_statement(sws_data) conf.CLIENTS[""]["client_info"] = {"software_statement": software_statement} CLIENTS = OIDCClients(conf, software_statement, keyjar=keyjar) SERVER_ENV.update({"template_lookup": LOOKUP, "base_url": conf.BASE})
import json from oic.utils.keyio import build_keyjar from oic.utils.keyio import dump_jwks __author__ = 'roland' key_conf = [{"type": "RSA", "use": ["enc", "sig"]}] pub_jwks, keyjar, kdd = build_keyjar(key_conf, "tre%d", None, None) dump_jwks(keyjar.issuer_keys[''], 'tre.jwks') # # To get the private keys # priv_jwks = keyjar.export_jwks(private=True) # # f = open('tre.jwks', 'w') # f.write(json.dumps(priv_jwks)) # f.close()