def make_ms(desc, leaf, operator, sup=None): """ Construct a signed metadata statement :param desc: A description of who wants who to signed what. represented as a dictionary containing: 'request', 'requester', 'signer' and 'signer_add'. :param leaf: if the requester is the entity operator/agent :param operator: A dictionary containing Operator instance as values. :param ms: Metadata statements to be added, dict. The values are signed MetadataStatements. :param ms_uris: Metadata Statement URIs to be added. Note that ms and ms_uris can not be present at the same time. It can be one of them or none. :return: A dictionary with the FO ID as key and the signed metadata statement as value. """ req = MetadataStatement(**desc['request']) _requester = operator[desc['requester']] req['signing_keys'] = _requester.signing_keys_as_jwks_json() _signer = operator[desc['signer']] if sup is None: sup = {} _fo = _signer.iss try: _ms = sup['ms'] except KeyError: pass else: req['metadata_statements'] = dict(_ms.items()) if len(_ms): _fo = list(_ms.keys())[0] else: _fo = '' try: _ms_uri = sup['ms_uri'] except KeyError: pass else: req['metadata_statement_uris'] = dict(_ms_uri.items()) if len(_ms_uri): _fo = list(_ms_uri.keys())[0] else: _fo = '' req.update(desc['signer_add']) if leaf: jwt_args = {'recv': _requester.iss} else: jwt_args = {} ms = _signer.pack_metadata_statement(req, jwt_args=jwt_args) return {_fo: ms}
def test_create_client_metadata_statement(): ms = MetadataStatement(signing_keys=KEYS['org']['jwks']) ms_jwt = ms.to_jwt(KEYS['fo']['keyjar'].get_signing_key('rsa')) cms = ClientMetadataStatement( metadata_statements=Message(**{ISSUER['org']: ms_jwt}), contacts=['*****@*****.**']) assert cms
def ace(self, req, fos, context): """ Add signing keys, create metadata statement and extend request. :param req: Request :param fos: List of Federation Operator IDs :param context: One of :py:data:`fedoidc.CONTEXTS` """ _cms = MetadataStatement() _cms.update(req) _cms = self.add_signing_keys(_cms) sms = self.signer.create_signed_metadata_statement(_cms, context, fos=fos) return self.extend_with_ms(req, sms)
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=public_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_request_signed_by_signing_keys(): kj = KeyJar() kj.issuer_keys['abc'] = KEYJAR.issuer_keys[''] msreq = MetadataStatement(signing_keys=json.dumps(JWKS)) smsreq = request_signed_by_signing_keys(kj, msreq, 'abc', 3600) assert smsreq res = verify_request_signed_by_signing_keys(smsreq) assert set(res.keys()) == {'ms', 'iss'} assert res['iss'] == 'abc'
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 _kj = public_keys_keyjar(_keyjar, '', None, op.iss) r = _jwt.verify_compact(sms, _kj.get_signing_key(owner=op.iss)) assert r
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=public_jwks_bundle(jb)) loe = ent.get_metadata_statement(req) assert loe
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=public_jwks_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 verify_request_signed_by_signing_keys(smsreq): """ Verify that a JWT is signed with a key that is inside the JWT. :param smsreq: Signed Metadata Statement signing request :return: Dictionary containing 'ms' (the signed request) and 'iss' (the issuer of the JWT). """ _jws = factory(smsreq) _json = _jws.jwt.part[1] _body = json.loads(as_unicode(_json)) iss = _body['iss'] _jwks = _body['signing_keys'] _kj = jwks_to_keyjar(_jwks, iss) try: _kid = _jws.jwt.headers['kid'] except KeyError: _keys = _kj.get_signing_key(owner=iss) else: _keys = _kj.get_signing_key(owner=iss, kid=_kid) _ver = _jws.verify_compact(smsreq, _keys) # remove the JWT specific claims for k in JsonWebToken.c_param.keys(): try: del _ver[k] except KeyError: pass try: del _ver['kid'] except KeyError: pass return {'ms': MetadataStatement(**_ver), 'iss': iss}
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 _kj = public_keys_keyjar(_keyjar, '', None, op.iss) r = _jwt.verify_compact(sms, _kj.get_signing_key(owner=op.iss)) assert r
def test_create_metadata_statement_simple(): ms = MetadataStatement(signing_keys=KEYS['org']['jwks']) assert ms sig_keys = ms['signing_keys'] assert len(sig_keys['keys']) == 2
def test_create_sms(): s = signer[OA['sunet']] req = MetadataStatement(issuer='https://example.org/op') r = s.create_signed_metadata_statement(req, 'discovery') assert r