Skip to content

Commit 4b7df5b

Browse files
committed
More work on the federation stuff
1 parent 80d7a52 commit 4b7df5b

File tree

7 files changed

+104
-18
lines changed

7 files changed

+104
-18
lines changed

oidc_fed/fed_op/fedop.py renamed to oidc_fed/fed_op/faop.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171

7272
# OIDC Provider
7373
_op = setup.op_setup(args, config, Provider)
74+
setup.fed_setup(_op.baseurl, _op, config)
7475

7576
# WebFinger
7677
webfinger_config = {

oidc_fed/fed_op/setup.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
import json
33
import logging
44
import sys
5+
from urllib.parse import quote_plus, unquote_plus
56

67
from jwkest import as_unicode
78

9+
from oic.federation.bundle import FSJWKSBundle
10+
from oic.federation.entity import FederationEntity
11+
from oic.federation.operator import Operator
812
from oic.utils import shelve_wrapper
913
from oic.utils.authn.authn_context import AuthnBroker
1014
from oic.utils.authn.authn_context import make_auth_verify
@@ -15,7 +19,7 @@
1519
from oic.utils.authn.saml import SAMLAuthnMethod
1620
from oic.utils.authn.user import UsernamePasswordMako
1721
from oic.utils.authz import AuthzHandling
18-
from oic.utils.keyio import keyjar_init
22+
from oic.utils.keyio import keyjar_init, build_keyjar
1923
from oic.utils.sdb import SessionDB
2024
from oic.utils.userinfo import UserInfo
2125
from oic.utils.userinfo.aa_info import AaUserInfo
@@ -272,3 +276,16 @@ def op_setup(args, config, provider_cls):
272276
logger.info("OC3 server keys: %s" % b)
273277

274278
return _op
279+
280+
281+
def fed_setup(iss, provider, conf):
282+
bundle = FSJWKSBundle(iss, fdir=conf.JWKS_DIR,
283+
key_conv={'to': quote_plus, 'from': unquote_plus})
284+
285+
sig_keys = build_keyjar(conf.SIG_KEYS)[1]
286+
287+
provider.federation_entity = FederationEntity(
288+
provider, iss=iss, keyjar=sig_keys, fo_bundle=bundle,
289+
signed_metadata_statements_dir=conf.SMS_DIR)
290+
291+
provider.fo_priority = conf.FO_PRIORITY

src/oic/federation/bundle.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@
22
import json
33
import os
44

5-
import sys
6-
7-
from future.backports.urllib.parse import quote_plus, unquote_plus
8-
from jwkest import jws
9-
from jwkest.jws import NoSuitableSigningKeys
105
from oic.federation.file_system import FileSystem
116

127
from oic.utils.jwt import JWT
@@ -164,8 +159,44 @@ def get_signing_keys(eid, keydef, key_file):
164159
return kj
165160

166161

162+
def jwks_to_keyjar(jwks):
163+
"""
164+
165+
:param jwks: String representation of a JWKS
166+
:return: A KeyJar instance
167+
"""
168+
try:
169+
_jwks = json.loads(jwks)
170+
except json.JSONDecodeError:
171+
raise ValueError('No proper JWKS')
172+
kj = KeyJar()
173+
kj.import_jwks(_jwks, issuer='')
174+
return kj
175+
176+
177+
def k_to_k(keyjar, private=False):
178+
k = list(keyjar.keys())
179+
if len(k) == 1:
180+
return json.dumps(keyjar.export_jwks(issuer=k[0], private=private))
181+
elif len(k) == 2 and '' in k:
182+
k.remove('')
183+
return json.dumps(keyjar.export_jwks(issuer=k[0], private=private))
184+
else:
185+
raise ValueError('Too many issuers')
186+
187+
188+
def keyjar_to_jwks(keyjar):
189+
return k_to_k(keyjar)
190+
191+
192+
def keyjar_to_jwks_private(keyjar):
193+
return k_to_k(keyjar, private=True)
194+
195+
167196
class FSJWKSBundle(JWKSBundle):
168197
def __init__(self, iss, sign_keys=None, fdir='./', key_conv=None):
169198
JWKSBundle.__init__(self, iss, sign_keys=sign_keys)
170-
self.bundle = FileSystem(fdir, key_conv)
199+
self.bundle = FileSystem(fdir, key_conv=key_conv,
200+
value_conv={'to': keyjar_to_jwks,
201+
'from': jwks_to_keyjar})
171202

src/oic/federation/entity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def __init__(self, srv, jwks_file=None, iss='', keyjar=None,
3636
# Signed metadata statements
3737
self.signed_metadata_statements = FileSystem(
3838
signed_metadata_statements_dir,
39-
key_conv={'in': quote_plus, 'out': unquote_plus})
39+
key_conv={'to': quote_plus, 'from': unquote_plus})
4040
self.signed_metadata_statements.sync()
4141

4242
self.ms_cls = ms_cls

src/oic/federation/file_system.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66

77

88
class FileSystem(object):
9-
def __init__(self, fdir, key_conv=None):
9+
def __init__(self, fdir, key_conv=None, value_conv=None):
1010
self.fdir = fdir
1111
self.fmtime = {}
1212
self.db = {}
1313
self.key_conv = key_conv or {}
14+
self.value_conv = value_conv or {}
1415

1516
def __getitem__(self, item):
1617
try:
@@ -21,16 +22,43 @@ def __getitem__(self, item):
2122
if self.is_changed(item):
2223
logger.info("File content change in {}".format(item))
2324
fname = os.path.join(self.fdir, item)
24-
self.db[item] = self._read_info(fname)
25+
self.db[item] = self._read_info(self.value_conv['from'](fname))
2526

2627
return self.db[item]
2728

29+
def __setitem__(self, key, value):
30+
"""
31+
32+
:param key: Identifier
33+
:param value: Most be a string
34+
:return:
35+
"""
36+
37+
if not os.path.isdir(self.fdir):
38+
os.makedirs(self.fdir, exist_ok=True)
39+
40+
try:
41+
_key = self.key_conv['to'](key)
42+
except KeyError:
43+
_key = key
44+
45+
fname = os.path.join(self.fdir, _key)
46+
fp = open(fname, 'w')
47+
try:
48+
fp.write(self.value_conv['to'](value))
49+
except KeyError:
50+
fp.write(value)
51+
fp.close()
52+
53+
self.db[key] = value
54+
self.fmtime[key] = self.get_mtime(fname)
55+
2856
def keys(self):
2957
self.sync()
3058
res = []
3159
for k in self.db.keys():
3260
try:
33-
res.append(self.key_conv['out'](k))
61+
res.append(self.key_conv['from'](k))
3462
except KeyError:
3563
res.append(k)
3664
return res
@@ -67,11 +95,15 @@ def is_changed(self, item):
6795
logger.error('Could not access {}'.format(fname))
6896
raise KeyError(item)
6997

70-
@staticmethod
71-
def _read_info(fname):
98+
def _read_info(self, fname):
7299
if os.path.isfile(fname):
73100
try:
74-
return open(fname, 'r').read()
101+
info = open(fname, 'r').read()
102+
try:
103+
info = self.value_conv['from'](info)
104+
except KeyError:
105+
pass
106+
return info
75107
except Exception as err:
76108
logger.error(err)
77109
raise
@@ -97,7 +129,7 @@ def items(self):
97129
res = {}
98130
for k, v in self.db.items():
99131
try:
100-
res[(self.key_conv['out'](k))] = v
132+
res[(self.key_conv['from'](k))] = v
101133
except KeyError:
102134
res[k] = v
103135
return res

src/oic/utils/keyio.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,11 @@ def export_jwks(self, private=False, issuer=""):
715715
return {"keys": keys}
716716

717717
def import_jwks(self, jwks, issuer):
718+
"""
719+
720+
:param jwks: Dictionary representation of a JWKS
721+
:param issuer: Who 'owns' the JWKS
722+
"""
718723
try:
719724
_keys = jwks["keys"]
720725
except KeyError:

tests/test_x_fed_entity.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def test_create_entity():
200200
os.makedirs(_dir)
201201

202202
fo_bundle = FSJWKSBundle(CLIENT_ID, fdir=JWKS_DIR,
203-
key_conv={'in': quote_plus, 'out': unquote_plus})
203+
key_conv={'to': quote_plus, 'from': unquote_plus})
204204

