annotate get_agent.py @ 13:3014db0a5500 default tip

mv board to proj/micro, rename this repo with dashes
author drewp@bigasterisk.com
date Fri, 28 Jun 2024 17:08:09 -0700
parents 6e0d47f9e56d
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
drewp@bigasterisk.com
parents:
diff changeset
1 import datetime
drewp@bigasterisk.com
parents:
diff changeset
2 import json
drewp@bigasterisk.com
parents:
diff changeset
3 import logging
drewp@bigasterisk.com
parents:
diff changeset
4 from typing import Any, Dict
drewp@bigasterisk.com
parents:
diff changeset
5
drewp@bigasterisk.com
parents:
diff changeset
6 import aiohttp
drewp@bigasterisk.com
parents:
diff changeset
7 from attr import dataclass
drewp@bigasterisk.com
parents:
diff changeset
8 from jwskate import JwkSet, Jwt
drewp@bigasterisk.com
parents:
diff changeset
9 from rdflib import URIRef
drewp@bigasterisk.com
parents:
diff changeset
10 from starlette.requests import Request
drewp@bigasterisk.com
parents:
diff changeset
11
drewp@bigasterisk.com
parents:
diff changeset
12 log = logging.getLogger(__name__)
drewp@bigasterisk.com
parents:
diff changeset
13 tzlocal = datetime.datetime.now().astimezone().tzinfo
drewp@bigasterisk.com
parents:
diff changeset
14
2
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
15
0
drewp@bigasterisk.com
parents:
diff changeset
16 @dataclass
drewp@bigasterisk.com
parents:
diff changeset
17 class Agent:
drewp@bigasterisk.com
parents:
diff changeset
18 email: str
drewp@bigasterisk.com
parents:
diff changeset
19 agent: URIRef
drewp@bigasterisk.com
parents:
diff changeset
20 name: str
drewp@bigasterisk.com
parents:
diff changeset
21 issuedAt: datetime.datetime
drewp@bigasterisk.com
parents:
diff changeset
22 expiration: datetime.datetime
drewp@bigasterisk.com
parents:
diff changeset
23
drewp@bigasterisk.com
parents:
diff changeset
24 def asDict(self):
drewp@bigasterisk.com
parents:
diff changeset
25 now = datetime.datetime.now(tzlocal)
drewp@bigasterisk.com
parents:
diff changeset
26 return {
drewp@bigasterisk.com
parents:
diff changeset
27 'email': self.email,
drewp@bigasterisk.com
parents:
diff changeset
28 'agent': str(self.agent),
drewp@bigasterisk.com
parents:
diff changeset
29 'name': self.name,
drewp@bigasterisk.com
parents:
diff changeset
30 'issuedAt': {
drewp@bigasterisk.com
parents:
diff changeset
31 't': self.issuedAt.isoformat(),
drewp@bigasterisk.com
parents:
diff changeset
32 'secAgo': (now - self.issuedAt).total_seconds(),
drewp@bigasterisk.com
parents:
diff changeset
33 },
drewp@bigasterisk.com
parents:
diff changeset
34 'expiration': {
drewp@bigasterisk.com
parents:
diff changeset
35 't': self.expiration.isoformat(),
drewp@bigasterisk.com
parents:
diff changeset
36 'inSec': (self.expiration - now).total_seconds(),
drewp@bigasterisk.com
parents:
diff changeset
37 },
drewp@bigasterisk.com
parents:
diff changeset
38 'now': now.isoformat(),
drewp@bigasterisk.com
parents:
diff changeset
39 }
drewp@bigasterisk.com
parents:
diff changeset
40
drewp@bigasterisk.com
parents:
diff changeset
41
drewp@bigasterisk.com
parents:
diff changeset
42 def foafAgentFromAuthEmail(email: str) -> URIRef:
drewp@bigasterisk.com
parents:
diff changeset
43 return URIRef({
drewp@bigasterisk.com
parents:
diff changeset
44 'drewpca@gmail.com': 'http://bigasterisk.com/foaf.rdf#drewp',
drewp@bigasterisk.com
parents:
diff changeset
45 'kelsimp@gmail.com': 'http://bigasterisk.com/kelsi/foaf.rdf#kelsi',
drewp@bigasterisk.com
parents:
diff changeset
46 }[email])
drewp@bigasterisk.com
parents:
diff changeset
47
drewp@bigasterisk.com
parents:
diff changeset
48
drewp@bigasterisk.com
parents:
diff changeset
49 _jwkset: JwkSet | None = None
drewp@bigasterisk.com
parents:
diff changeset
50
drewp@bigasterisk.com
parents:
diff changeset
51
drewp@bigasterisk.com
parents:
diff changeset
52 async def loadJwkset() -> JwkSet:
drewp@bigasterisk.com
parents:
diff changeset
53 global _jwkset
drewp@bigasterisk.com
parents:
diff changeset
54 if _jwkset is None:
drewp@bigasterisk.com
parents:
diff changeset
55 log.info("loading jwks.json")
drewp@bigasterisk.com
parents:
diff changeset
56 async with aiohttp.ClientSession() as session:
drewp@bigasterisk.com
parents:
diff changeset
57 async with session.get('https://authenticate2.bigasterisk.com/.well-known/pomerium/jwks.json') as response:
drewp@bigasterisk.com
parents:
diff changeset
58 if response.status != 200:
drewp@bigasterisk.com
parents:
diff changeset
59 raise ValueError(f'{response.status=}')
drewp@bigasterisk.com
parents:
diff changeset
60
drewp@bigasterisk.com
parents:
diff changeset
61 ct = json.loads(await response.text())
drewp@bigasterisk.com
parents:
diff changeset
62 _jwkset = JwkSet(ct)
drewp@bigasterisk.com
parents:
diff changeset
63 return _jwkset
drewp@bigasterisk.com
parents:
diff changeset
64
drewp@bigasterisk.com
parents:
diff changeset
65
drewp@bigasterisk.com
parents:
diff changeset
66 async def getAgent(req: Request) -> Agent | None:
drewp@bigasterisk.com
parents:
diff changeset
67 jwkset = await loadJwkset()
drewp@bigasterisk.com
parents:
diff changeset
68 pomAssertion = req.headers.get('X-Pomerium-Jwt-Assertion', None)
drewp@bigasterisk.com
parents:
diff changeset
69 if pomAssertion is None:
drewp@bigasterisk.com
parents:
diff changeset
70 raise ValueError("missing X-Pomerium-Jwt-Assertion")
drewp@bigasterisk.com
parents:
diff changeset
71 jwt = Jwt(pomAssertion)
drewp@bigasterisk.com
parents:
diff changeset
72 jwt.validate(
drewp@bigasterisk.com
parents:
diff changeset
73 jwkset['keys'][0], #??
drewp@bigasterisk.com
parents:
diff changeset
74 algs=['ES256'],
9
6e0d47f9e56d pom issuer change
drewp@bigasterisk.com
parents: 2
diff changeset
75 issuer='bigasterisk.com',
0
drewp@bigasterisk.com
parents:
diff changeset
76 audience='bigasterisk.com')
drewp@bigasterisk.com
parents:
diff changeset
77 claims: Dict[str, Any] = jwt.claims
drewp@bigasterisk.com
parents:
diff changeset
78 log.debug('claims=%r', claims)
drewp@bigasterisk.com
parents:
diff changeset
79 if not claims['email']:
drewp@bigasterisk.com
parents:
diff changeset
80 return None
drewp@bigasterisk.com
parents:
diff changeset
81
drewp@bigasterisk.com
parents:
diff changeset
82 return Agent(
drewp@bigasterisk.com
parents:
diff changeset
83 email=claims['email'],
drewp@bigasterisk.com
parents:
diff changeset
84 agent=foafAgentFromAuthEmail(claims['email']),
drewp@bigasterisk.com
parents:
diff changeset
85 expiration=datetime.datetime.fromtimestamp(claims['exp']).astimezone(tzlocal),
drewp@bigasterisk.com
parents:
diff changeset
86 issuedAt=datetime.datetime.fromtimestamp(claims['iat']).astimezone(tzlocal),
drewp@bigasterisk.com
parents:
diff changeset
87 name=claims['name'],
drewp@bigasterisk.com
parents:
diff changeset
88 )
2
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
89
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
90
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
91 async def getFoafAgent(req) -> URIRef | None:
9
6e0d47f9e56d pom issuer change
drewp@bigasterisk.com
parents: 2
diff changeset
92 """this is special because fingerprint needs to be able to send
2
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
93 x-foaf-agent AND we need to get agents the normal way from pomerium"""
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
94
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
95 if 'X-Pomerium-Jwt-Assertion' in req.headers:
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
96 agent = await getAgent(req)
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
97 if agent:
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
98 return agent.agent
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
99 else:
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
100 if 'x-foaf-agent' in req.headers:
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
101 # we can trust fingerprint-unlocker to give us a x-foaf-agent derived from the fingerprint
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
102 return URIRef(req.headers['x-foaf-agent'])
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
103
76cec592435c special getFoafAgent version
drewp@bigasterisk.com
parents: 0
diff changeset
104 return None