Skip to content

Commit

Permalink
Worked through the EDU example
Browse files Browse the repository at this point in the history
  • Loading branch information
rohe committed Sep 12, 2024
1 parent 1064975 commit b673ed1
Show file tree
Hide file tree
Showing 22 changed files with 364 additions and 84 deletions.
2 changes: 1 addition & 1 deletion edu_federation/trust_mark_issuer/conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
"class": "fedservice.trust_mark_entity.server.trust_mark.TrustMark",
"kwargs": {
"client_authn_method": [
"private_key_jwt"
"none"
],
"auth_signing_alg_values": [
"ES256"
Expand Down
18 changes: 18 additions & 0 deletions edu_federation/trust_mark_issuer/personalized
Original file line number Diff line number Diff line change
@@ -1 +1,19 @@
{"iat": 1725967048, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4002", "exp": 1728559048}
{"iat": 1726062435, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728654435}
{"iat": 1726062483, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728654483}
{"iat": 1726062556, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728654556}
{"iat": 1726062582, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728654582}
{"iat": 1726067529, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728659529}
{"iat": 1726067580, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728659580}
{"iat": 1726068101, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728660101}
{"iat": 1726068332, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728660332}
{"iat": 1726068434, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728660434}
{"iat": 1726068537, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728660537}
{"iat": 1726068598, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728660598}
{"iat": 1726074683, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728666683}
{"iat": 1726074734, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728666734}
{"iat": 1726075226, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728667226}
{"iat": 1726075268, "id": "https://refeds.org/category/personalized", "sub": null, "exp": 1728667268}
{"iat": 1726075871, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4002", "exp": 1728667871}
{"iat": 1726076382, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4002", "exp": 1728668382}
{"iat": 1726076473, "id": "https://refeds.org/category/personalized", "sub": "https://127.0.0.1:4002", "exp": 1728668473}
41 changes: 18 additions & 23 deletions edu_federation/trust_mark_issuer/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,23 +78,9 @@ def service_endpoint(endpoint):

if request.method == 'GET':
if request.args:
_req_args = request.args.to_dict()
req_args = request.args.to_dict()
else:
_req_args = {}
try:
req_args = endpoint.parse_request(_req_args)
except (InvalidClient, UnknownClient) as err:
_log.error(err)
return make_response(json.dumps({
'error': 'unauthorized_client',
'error_description': str(err)
}), 400)
except Exception as err:
_log.error(err)
return make_response(json.dumps({
'error': 'invalid_request',
'error_description': str(err)
}), 400)
req_args = {}
else:
if request.data:
if isinstance(request.data, str):
Expand All @@ -103,12 +89,19 @@ def service_endpoint(endpoint):
req_args = request.data.decode()
else:
req_args = dict([(k, v) for k, v in request.form.items()])
try:
req_args = endpoint.parse_request(req_args)
except Exception as err:
_log.error(err)
err_msg = ResponseMessage(error='invalid_request', error_description=str(err))
return make_response(err_msg.to_json(), 400)

try:
req_args = endpoint.parse_request(req_args)
except (InvalidClient, UnknownClient) as err:
_log.error(err)
return make_response(json.dumps({
'error': 'unauthorized_client',
'error_description': str(err)
}), 400)
except Exception as err:
_log.error(err)
err_msg = ResponseMessage(error='invalid_request', error_description=str(err))
return make_response(err_msg.to_json(), 400)

_log.info('request: {}'.format(req_args))
if isinstance(req_args, ResponseMessage) and 'error' in req_args:
Expand All @@ -127,7 +120,9 @@ def service_endpoint(endpoint):
if 'redirect_location' in args:
return redirect(args['redirect_location'])
if 'http_response' in args:
return make_response(args['http_response'], 200)
resp = make_response(args['http_response'], 200)
resp.headers['Content-Type'] = endpoint.response_content_type
return resp

response = do_response(endpoint, req_args, **args)
return response
Expand Down
23 changes: 23 additions & 0 deletions script/checks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Trust Anchor: https://127.0.0.1:7003
# OpenID Provider: https://127.0.0.1:4004
# OpenID Relying Party: https://127.0.0.1:4002
# Trust Mark Issuer: https://127.0.0.1:6000

# Get the entity configuration
./get_entity_configuration.py -k -t trust_anchor_local.json -c https://127.0.0.1:4002

# Get subordinate statement from superior
./get_subordinate_statement.py -k -t trust_anchor_local.json -s https://127.0.0.1:7003 https://127.0.0.1:4002

# Get Trust Chain
./get_trust_chains.py -k -t trust_anchor_local.json https://127.0.0.1:4002
./get_trust_chains.py -k -t trust_anchor_local.json https://127.0.0.1:4004

# Get new trust mark
./get_trust_mark.py -k -t trust_anchor_local.json -i https://refeds.org/category/personalized -s https://127.0.0.1:4002 https://127.0.0.1:6000

# Check Trust Mark status
./get_trust_mark_status.py -k -t trust_anchor_local.json -i https://refeds.org/category/personalized
-s https://127.0.0.1:4002 https://127.0.0.1:6000

# List subordinates
43 changes: 43 additions & 0 deletions script/get_entity_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python3
import json

from pygments import highlight
from pygments.formatters.terminal import TerminalFormatter
from pygments.lexers.data import JsonLexer

from fedservice.entity.function.trust_chain_collector import unverified_entity_statement
from fedservice.entity.function.trust_chain_collector import verify_self_signed_signature
from fedservice.utils import make_federation_entity

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-k', "--insecure", action='store_true')
parser.add_argument('-t', "--trust_anchors_file")
parser.add_argument(dest="entity_id")
args = parser.parse_args()

if not args.entity_id:
print("Need an entity_id to work with")

if args.trust_anchors_file:
trust_anchors = json.loads(open(args.trust_anchors_file).read())
else:
trust_anchors = {}

federation_entity = make_federation_entity(entity_id="https://localhost",
trust_anchors=trust_anchors)
if args.insecure:
federation_entity.keyjar.httpc_params = {"verify": False}

_collector = federation_entity.get_function("trust_chain_collector")

# Read the entity configuration
_jws = _collector.get_entity_configuration(args.entity_id)
# Verify the self signed signature
entity_configuration = verify_self_signed_signature(_jws)
# Print
json_str = json.dumps(entity_configuration, indent=2)
print(20 * "=" + " Entity Configuration " + 20 * "=")
print(highlight(json_str, JsonLexer(), TerminalFormatter()))
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
parser = argparse.ArgumentParser()
parser.add_argument('-k', "--insecure", action='store_true')
parser.add_argument('-t', "--trust_anchors_file")
parser.add_argument('-c', dest='config', action='store_true')
parser.add_argument('-s', "--superior")
parser.add_argument(dest="entity_id")
args = parser.parse_args()
Expand All @@ -36,23 +35,20 @@
_collector = federation_entity.get_function("trust_chain_collector")

_info = None
if args.config:
_jws = _collector.get_entity_configuration(args.entity_id)
entity_configuration = verify_self_signed_signature(_jws)
json_str = json.dumps(entity_configuration, indent=2)
print(20 * "=" + " Entity Configuration " + 20 * "=")
print(highlight(json_str, JsonLexer(), TerminalFormatter()))

if args.superior:
_jws = _collector.get_entity_configuration(args.superior)
superior_entity_configuration = verify_self_signed_signature(_jws)
_fetch_endpoint = superior_entity_configuration["metadata"]["federation_entity"][
"federation_fetch_endpoint"]
# The entity with the entity_id is the one issuing an entity statement
_jws = _collector.get_entity_statement(fetch_endpoint=_fetch_endpoint,
issuer=args.superior,
subject=args.entity_id)
entity_statement = unverified_entity_statement(_jws)
json_str = json.dumps(entity_statement, indent=2)
print(20 * "=" + " Entity Statement " + 20 * "=")
print(highlight(json_str, JsonLexer(), TerminalFormatter()))

# Get the entity configuration for the superior
_jws = _collector.get_entity_configuration(args.superior)
superior_entity_configuration = verify_self_signed_signature(_jws)

# Pick out the fetch endpoint
_fetch_endpoint = superior_entity_configuration["metadata"]["federation_entity"]["federation_fetch_endpoint"]

# Ask the superior for the subordinate statement
_jws = _collector.get_entity_statement(fetch_endpoint=_fetch_endpoint,
issuer=args.superior,
subject=args.entity_id)
# Don't try to verify the signatures
entity_statement = unverified_entity_statement(_jws)
json_str = json.dumps(entity_statement, indent=2)
print(20 * "=" + f" Subordinate Statement about {args.entity_id} from {args.superior} " + 20 * "=")
print(highlight(json_str, JsonLexer(), TerminalFormatter()))
6 changes: 5 additions & 1 deletion script/get_trust_chains.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@
trust_chains = apply_policies(federation_entity, trust_chains)

for trust_chain in trust_chains:
print(20 * "=", trust_chain.anchor, 20 * "=")
print(20 * "=", f"Trust Chain Anchor: {trust_chain.anchor}", 20 * "=")
for node in trust_chain.verified_chain:
if node["iss"] == node["sub"]:
print(20 * "-", f"Entity Configuration for: {node['iss']}", 20 * "-")
else:
print(20 * "-", f"Subordinate statement about: {node['sub']} from {node['iss']}", 20 * "-")
# pretty print JSON
print(json.dumps(node, sort_keys=True, indent=4))
53 changes: 53 additions & 0 deletions script/get_trust_mark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import json

import requests

from fedservice.defaults import federation_services
from fedservice.entity.function import get_entity_endpoint
from fedservice.utils import make_federation_entity

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-k', "--insecure", action='store_true')
parser.add_argument('-t', "--trust_anchors")
parser.add_argument('-i', "--trust_mark_id")
parser.add_argument('-s', "--subject")
parser.add_argument(dest="entity_id")
args = parser.parse_args()

if not args.entity_id:
print("Need an entity_id to work with")

trust_anchors = json.loads(open(args.trust_anchors).read())

federation_entity = make_federation_entity(entity_id="https://localhost",
services=federation_services("entity_configuration", "trust_mark",
"entity_statement"),
trust_anchors=trust_anchors)

if args.insecure:
_param = {"verify": False}
federation_entity.keyjar.httpc_params = _param
federation_entity.httpc_params = _param
federation_entity.client.httpc_params = _param

httpc = getattr(federation_entity, "httpc", None)
if not httpc:
httpc = requests

# Need to find the trust mark issuer Trust Mark Endpoint
endpoint = get_entity_endpoint(federation_entity, args.entity_id, "federation_entity",
"federation_trust_mark_endpoint")

# federation_entity.client.context.issuer = args.entity_id
_response = federation_entity.client.do_request("trust_mark",
request_args={
"trust_mark_id": args.trust_mark_id,
"sub": args.subject
},
endpoint=endpoint)
#result = _service.parse_response(response)
print(f"Trust mark claims: {_response}")
53 changes: 53 additions & 0 deletions script/get_trust_mark_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env python3
import json

import requests

from fedservice.defaults import federation_services
from fedservice.entity.function import get_entity_endpoint
from fedservice.utils import make_federation_entity

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-k', "--insecure", action='store_true')
parser.add_argument('-i', "--trust_mark_id")
parser.add_argument('-s', "--subject")
parser.add_argument('-t', "--trust_anchors")
parser.add_argument(dest="entity_id")
args = parser.parse_args()

if not args.entity_id:
print("Need an entity_id to work with")

trust_anchors = json.loads(open(args.trust_anchors).read())

federation_entity = make_federation_entity(entity_id="https://localhost",
services=federation_services("entity_configuration", "trust_mark",
"entity_statement", "trust_mark_status"),
trust_anchors=trust_anchors)

if args.insecure:
_param = {"verify": False}
federation_entity.keyjar.httpc_params = _param
federation_entity.httpc_params = _param
federation_entity.client.httpc_params = _param

httpc = getattr(federation_entity, "httpc", None)
if not httpc:
httpc = requests

# Need to find the trust mark issuer Trust Mark Endpoint
endpoint = get_entity_endpoint(federation_entity, args.entity_id, "federation_entity",
"federation_trust_mark_status_endpoint")

# federation_entity.client.context.issuer = args.entity_id
_response = federation_entity.client.do_request("trust_mark_status",
request_args={
"trust_mark_id": args.trust_mark_id,
"sub": args.subject
},
endpoint=endpoint)
#result = _service.parse_response(response)
print(f"Trust mark status: {_response}")
42 changes: 42 additions & 0 deletions script/list_subordinates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python3
import json

from fedservice.defaults import federation_services
from fedservice.entity.function import get_entity_endpoint
from fedservice.utils import make_federation_entity

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-k', "--insecure", action='store_true')
parser.add_argument('-t', "--trust_anchors_file")
parser.add_argument('-s', "--superior")
parser.add_argument(dest="entity_id")
args = parser.parse_args()

if not args.entity_id:
print("Need an entity_id to work with")

if args.trust_anchors_file:
trust_anchors = json.loads(open(args.trust_anchors_file).read())
else:
trust_anchors = {}

federation_entity = make_federation_entity(entity_id="https://localhost",
services=federation_services("entity_configuration", "list",
"entity_statement"),
trust_anchors=trust_anchors)
if args.insecure:
federation_entity.keyjar.httpc_params = {"verify": False}
federation_entity.client.httpc_params = {"verify": False}

# Need to find the listing endpoint
endpoint = get_entity_endpoint(federation_entity, args.entity_id, "federation_entity",
"federation_list_endpoint")

# Ask the superior for the subordinates statement
_response = federation_entity.client.do_request('list', endpoint=endpoint)

# Don't try to verify the signatures
print(20 * "=" + f" Subordinates: {_response} " + 20 * "=")
21 changes: 21 additions & 0 deletions script/trust_anchor_local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"https://127.0.0.1:7003": {
"keys": [
{
"kty": "RSA",
"use": "sig",
"kid": "ZXFYbDlqWkNzaWd1eDNseTVfWFBNUWRFX3lrQ2Y3b2owaWVMTjNhcnpBMA",
"e": "AQAB",
"n": "qHE53SwNAYWZfLQufshE5vhJDBzAEgdO762SkGcV59GDx2VZIyoSek3Y8X8_Z6pVGeDovBQCBstwD7X4ZL4ynMsGb_Szphx2dlcvYPHfY4BFJWGoROPzo8VJ-z5CLseHKg_LXL-PxTHziZFBawMJn5vTodRQVJIU_WA5K408WuNgBh_IhkTj37L-fajwExYoPMWu-YMNlUWD8ta_hnHxLE43QZW5shq09LcTj9VcJdWey1i4q_ftHoZsFngML-kA8KBImeiirtCHs6V1eA3LxJ5a_KojK7aPcA9VgvPH1987I4gqHFedtLZkV5dewYt4HGQ4O3YQ8IsX1Nse0ib2Sw"
},
{
"kty": "EC",
"use": "sig",
"kid": "Nng1Yy1SMmFoRC1VQ2g4NllXSEU1dEtkY0VkX3pweG5RXzdLMjY1WkJNMA",
"crv": "P-256",
"x": "yLcidWumqjOPjJI1OcSjgTtqmOfNzC0APWKdRIFik3Y",
"y": "8IkDqyQyLHB10Klvz7vJIb6jrlJ_-HDgMGusR_JzckE"
}
]
}
}
Loading

0 comments on commit b673ed1

Please sign in to comment.