205205
entity = FederationEntity(None, iss=CLIENT_ID, jwks_file=JWKS_FILE,
206206
signed_metadata_statements_dir=SMD_DIR,
@@ -228,7 +228,7 @@ def test_create_entity_with_fo_jwks_dir():
228228
populate_jwks_dir([FOP, FO1P])
229229

230230
fo_bundle = FSJWKSBundle(CLIENT_ID, fdir=JWKS_DIR,
231-
key_conv={'in': quote_plus, 'out': unquote_plus})
231+
key_conv={'to': quote_plus, 'from': unquote_plus})
232232

233233
entity = FederationEntity(None, iss=CLIENT_ID, jwks_file=JWKS_FILE,
234234
signed_metadata_statements_dir=SMD_DIR,
@@ -251,7 +251,7 @@ def test_create_entity_with_fo_jwks_and_sms_dirs():
251251
populate_sms_dir(SPEC)
252252

253253
fo_bundle = FSJWKSBundle(CLIENT_ID, fdir=JWKS_DIR,
254-
key_conv={'in': quote_plus, 'out': unquote_plus})
254+
key_conv={'to': quote_plus, 'from': unquote_plus})
255255

256256
entity = FederationEntity(None, iss=CLIENT_ID, jwks_file=JWKS_FILE,
257257
signed_metadata_statements_dir=SMD_DIR,

0 commit comments

Comments
 (0)