Skip to content

Commit

Permalink
More work on the federation stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
rohe committed Feb 21, 2017
1 parent 80d7a52 commit 4b7df5b
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 18 deletions.
1 change: 1 addition & 0 deletions oidc_fed/fed_op/fedop.py → oidc_fed/fed_op/faop.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@

# OIDC Provider
_op = setup.op_setup(args, config, Provider)
setup.fed_setup(_op.baseurl, _op, config)

# WebFinger
webfinger_config = {
Expand Down
19 changes: 18 additions & 1 deletion oidc_fed/fed_op/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
import json
import logging
import sys
from urllib.parse import quote_plus, unquote_plus

from jwkest import as_unicode

from oic.federation.bundle import FSJWKSBundle
from oic.federation.entity import FederationEntity
from oic.federation.operator import Operator
from oic.utils import shelve_wrapper
from oic.utils.authn.authn_context import AuthnBroker
from oic.utils.authn.authn_context import make_auth_verify
Expand All @@ -15,7 +19,7 @@
from oic.utils.authn.saml import SAMLAuthnMethod
from oic.utils.authn.user import UsernamePasswordMako
from oic.utils.authz import AuthzHandling
from oic.utils.keyio import keyjar_init
from oic.utils.keyio import keyjar_init, build_keyjar
from oic.utils.sdb import SessionDB
from oic.utils.userinfo import UserInfo
from oic.utils.userinfo.aa_info import AaUserInfo
Expand Down Expand Up @@ -272,3 +276,16 @@ def op_setup(args, config, provider_cls):
logger.info("OC3 server keys: %s" % b)

return _op


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
43 changes: 37 additions & 6 deletions src/oic/federation/bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
import json
import os

import sys

from future.backports.urllib.parse import quote_plus, unquote_plus
from jwkest import jws
from jwkest.jws import NoSuitableSigningKeys
from oic.federation.file_system import FileSystem

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


def jwks_to_keyjar(jwks):
"""
:param jwks: String representation of a JWKS
:return: A KeyJar instance
"""
try:
_jwks = json.loads(jwks)
except json.JSONDecodeError:
raise ValueError('No proper JWKS')
kj = KeyJar()
kj.import_jwks(_jwks, issuer='')
return kj


def k_to_k(keyjar, private=False):
k = list(keyjar.keys())
if len(k) == 1:
return json.dumps(keyjar.export_jwks(issuer=k[0], private=private))
elif len(k) == 2 and '' in k:
k.remove('')
return json.dumps(keyjar.export_jwks(issuer=k[0], private=private))
else:
raise ValueError('Too many issuers')


def keyjar_to_jwks(keyjar):
return k_to_k(keyjar)


def keyjar_to_jwks_private(keyjar):
return k_to_k(keyjar, private=True)


class FSJWKSBundle(JWKSBundle):
def __init__(self, iss, sign_keys=None, fdir='./', key_conv=None):
JWKSBundle.__init__(self, iss, sign_keys=sign_keys)
self.bundle = FileSystem(fdir, key_conv)
self.bundle = FileSystem(fdir, key_conv=key_conv,
value_conv={'to': keyjar_to_jwks,
'from': jwks_to_keyjar})

2 changes: 1 addition & 1 deletion src/oic/federation/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, srv, jwks_file=None, iss='', keyjar=None,
# Signed metadata statements
self.signed_metadata_statements = FileSystem(
signed_metadata_statements_dir,
key_conv={'in': quote_plus, 'out': unquote_plus})
key_conv={'to': quote_plus, 'from': unquote_plus})
self.signed_metadata_statements.sync()

self.ms_cls = ms_cls
Expand Down
46 changes: 39 additions & 7 deletions src/oic/federation/file_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@


class FileSystem(object):
def __init__(self, fdir, key_conv=None):
def __init__(self, fdir, key_conv=None, value_conv=None):
self.fdir = fdir
self.fmtime = {}
self.db = {}
self.key_conv = key_conv or {}
self.value_conv = value_conv or {}

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

return self.db[item]

def __setitem__(self, key, value):
"""
:param key: Identifier
:param value: Most be a string
:return:
"""

if not os.path.isdir(self.fdir):
os.makedirs(self.fdir, exist_ok=True)

try:
_key = self.key_conv['to'](key)
except KeyError:
_key = key

fname = os.path.join(self.fdir, _key)
fp = open(fname, 'w')
try:
fp.write(self.value_conv['to'](value))
except KeyError:
fp.write(value)
fp.close()

self.db[key] = value
self.fmtime[key] = self.get_mtime(fname)

def keys(self):
self.sync()
res = []
for k in self.db.keys():
try:
res.append(self.key_conv['out'](k))
res.append(self.key_conv['from'](k))
except KeyError:
res.append(k)
return res
Expand Down Expand Up @@ -67,11 +95,15 @@ def is_changed(self, item):
logger.error('Could not access {}'.format(fname))
raise KeyError(item)

@staticmethod
def _read_info(fname):
def _read_info(self, fname):
if os.path.isfile(fname):
try:
return open(fname, 'r').read()
info = open(fname, 'r').read()
try:
info = self.value_conv['from'](info)
except KeyError:
pass
return info
except Exception as err:
logger.error(err)
raise
Expand All @@ -97,7 +129,7 @@ def items(self):
res = {}
for k, v in self.db.items():
try:
res[(self.key_conv['out'](k))] = v
res[(self.key_conv['from'](k))] = v
except KeyError:
res[k] = v
return res
5 changes: 5 additions & 0 deletions src/oic/utils/keyio.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,11 @@ def export_jwks(self, private=False, issuer=""):
return {"keys": keys}

def import_jwks(self, jwks, issuer):
"""
:param jwks: Dictionary representation of a JWKS
:param issuer: Who 'owns' the JWKS
"""
try:
_keys = jwks["keys"]
except KeyError:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_x_fed_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def test_create_entity():
os.makedirs(_dir)

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

entity = FederationEntity(None, iss=CLIENT_ID, jwks_file=JWKS_FILE,
signed_metadata_statements_dir=SMD_DIR,
Expand Down Expand Up @@ -228,7 +228,7 @@ def test_create_entity_with_fo_jwks_dir():
populate_jwks_dir([FOP, FO1P])

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

entity = FederationEntity(None, iss=CLIENT_ID, jwks_file=JWKS_FILE,
signed_metadata_statements_dir=SMD_DIR,
Expand All @@ -251,7 +251,7 @@ def test_create_entity_with_fo_jwks_and_sms_dirs():
populate_sms_dir(SPEC)

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

entity = FederationEntity(None, iss=CLIENT_ID, jwks_file=JWKS_FILE,
signed_metadata_statements_dir=SMD_DIR,
Expand Down

0 comments on commit 4b7df5b

Please sign in to comment.