From 8714a9925e8929eeda611f64bb558236b3e2f64c Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 09:03:39 +0100 Subject: [PATCH 01/12] Added an argument to the dump method. Useful when dumping part of tree of objects. --- src/cryptojwt/key_bundle.py | 44 +++++++++++++------- src/cryptojwt/key_issuer.py | 7 +++- src/cryptojwt/key_jar.py | 81 +++++++++++++++++++------------------ 3 files changed, 77 insertions(+), 55 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index c01211c9..cb389aa5 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -6,6 +6,7 @@ import time from datetime import datetime from functools import cmp_to_key +from typing import Optional import requests @@ -24,7 +25,6 @@ from .jwk.jwk import dump_jwk from .jwk.jwk import import_jwk from .jwk.rsa import RSAKey -from .jwk.rsa import import_private_rsa_key_from_file from .jwk.rsa import new_rsa_key from .utils import as_unicode @@ -153,18 +153,18 @@ class KeyBundle: """The Key Bundle""" def __init__( - self, - keys=None, - source="", - cache_time=300, - ignore_errors_period=0, - fileformat="jwks", - keytype="RSA", - keyusage=None, - kid="", - ignore_invalid_keys=True, - httpc=None, - httpc_params=None, + self, + keys=None, + source="", + cache_time=300, + ignore_errors_period=0, + fileformat="jwks", + keytype="RSA", + keyusage=None, + kid="", + ignore_invalid_keys=True, + httpc=None, + httpc_params=None, ): """ Contains a set of keys that have a common origin. @@ -751,7 +751,7 @@ def difference(self, bundle): return [k for k in self._keys if k not in bundle] - def dump(self): + def dump(self, cutoff: Optional[list] = None): _keys = [] for _k in self._keys: _ser = _k.to_dict() @@ -1246,3 +1246,19 @@ def init_key(filename, type, kid="", **kwargs): _new_key = key_gen(type, kid=kid, **kwargs) dump_jwk(filename, _new_key) return _new_key + + +def key_by_alg(alg: str): + if alg.startswith("RS"): + return key_gen("RSA", alg="RS256") + elif alg.startswith("ES"): + if alg == "ES256": + return key_gen("EC", crv="P-256") + elif alg == "ES384": + return key_gen("EC", crv="P-384") + elif alg == "ES512": + return key_gen("EC", crv="P-521") + elif alg.startswith("HS"): + return key_gen("sym") + + raise ValueError("Don't know who to create a key to use with '{}'".format(alg)) diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 0e02e1ac..e2f89900 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -1,6 +1,7 @@ import json import logging import os +from typing import Optional from requests import request @@ -350,16 +351,18 @@ def __len__(self): nr += len(kb) return nr - def dump(self, exclude=None): + def dump(self, exclude=None, cutoff: Optional[list]=None) -> dict: """ Returns the content as a dictionary. + :param exclude: Issuer that should not be include in the dump + :param cutoff: List of attribute name for objects that should be ignored. :return: A dictionary """ _bundles = [] for kb in self._bundles: - _bundles.append(kb.dump()) + _bundles.append(kb.dump(cutoff=cutoff)) info = { "name": self.name, diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 4b58bfe7..00a00844 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -25,14 +25,13 @@ class KeyJar(object): """ A keyjar contains a number of KeyBundles sorted by owner/issuer """ def __init__( - self, - ca_certs=None, - verify_ssl=True, - keybundle_cls=KeyBundle, - remove_after=3600, - httpc=None, - httpc_params=None, - storage=None, + self, + ca_certs=None, + verify_ssl=True, + keybundle_cls=KeyBundle, + remove_after=3600, + httpc=None, + httpc_params=None, ): """ KeyJar init function @@ -43,15 +42,9 @@ def __init__( :param remove_after: How long keys marked as inactive will remain in the key Jar. :param httpc: A HTTP client to use. Default is Requests request. :param httpc_params: HTTP request parameters - :param storage: An instance that can store information. It basically look like dictionary. :return: Keyjar instance """ - - if storage is None: - self._issuers = {} - else: - self._issuers = storage - + self._issuers = {} self.spec2key = {} self.ca_certs = ca_certs self.keybundle_cls = keybundle_cls @@ -386,7 +379,7 @@ def export_jwks(self, private=False, issuer_id="", usage=None): k.serialize(private) for k in kb.keys() if k.inactive_since == 0 - and (usage is None or (hasattr(k, "use") and k.use == usage)) + and (usage is None or (hasattr(k, "use") and k.use == usage)) ] ) return {"keys": keys} @@ -472,14 +465,14 @@ def remove_outdated(self, when=0): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def _add_key( - self, - keys, - issuer_id, - use, - key_type="", - kid="", - no_kid_issuer=None, - allow_missing_kid=False, + self, + keys, + issuer_id, + use, + key_type="", + kid="", + no_kid_issuer=None, + allow_missing_kid=False, ): _issuer = self._get_issuer(issuer_id) @@ -617,8 +610,6 @@ def copy(self): """ Make deep copy of the content of this key jar. - Note that if this key jar uses an external storage module the copy will not. - :return: A :py:class:`oidcmsg.key_jar.KeyJar` instance """ @@ -635,10 +626,12 @@ def copy(self): def __len__(self): return len(self._issuers) - def dump(self, exclude=None): + def dump(self, exclude: Optional[bool] = None, cutoff: Optional[list] = None) -> dict: """ Returns the key jar content as dictionary + :param cutoff: list of attribute names that should be ignored when dumping. + :type cutoff: list :return: A dictionary """ @@ -654,11 +647,21 @@ def dump(self, exclude=None): for _id, _issuer in self._issuers.items(): if exclude and _issuer.name in exclude: continue - _issuers[_id] = _issuer.dump() + _issuers[_id] = _issuer.dump(cutoff=cutoff) info["issuers"] = _issuers return info + def dumps(self, exclude=None): + """ + Returns a JSON representation of the key jar + + :param exclude: Exclude these issuers + :return: A string + """ + _dict = self.dump(exclude=exclude) + return json.dumps(_dict) + def load(self, info): """ @@ -675,6 +678,9 @@ def load(self, info): self._issuers[_issuer_id] = KeyIssuer().load(_issuer_desc) return self + def loads(self, string): + return self.load(json.loads(string)) + @deprecated_alias(issuer="issuer_id", owner="issuer_id") def key_summary(self, issuer_id): _issuer = self._get_issuer(issuer_id) @@ -705,7 +711,7 @@ def rotate_keys(self, key_conf, kid_template="", issuer_id=""): # ============================================================================= -def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id="", storage=None): +def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id=""): """ Builds a :py:class:`oidcmsg.key_jar.KeyJar` instance or adds keys to an existing KeyJar based on a key specification. @@ -744,7 +750,6 @@ def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id="", storage=N kid_template is given then the built-in function add_kid() will be used. :param keyjar: If an KeyJar instance the new keys are added to this key jar. :param issuer_id: The default owner of the keys in the key jar. - :param storage: A Storage instance. :return: A KeyJar instance """ @@ -753,7 +758,7 @@ def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id="", storage=N return None if keyjar is None: - keyjar = KeyJar(storage=storage) + keyjar = KeyJar() keyjar[issuer_id] = _issuer @@ -762,12 +767,11 @@ def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id="", storage=N @deprecated_alias(issuer="issuer_id", owner="issuer_id") def init_key_jar( - public_path="", - private_path="", - key_defs="", - issuer_id="", - read_only=True, - storage=None, + public_path="", + private_path="", + key_defs="", + issuer_id="", + read_only=True, ): """ A number of cases here: @@ -805,7 +809,6 @@ def init_key_jar( :param key_defs: A definition of what keys should be created if they are not already available :param issuer_id: The owner of the keys :param read_only: This function should not attempt to write anything to a file system. - :param storage: A Storage instance. :return: An instantiated :py:class;`oidcmsg.key_jar.KeyJar` instance """ @@ -819,7 +822,7 @@ def init_key_jar( if _issuer is None: raise ValueError("Could not find any keys") - keyjar = KeyJar(storage=storage) + keyjar = KeyJar() keyjar[issuer_id] = _issuer return keyjar From bdf512db0498bd9100833a40096571f8f481dd6e Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 09:05:04 +0100 Subject: [PATCH 02/12] Bumped version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4527577c..69fd4e45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ exclude_lines = [ [tool.poetry] name = "cryptojwt" -version = "1.4.1" +version = "1.4.2" description = "Python implementation of JWT, JWE, JWS and JWK" authors = ["Roland Hedberg "] license = "Apache-2.0" From f518bcb4aced39a72a4e9ecde0e9a49a0cb90fcd Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 09:14:29 +0100 Subject: [PATCH 03/12] Ran isort and black --- src/cryptojwt/key_bundle.py | 24 ++++++++++----------- src/cryptojwt/key_issuer.py | 2 +- src/cryptojwt/key_jar.py | 42 ++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index cb389aa5..44d4631d 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -153,18 +153,18 @@ class KeyBundle: """The Key Bundle""" def __init__( - self, - keys=None, - source="", - cache_time=300, - ignore_errors_period=0, - fileformat="jwks", - keytype="RSA", - keyusage=None, - kid="", - ignore_invalid_keys=True, - httpc=None, - httpc_params=None, + self, + keys=None, + source="", + cache_time=300, + ignore_errors_period=0, + fileformat="jwks", + keytype="RSA", + keyusage=None, + kid="", + ignore_invalid_keys=True, + httpc=None, + httpc_params=None, ): """ Contains a set of keys that have a common origin. diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index e2f89900..34ede7df 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -351,7 +351,7 @@ def __len__(self): nr += len(kb) return nr - def dump(self, exclude=None, cutoff: Optional[list]=None) -> dict: + def dump(self, exclude=None, cutoff: Optional[list] = None) -> dict: """ Returns the content as a dictionary. diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 00a00844..cf5c20e1 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -25,13 +25,13 @@ class KeyJar(object): """ A keyjar contains a number of KeyBundles sorted by owner/issuer """ def __init__( - self, - ca_certs=None, - verify_ssl=True, - keybundle_cls=KeyBundle, - remove_after=3600, - httpc=None, - httpc_params=None, + self, + ca_certs=None, + verify_ssl=True, + keybundle_cls=KeyBundle, + remove_after=3600, + httpc=None, + httpc_params=None, ): """ KeyJar init function @@ -379,7 +379,7 @@ def export_jwks(self, private=False, issuer_id="", usage=None): k.serialize(private) for k in kb.keys() if k.inactive_since == 0 - and (usage is None or (hasattr(k, "use") and k.use == usage)) + and (usage is None or (hasattr(k, "use") and k.use == usage)) ] ) return {"keys": keys} @@ -465,14 +465,14 @@ def remove_outdated(self, when=0): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def _add_key( - self, - keys, - issuer_id, - use, - key_type="", - kid="", - no_kid_issuer=None, - allow_missing_kid=False, + self, + keys, + issuer_id, + use, + key_type="", + kid="", + no_kid_issuer=None, + allow_missing_kid=False, ): _issuer = self._get_issuer(issuer_id) @@ -767,11 +767,11 @@ def build_keyjar(key_conf, kid_template="", keyjar=None, issuer_id=""): @deprecated_alias(issuer="issuer_id", owner="issuer_id") def init_key_jar( - public_path="", - private_path="", - key_defs="", - issuer_id="", - read_only=True, + public_path="", + private_path="", + key_defs="", + issuer_id="", + read_only=True, ): """ A number of cases here: From aaf98329cf6d74650500f8973bb7dbc44ecf2d6d Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 10:00:09 +0100 Subject: [PATCH 04/12] Cleaned up a bit. --- src/cryptojwt/key_bundle.py | 80 ++++++++++++++++++++++++++----------- src/cryptojwt/key_issuer.py | 14 ++++++- src/cryptojwt/key_jar.py | 33 ++++++++++----- tests/test_03_key_bundle.py | 6 +++ 4 files changed, 100 insertions(+), 33 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 44d4631d..3e0cc5dd 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -189,22 +189,22 @@ def __init__( """ self._keys = [] - self.remote = False - self.local = False self.cache_time = cache_time - self.ignore_errors_period = ignore_errors_period - self.ignore_errors_until = None # UNIX timestamp of last error - self.time_out = 0 self.etag = "" - self.source = None self.fileformat = fileformat.lower() + self.ignore_errors_period = ignore_errors_period + self.ignore_errors_until = None # UNIX timestamp of last error + self.ignore_invalid_keys = ignore_invalid_keys + self.imp_jwks = None self.keytype = keytype self.keyusage = keyusage - self.imp_jwks = None - self.last_updated = 0 - self.last_remote = None # HTTP Date of last remote update self.last_local = None # UNIX timestamp of last local update - self.ignore_invalid_keys = ignore_invalid_keys + self.last_remote = None # HTTP Date of last remote update + self.last_updated = 0 + self.local = False + self.remote = False + self.source = None + self.time_out = 0 if httpc: self.httpc = httpc @@ -761,16 +761,22 @@ def dump(self, cutoff: Optional[list] = None): res = { "keys": _keys, + "cache_time": self.cache_time, + "etag": self.etag, "fileformat": self.fileformat, - "last_updated": self.last_updated, - "last_remote": self.last_remote, - "last_local": self.last_local, "httpc_params": self.httpc_params, - "remote": self.remote, - "local": self.local, + "ignore_errors_period": self.ignore_errors_period, + "ignore_errors_until": self.ignore_errors_until, + "ignore_invalid_keys": self.ignore_invalid_keys, "imp_jwks": self.imp_jwks, + "keytype": self.keytype, + "keyusage": self.keyusage, + "last_local": self.last_local, + "last_remote": self.last_remote, + "last_updated": self.last_updated, + "local": self.local, + "remote": self.remote, "time_out": self.time_out, - "cache_time": self.cache_time, } if self.source: @@ -782,17 +788,45 @@ def load(self, spec): _keys = spec.get("keys", []) if _keys: self.do_keys(_keys) - self.source = spec.get("source", None) + self.cache_time = spec.get("cache_time", 0) + self.etag = spec.get("etag", "") self.fileformat = spec.get("fileformat", "jwks") - self.last_updated = spec.get("last_updated", 0) - self.last_remote = spec.get("last_remote", None) + self.httpc_params = spec.get("httpc_params", {}) + self.ignore_errors_period = spec.get("ignore_errors_period", 0) + self.ignore_errors_until = spec.get("ignore_errors_until", None) + self.ignore_invalid_keys = spec.get("ignore_invalid_keys", True) + self.imp_jwks = spec.get("imp_jwks", None) + self.keytype = (spec.get("keytype", "RSA"),) + self.keyusage = (spec.get("keyusage", None),) self.last_local = spec.get("last_local", None) - self.remote = spec.get("remote", False) + self.last_remote = spec.get("last_remote", None) + self.last_updated = spec.get("last_updated", 0) self.local = spec.get("local", False) - self.imp_jwks = spec.get("imp_jwks", None) + self.remote = spec.get("remote", False) + self.source = spec.get("source", None) self.time_out = spec.get("time_out", 0) - self.cache_time = spec.get("cache_time", 0) - self.httpc_params = spec.get("httpc_params", {}) + return self + + def flush(self): + self._keys = [] + self.cache_time = (300,) + self.etag = "" + self.fileformat = "jwks" + # self.httpc=None, + self.httpc_params = (None,) + self.ignore_errors_period = 0 + self.ignore_errors_until = None + self.ignore_invalid_keys = True + self.imp_jwks = None + self.keytype = ("RSA",) + self.keyusage = (None,) + self.last_local = None # UNIX timestamp of last local update + self.last_remote = None # HTTP Date of last remote update + self.last_updated = 0 + self.local = False + self.remote = False + self.source = None + self.time_out = 0 return self diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 34ede7df..a228960a 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -378,7 +378,7 @@ def dump(self, exclude=None, cutoff: Optional[list] = None) -> dict: def load(self, info): """ - :param items: A list with the information + :param items: A dictionary with the information to load :return: """ self.name = info["name"] @@ -390,6 +390,18 @@ def load(self, info): self._bundles = [KeyBundle().load(val) for val in info["bundles"]] return self + def flush(self): + self.ca_certs = (None,) + self.keybundle_cls = (KeyBundle,) + self.remove_after = (3600,) + self.httpc = (None,) + self.httpc_params = (None,) + self.name = "" + self.spec2key = None + self.remove_after = 0 + self._bundles = [] + return self + def update(self): for kb in self._bundles: kb.update() diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index cf5c20e1..ffc5f66a 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -636,11 +636,11 @@ def dump(self, exclude: Optional[bool] = None, cutoff: Optional[list] = None) -> """ info = { - "spec2key": self.spec2key, "ca_certs": self.ca_certs, + "httpc_params": self.httpc_params, "keybundle_cls": qualified_name(self.keybundle_cls), "remove_after": self.remove_after, - "httpc_params": self.httpc_params, + "spec2key": self.spec2key, } _issuers = {} @@ -668,19 +668,34 @@ def load(self, info): :param info: A dictionary with the information :return: """ - self.spec2key = info["spec2key"] - self.ca_certs = info["ca_certs"] - self.keybundle_cls = importer(info["keybundle_cls"]) - self.remove_after = info["remove_after"] - self.httpc_params = info["httpc_params"] + self.ca_certs = info.get("ca_certs", None) + self.httpc_params = info.get("httpc_params", None) + self.keybundle_cls = importer(info.get("keybundle_cls", KeyBundle)) + self.remove_after = info.get("remove_after", 3600) + self.spec2key = info.get("spec2key", {}) - for _issuer_id, _issuer_desc in info["issuers"].items(): - self._issuers[_issuer_id] = KeyIssuer().load(_issuer_desc) + _issuers = info.get("issuers", None) + if _issuers is None: + self._issuers = {} + else: + for _issuer_id, _issuer_desc in _issuers.items(): + self._issuers[_issuer_id] = KeyIssuer().load(_issuer_desc) return self def loads(self, string): return self.load(json.loads(string)) + def flush(self): + self.ca_certs = None + self.httpc_params = None + self._issuers = {} + self.keybundle_cls = KeyBundle + self.remove_after = 3600 + self.spec2key = {} + # self.httpc=None, + + return self + @deprecated_alias(issuer="issuer_id", owner="issuer_id") def key_summary(self, issuer_id): _issuer = self._get_issuer(issuer_id) diff --git a/tests/test_03_key_bundle.py b/tests/test_03_key_bundle.py index bfd4f958..3530a7d8 100755 --- a/tests/test_03_key_bundle.py +++ b/tests/test_03_key_bundle.py @@ -953,10 +953,16 @@ def test_export_inactive(): res = kb.dump() assert set(res.keys()) == { "cache_time", + "etag", "fileformat", "httpc_params", + "ignore_errors_until", + "ignore_errors_period", + "ignore_invalid_keys", "imp_jwks", "keys", + "keytype", + "keyusage", "last_updated", "last_remote", "last_local", From 5467ca1bbcfe4e2ef7d02f040c2b6050a2089eb0 Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 10:41:19 +0100 Subject: [PATCH 05/12] Dealt with reviewers issues. --- pyproject.toml | 2 +- src/cryptojwt/key_bundle.py | 7 ++++++- src/cryptojwt/key_issuer.py | 14 ++++++++++---- src/cryptojwt/key_jar.py | 15 ++++++++++----- 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 69fd4e45..01b995c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ exclude_lines = [ [tool.poetry] name = "cryptojwt" -version = "1.4.2" +version = "1.5.0" description = "Python implementation of JWT, JWE, JWS and JWK" authors = ["Roland Hedberg "] license = "Apache-2.0" diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 3e0cc5dd..8ad0684c 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -6,6 +6,7 @@ import time from datetime import datetime from functools import cmp_to_key +from typing import List from typing import Optional import requests @@ -751,7 +752,7 @@ def difference(self, bundle): return [k for k in self._keys if k not in bundle] - def dump(self, cutoff: Optional[list] = None): + def dump(self, exclude_attribute: Optional[List[str]] = None): _keys = [] for _k in self._keys: _ser = _k.to_dict() @@ -782,6 +783,10 @@ def dump(self, cutoff: Optional[list] = None): if self.source: res["source"] = self.source + if exclude_attribute: + for attr in exclude_attribute: + del res[attr] + return res def load(self, spec): diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index a228960a..493f1300 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -1,6 +1,7 @@ import json import logging import os +from typing import List from typing import Optional from requests import request @@ -351,18 +352,17 @@ def __len__(self): nr += len(kb) return nr - def dump(self, exclude=None, cutoff: Optional[list] = None) -> dict: + def dump(self, exclude_attribute: Optional[List[str]] = None) -> dict: """ Returns the content as a dictionary. - :param exclude: Issuer that should not be include in the dump - :param cutoff: List of attribute name for objects that should be ignored. + :param exclude_attribute: List of attribute names for objects that should be ignored. :return: A dictionary """ _bundles = [] for kb in self._bundles: - _bundles.append(kb.dump(cutoff=cutoff)) + _bundles.append(kb.dump(exclude_attribute=exclude_attribute)) info = { "name": self.name, @@ -373,6 +373,12 @@ def dump(self, exclude=None, cutoff: Optional[list] = None) -> dict: "remove_after": self.remove_after, "httpc_params": self.httpc_params, } + + # remove after the fact + if exclude_attribute: + for attr in exclude_attribute: + del info[attr] + return info def load(self, info): diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index ffc5f66a..3db63f6d 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -626,12 +626,17 @@ def copy(self): def __len__(self): return len(self._issuers) - def dump(self, exclude: Optional[bool] = None, cutoff: Optional[list] = None) -> dict: + def dump( + self, + exclude_issuer: Optional[List[str]] = None, + exclude_attribute: Optional[List[str]] = None, + ) -> dict: """ Returns the key jar content as dictionary - :param cutoff: list of attribute names that should be ignored when dumping. - :type cutoff: list + :param exclude_issuer: A list of issuers you don't want included. + :param exclude_attribute: list of attribute names that should be ignored when dumping. + :type exclude_attribute: list :return: A dictionary """ @@ -645,9 +650,9 @@ def dump(self, exclude: Optional[bool] = None, cutoff: Optional[list] = None) -> _issuers = {} for _id, _issuer in self._issuers.items(): - if exclude and _issuer.name in exclude: + if exclude_issuer and _issuer.name in exclude_issuer: continue - _issuers[_id] = _issuer.dump(cutoff=cutoff) + _issuers[_id] = _issuer.dump(exclude_attribute=exclude_attribute) info["issuers"] = _issuers return info From 85c6a4aa018eb8e3264d57b17d26578a3cc969df Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 12:31:15 +0100 Subject: [PATCH 06/12] Changed attribute names - plural ! --- src/cryptojwt/key_bundle.py | 6 +++--- src/cryptojwt/key_issuer.py | 10 +++++----- src/cryptojwt/key_jar.py | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 8ad0684c..bb356b75 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -752,7 +752,7 @@ def difference(self, bundle): return [k for k in self._keys if k not in bundle] - def dump(self, exclude_attribute: Optional[List[str]] = None): + def dump(self, exclude_attributes: Optional[List[str]] = None): _keys = [] for _k in self._keys: _ser = _k.to_dict() @@ -783,8 +783,8 @@ def dump(self, exclude_attribute: Optional[List[str]] = None): if self.source: res["source"] = self.source - if exclude_attribute: - for attr in exclude_attribute: + if exclude_attributes: + for attr in exclude_attributes: del res[attr] return res diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 493f1300..a231e837 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -352,17 +352,17 @@ def __len__(self): nr += len(kb) return nr - def dump(self, exclude_attribute: Optional[List[str]] = None) -> dict: + def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict: """ Returns the content as a dictionary. - :param exclude_attribute: List of attribute names for objects that should be ignored. + :param exclude_attributes: List of attribute names for objects that should be ignored. :return: A dictionary """ _bundles = [] for kb in self._bundles: - _bundles.append(kb.dump(exclude_attribute=exclude_attribute)) + _bundles.append(kb.dump(exclude_attributes=exclude_attributes)) info = { "name": self.name, @@ -375,8 +375,8 @@ def dump(self, exclude_attribute: Optional[List[str]] = None) -> dict: } # remove after the fact - if exclude_attribute: - for attr in exclude_attribute: + if exclude_attributes: + for attr in exclude_attributes: del info[attr] return info diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 3db63f6d..a9fe2841 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -629,14 +629,14 @@ def __len__(self): def dump( self, exclude_issuer: Optional[List[str]] = None, - exclude_attribute: Optional[List[str]] = None, + exclude_attributes: Optional[List[str]] = None, ) -> dict: """ Returns the key jar content as dictionary - :param exclude_issuer: A list of issuers you don't want included. - :param exclude_attribute: list of attribute names that should be ignored when dumping. - :type exclude_attribute: list + :param exclude_issuers: A list of issuers you don't want included. + :param exclude_attributes: list of attribute names that should be ignored when dumping. + :type exclude_attributes: list :return: A dictionary """ @@ -652,7 +652,7 @@ def dump( for _id, _issuer in self._issuers.items(): if exclude_issuer and _issuer.name in exclude_issuer: continue - _issuers[_id] = _issuer.dump(exclude_attribute=exclude_attribute) + _issuers[_id] = _issuer.dump(exclude_attributes=exclude_attributes) info["issuers"] = _issuers return info From 161db5e5c288a51eac0e833a6bc9e55696cdaab5 Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 13:36:08 +0100 Subject: [PATCH 07/12] Improved the code a bit. --- src/cryptojwt/key_bundle.py | 5 ++++- src/cryptojwt/key_issuer.py | 5 ++++- src/cryptojwt/key_jar.py | 28 ++++++++++++++++++---------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index bb356b75..4c26f8bf 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -785,7 +785,10 @@ def dump(self, exclude_attributes: Optional[List[str]] = None): if exclude_attributes: for attr in exclude_attributes: - del res[attr] + try: + del res[attr] + except KeyError: + pass return res diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index a231e837..0ff7f126 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -377,7 +377,10 @@ def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict: # remove after the fact if exclude_attributes: for attr in exclude_attributes: - del info[attr] + try: + del info[attr] + except KeyError: + pass return info diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index a9fe2841..d62367f8 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -628,7 +628,7 @@ def __len__(self): def dump( self, - exclude_issuer: Optional[List[str]] = None, + exclude_issuers: Optional[List[str]] = None, exclude_attributes: Optional[List[str]] = None, ) -> dict: """ @@ -648,23 +648,31 @@ def dump( "spec2key": self.spec2key, } - _issuers = {} - for _id, _issuer in self._issuers.items(): - if exclude_issuer and _issuer.name in exclude_issuer: - continue - _issuers[_id] = _issuer.dump(exclude_attributes=exclude_attributes) - info["issuers"] = _issuers + if exclude_attributes: + for attr in exclude_attributes: + try: + del info[attr] + except KeyError: + pass + + if "issuers" not in exclude_attributes: + _issuers = {} + for _id, _issuer in self._issuers.items(): + if exclude_issuers and _issuer.name in exclude_issuers: + continue + _issuers[_id] = _issuer.dump(exclude_attributes=exclude_attributes) + info["issuers"] = _issuers return info - def dumps(self, exclude=None): + def dumps(self, exclude_issuers: Optional[List[str]] = None): """ Returns a JSON representation of the key jar - :param exclude: Exclude these issuers + :param exclude_issuers: Exclude these issuers :return: A string """ - _dict = self.dump(exclude=exclude) + _dict = self.dump(exclude_issuers=exclude_issuers) return json.dumps(_dict) def load(self, info): From eba52998540842ad672a2a53b49c81a2799bf9c6 Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 13:45:10 +0100 Subject: [PATCH 08/12] Fixed exclude_attributes problem. --- src/cryptojwt/key_jar.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index d62367f8..85532a69 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -626,6 +626,17 @@ def copy(self): def __len__(self): return len(self._issuers) + def _dump_issuers(self, + exclude_issuers: Optional[List[str]] = None, + exclude_attributes: Optional[List[str]] = None + ): + _issuers = {} + for _id, _issuer in self._issuers.items(): + if exclude_issuers and _issuer.name in exclude_issuers: + continue + _issuers[_id] = _issuer.dump(exclude_attributes=exclude_attributes) + return _issuers + def dump( self, exclude_issuers: Optional[List[str]] = None, @@ -655,13 +666,12 @@ def dump( except KeyError: pass - if "issuers" not in exclude_attributes: - _issuers = {} - for _id, _issuer in self._issuers.items(): - if exclude_issuers and _issuer.name in exclude_issuers: - continue - _issuers[_id] = _issuer.dump(exclude_attributes=exclude_attributes) - info["issuers"] = _issuers + if exclude_attributes is None: + info["issuers"] = self._dump_issuers(exclude_issuers=exclude_issuers, + exclude_attributes=exclude_attributes) + elif "issuers" not in exclude_attributes: + info["issuers"] = self._dump_issuers(exclude_issuers=exclude_issuers, + exclude_attributes=exclude_attributes) return info From cd543a90450f7e33f6ddd670d930d8b055616853 Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 14:30:51 +0100 Subject: [PATCH 09/12] black&isort --- src/cryptojwt/key_jar.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/cryptojwt/key_jar.py b/src/cryptojwt/key_jar.py index 85532a69..c6fee93b 100755 --- a/src/cryptojwt/key_jar.py +++ b/src/cryptojwt/key_jar.py @@ -626,10 +626,11 @@ def copy(self): def __len__(self): return len(self._issuers) - def _dump_issuers(self, - exclude_issuers: Optional[List[str]] = None, - exclude_attributes: Optional[List[str]] = None - ): + def _dump_issuers( + self, + exclude_issuers: Optional[List[str]] = None, + exclude_attributes: Optional[List[str]] = None, + ): _issuers = {} for _id, _issuer in self._issuers.items(): if exclude_issuers and _issuer.name in exclude_issuers: @@ -667,11 +668,13 @@ def dump( pass if exclude_attributes is None: - info["issuers"] = self._dump_issuers(exclude_issuers=exclude_issuers, - exclude_attributes=exclude_attributes) + info["issuers"] = self._dump_issuers( + exclude_issuers=exclude_issuers, exclude_attributes=exclude_attributes + ) elif "issuers" not in exclude_attributes: - info["issuers"] = self._dump_issuers(exclude_issuers=exclude_issuers, - exclude_attributes=exclude_attributes) + info["issuers"] = self._dump_issuers( + exclude_issuers=exclude_issuers, exclude_attributes=exclude_attributes + ) return info From 1bf46d61583d8e38412692e182a8d1df1d779a91 Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 15:38:40 +0100 Subject: [PATCH 10/12] Fixed some dump/load problems. --- src/cryptojwt/key_bundle.py | 128 +++++++++++++++++++------------- src/cryptojwt/key_issuer.py | 73 +++++++++--------- src/cryptojwt/serialize/item.py | 2 +- tests/test_03_key_bundle.py | 16 ++++ 4 files changed, 129 insertions(+), 90 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index 4c26f8bf..a65e79fe 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -153,6 +153,26 @@ def ec_init(spec): class KeyBundle: """The Key Bundle""" + params = { + "cache_time": 0, + "etag": "", + "fileformat": "jwks", + "httpc_params": {}, + "ignore_errors_period": 0, + "ignore_errors_until": None, + "ignore_invalid_keys": True, + "imp_jwks": None, + "keytype": "RSA", + "keyusage": None, + "last_local": None, + "last_remote": None, + "last_updated": 0, + "local": False, + "remote": False, + "source": None, + "time_out": 0, + } + def __init__( self, keys=None, @@ -491,6 +511,7 @@ def update(self): # reread everything self._keys = [] + updated = None try: if self.local: @@ -753,66 +774,67 @@ def difference(self, bundle): return [k for k in self._keys if k not in bundle] def dump(self, exclude_attributes: Optional[List[str]] = None): - _keys = [] - for _k in self._keys: - _ser = _k.to_dict() - if _k.inactive_since: - _ser["inactive_since"] = _k.inactive_since - _keys.append(_ser) - - res = { - "keys": _keys, - "cache_time": self.cache_time, - "etag": self.etag, - "fileformat": self.fileformat, - "httpc_params": self.httpc_params, - "ignore_errors_period": self.ignore_errors_period, - "ignore_errors_until": self.ignore_errors_until, - "ignore_invalid_keys": self.ignore_invalid_keys, - "imp_jwks": self.imp_jwks, - "keytype": self.keytype, - "keyusage": self.keyusage, - "last_local": self.last_local, - "last_remote": self.last_remote, - "last_updated": self.last_updated, - "local": self.local, - "remote": self.remote, - "time_out": self.time_out, - } - - if self.source: - res["source"] = self.source - - if exclude_attributes: - for attr in exclude_attributes: - try: - del res[attr] - except KeyError: - pass + if exclude_attributes is None: + exclude_attributes = [] + + res = {} + + if "keys" not in exclude_attributes: + _keys = [] + for _k in self._keys: + _ser = _k.to_dict() + if _k.inactive_since: + _ser["inactive_since"] = _k.inactive_since + _keys.append(_ser) + res["keys"] = _keys + + for attr, default in self.params.items(): + if attr in exclude_attributes: + continue + val = getattr(self, attr) + res[attr] = val + + # res = { + # "cache_time": self.cache_time, + # "etag": self.etag, + # "fileformat": self.fileformat, + # "httpc_params": self.httpc_params, + # "ignore_errors_period": self.ignore_errors_period, + # "ignore_errors_until": self.ignore_errors_until, + # "ignore_invalid_keys": self.ignore_invalid_keys, + # "imp_jwks": self.imp_jwks, + # "keytype": self.keytype, + # "keyusage": self.keyusage, + # "last_local": self.last_local, + # "last_remote": self.last_remote, + # "last_updated": self.last_updated, + # "local": self.local, + # "remote": self.remote, + # "time_out": self.time_out, + # } + + # if self.source: + # res["source"] = self.source return res def load(self, spec): + """ + Sets attributes according to a specification. + Does not overwrite an existing attributes value with a default value. + + :param spec: Dictionary with attributes and value to populate the instance with + :return: The instance itself + """ _keys = spec.get("keys", []) if _keys: self.do_keys(_keys) - self.cache_time = spec.get("cache_time", 0) - self.etag = spec.get("etag", "") - self.fileformat = spec.get("fileformat", "jwks") - self.httpc_params = spec.get("httpc_params", {}) - self.ignore_errors_period = spec.get("ignore_errors_period", 0) - self.ignore_errors_until = spec.get("ignore_errors_until", None) - self.ignore_invalid_keys = spec.get("ignore_invalid_keys", True) - self.imp_jwks = spec.get("imp_jwks", None) - self.keytype = (spec.get("keytype", "RSA"),) - self.keyusage = (spec.get("keyusage", None),) - self.last_local = spec.get("last_local", None) - self.last_remote = spec.get("last_remote", None) - self.last_updated = spec.get("last_updated", 0) - self.local = spec.get("local", False) - self.remote = spec.get("remote", False) - self.source = spec.get("source", None) - self.time_out = spec.get("time_out", 0) + + for attr, default in self.params.items(): + val = spec.get(attr) + if val: + setattr(self, attr, val) + return self def flush(self): diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index 0ff7f126..a1bc3a81 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -17,13 +17,22 @@ __author__ = "Roland Hedberg" - logger = logging.getLogger(__name__) class KeyIssuer(object): """ A key issuer instance contains a number of KeyBundles. """ + params = { + "ca_certs": None, + "keybundle_cls": KeyBundle, + "remove_after": 3600, + "httpc": None, + "httpc_params": None, + "name": "", + "spec2key": None, + } + def __init__( self, ca_certs=None, @@ -360,27 +369,23 @@ def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict: :return: A dictionary """ - _bundles = [] - for kb in self._bundles: - _bundles.append(kb.dump(exclude_attributes=exclude_attributes)) - - info = { - "name": self.name, - "bundles": _bundles, - "keybundle_cls": qualified_name(self.keybundle_cls), - "spec2key": self.spec2key, - "ca_certs": self.ca_certs, - "remove_after": self.remove_after, - "httpc_params": self.httpc_params, - } - - # remove after the fact - if exclude_attributes: - for attr in exclude_attributes: - try: - del info[attr] - except KeyError: - pass + if exclude_attributes is None: + exclude_attributes = [] + + info = {} + for attr, default in self.params.items(): + if attr in exclude_attributes: + continue + val = getattr(self, attr) + if attr == "keybundle_cls": + val = qualified_name(val) + info[attr] = val + + if "bundles" not in exclude_attributes: + _bundles = [] + for kb in self._bundles: + _bundles.append(kb.dump(exclude_attributes=exclude_attributes)) + info["bundles"] = _bundles return info @@ -390,24 +395,20 @@ def load(self, info): :param items: A dictionary with the information to load :return: """ - self.name = info["name"] - self.keybundle_cls = importer(info["keybundle_cls"]) - self.spec2key = info["spec2key"] - self.ca_certs = info["ca_certs"] - self.remove_after = info["remove_after"] - self.httpc_params = info["httpc_params"] + for attr, default in self.params.items(): + val = info.get(attr) + if val: + if attr == "keybundle_cls": + val = importer(val) + setattr(self, attr, val) + self._bundles = [KeyBundle().load(val) for val in info["bundles"]] return self def flush(self): - self.ca_certs = (None,) - self.keybundle_cls = (KeyBundle,) - self.remove_after = (3600,) - self.httpc = (None,) - self.httpc_params = (None,) - self.name = "" - self.spec2key = None - self.remove_after = 0 + for attr, default in self.params.items(): + setattr(self, attr, default) + self._bundles = [] return self diff --git a/src/cryptojwt/serialize/item.py b/src/cryptojwt/serialize/item.py index a087c8dc..6b96a74a 100644 --- a/src/cryptojwt/serialize/item.py +++ b/src/cryptojwt/serialize/item.py @@ -7,7 +7,7 @@ class KeyIssuer: @staticmethod def serialize(item: key_issuer.KeyIssuer) -> str: """ Convert from KeyIssuer to JSON """ - return json.dumps(item.dump()) + return json.dumps(item.dump(exclude_attributes=["keybundle_cls", "httpc"])) def deserialize(self, spec: str) -> key_issuer.KeyIssuer: """ Convert from JSON to KeyIssuer """ diff --git a/tests/test_03_key_bundle.py b/tests/test_03_key_bundle.py index 3530a7d8..3d05ee5c 100755 --- a/tests/test_03_key_bundle.py +++ b/tests/test_03_key_bundle.py @@ -968,6 +968,7 @@ def test_export_inactive(): "last_local", "remote", "local", + "source", "time_out", } @@ -1085,3 +1086,18 @@ def test_ignore_invalid_keys(): with pytest.raises(UnknownKeyType): KeyBundle(keys={"keys": [rsa_key_dict]}, ignore_invalid_keys=False) + + +def test_exclude_attributes(): + source = "https://example.com/keys.json" + # Mock response + with responses.RequestsMock() as rsps: + rsps.add(method="GET", url=source, json=JWKS_DICT, status=200) + httpc_params = {"timeout": (2, 2)} # connect, read timeouts in seconds + kb = KeyBundle(source=source, httpc=requests.request, httpc_params=httpc_params) + kb.do_remote() + + exp = kb.dump(exclude_attributes=["cache_time", "ignore_invalid_keys"]) + kb2 = KeyBundle(cache_time=600, ignore_invalid_keys=False).load(exp) + assert kb2.cache_time == 600 + assert kb2.ignore_invalid_keys is False From bbe0d1e00f0a8eee738fc35c8ec1479a2e202820 Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 15:58:15 +0100 Subject: [PATCH 11/12] Whatever dump() produces MUST be valid input to json.dumps(). --- src/cryptojwt/key_bundle.py | 22 ---------- src/cryptojwt/key_issuer.py | 14 +++--- src/cryptojwt/serialize/item.py | 2 +- tests/test_03_key_bundle.py | 77 ++++++++++++++++++++------------- tests/test_04_key_issuer.py | 8 ++++ tests/test_04_key_jar.py | 10 +++++ 6 files changed, 72 insertions(+), 61 deletions(-) diff --git a/src/cryptojwt/key_bundle.py b/src/cryptojwt/key_bundle.py index a65e79fe..34b44205 100755 --- a/src/cryptojwt/key_bundle.py +++ b/src/cryptojwt/key_bundle.py @@ -794,28 +794,6 @@ def dump(self, exclude_attributes: Optional[List[str]] = None): val = getattr(self, attr) res[attr] = val - # res = { - # "cache_time": self.cache_time, - # "etag": self.etag, - # "fileformat": self.fileformat, - # "httpc_params": self.httpc_params, - # "ignore_errors_period": self.ignore_errors_period, - # "ignore_errors_until": self.ignore_errors_until, - # "ignore_invalid_keys": self.ignore_invalid_keys, - # "imp_jwks": self.imp_jwks, - # "keytype": self.keytype, - # "keyusage": self.keyusage, - # "last_local": self.last_local, - # "last_remote": self.last_remote, - # "last_updated": self.last_updated, - # "local": self.local, - # "remote": self.remote, - # "time_out": self.time_out, - # } - - # if self.source: - # res["source"] = self.source - return res def load(self, spec): diff --git a/src/cryptojwt/key_issuer.py b/src/cryptojwt/key_issuer.py index a1bc3a81..42a262ee 100755 --- a/src/cryptojwt/key_issuer.py +++ b/src/cryptojwt/key_issuer.py @@ -25,11 +25,10 @@ class KeyIssuer(object): params = { "ca_certs": None, - "keybundle_cls": KeyBundle, - "remove_after": 3600, - "httpc": None, "httpc_params": None, + "keybundle_cls": KeyBundle, "name": "", + "remove_after": 3600, "spec2key": None, } @@ -56,14 +55,13 @@ def __init__( self._bundles = [] - self.keybundle_cls = keybundle_cls - self.name = name - - self.spec2key = {} self.ca_certs = ca_certs - self.remove_after = remove_after self.httpc = httpc or request self.httpc_params = httpc_params or {} + self.keybundle_cls = keybundle_cls + self.name = name + self.remove_after = remove_after + self.spec2key = {} def __repr__(self) -> str: return ''.format(self.name, self.key_summary()) diff --git a/src/cryptojwt/serialize/item.py b/src/cryptojwt/serialize/item.py index 6b96a74a..206eb7de 100644 --- a/src/cryptojwt/serialize/item.py +++ b/src/cryptojwt/serialize/item.py @@ -7,7 +7,7 @@ class KeyIssuer: @staticmethod def serialize(item: key_issuer.KeyIssuer) -> str: """ Convert from KeyIssuer to JSON """ - return json.dumps(item.dump(exclude_attributes=["keybundle_cls", "httpc"])) + return json.dumps(item.dump(exclude_attributes=["keybundle_cls"])) def deserialize(self, spec: str) -> key_issuer.KeyIssuer: """ Convert from JSON to KeyIssuer """ diff --git a/tests/test_03_key_bundle.py b/tests/test_03_key_bundle.py index 3d05ee5c..5d8a4cfc 100755 --- a/tests/test_03_key_bundle.py +++ b/tests/test_03_key_bundle.py @@ -1,14 +1,14 @@ # pylint: disable=missing-docstring,no-self-use import json import os +from pathlib import Path import shutil import time -from pathlib import Path +from cryptography.hazmat.primitives.asymmetric import rsa import pytest import requests import responses -from cryptography.hazmat.primitives.asymmetric import rsa from cryptojwt.exception import UnknownKeyType from cryptojwt.jwk.ec import ECKey @@ -53,8 +53,8 @@ def full_path(local_file): "e": "AQAB", "kid": "abc", "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY" - "2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfK" - "qoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", + "2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfK" + "qoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", } ] } @@ -63,11 +63,11 @@ def full_path(local_file): "keys": [ { "n": "zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S" - "_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFY" - "Inq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVb" - "CGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znan" - "LwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MX" - "sGxBHf3AKT5w", + "_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFY" + "Inq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVb" + "CGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znan" + "LwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MX" + "sGxBHf3AKT5w", "e": "AQAB", "kty": "RSA", "kid": "rsa1", @@ -87,11 +87,11 @@ def full_path(local_file): "kid": "kriMPdmBvx68skT8-mPAB3BseeA", "kty": "RSA", "n": "kSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS" - "_AHsBeQPqYygfYVJL6_EgzVuwRk5txr9e3n1uml94fLyq_AXbwo9yAduf4dCHT" - "P8CWR1dnDR-Qnz_4PYlWVEuuHHONOw_blbfdMjhY-C_BYM2E3pRxbohBb3x__C" - "fueV7ddz2LYiH3wjz0QS_7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd_" - "GTgWN8A-6SN1r4hzpjFKFLbZnBt77ACSiYx-IHK4Mp-NaVEi5wQtSsjQtI--Xs" - "okxRDqYLwus1I1SihgbV_STTg5enufuw", + "_AHsBeQPqYygfYVJL6_EgzVuwRk5txr9e3n1uml94fLyq_AXbwo9yAduf4dCHT" + "P8CWR1dnDR-Qnz_4PYlWVEuuHHONOw_blbfdMjhY-C_BYM2E3pRxbohBb3x__C" + "fueV7ddz2LYiH3wjz0QS_7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd_" + "GTgWN8A-6SN1r4hzpjFKFLbZnBt77ACSiYx-IHK4Mp-NaVEi5wQtSsjQtI--Xs" + "okxRDqYLwus1I1SihgbV_STTg5enufuw", "use": "sig", "x5c": [ "MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKz" @@ -121,11 +121,11 @@ def full_path(local_file): "kid": "MnC_VZcATfM5pOYiJHMba9goEKY", "kty": "RSA", "n": "vIqz-4-ER_vNWLON9yv8hIYV737JQ6rCl6XfzOC628seYUPf0TaGk91CFxefhz" - "h23V9Tkq-RtwN1Vs_z57hO82kkzL-cQHZX3bMJD-GEGOKXCEXURN7VMyZWMAuz" - "QoW9vFb1k3cR1RW_EW_P-C8bb2dCGXhBYqPfHyimvz2WarXhntPSbM5XyS5v5y" - "Cw5T_Vuwqqsio3V8wooWGMpp61y12NhN8bNVDQAkDPNu2DT9DXB1g0CeFINp_K" - "AS_qQ2Kq6TSvRHJqxRR68RezYtje9KAqwqx4jxlmVAQy0T3-T-IAbsk1wRtWDn" - "dhO6s1Os-dck5TzyZ_dNOhfXgelixLUQ", + "h23V9Tkq-RtwN1Vs_z57hO82kkzL-cQHZX3bMJD-GEGOKXCEXURN7VMyZWMAuz" + "QoW9vFb1k3cR1RW_EW_P-C8bb2dCGXhBYqPfHyimvz2WarXhntPSbM5XyS5v5y" + "Cw5T_Vuwqqsio3V8wooWGMpp61y12NhN8bNVDQAkDPNu2DT9DXB1g0CeFINp_K" + "AS_qQ2Kq6TSvRHJqxRR68RezYtje9KAqwqx4jxlmVAQy0T3-T-IAbsk1wRtWDn" + "dhO6s1Os-dck5TzyZ_dNOhfXgelixLUQ", "use": "sig", "x5c": [ "MIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb" @@ -152,12 +152,12 @@ def full_path(local_file): { "e": "AQAB", "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b" - "-b112-36a304b66dad/v2.0/", + "-b112-36a304b66dad/v2.0/", "kid": "GvnPApfWMdLRi8PDmisFn7bprKg", "kty": "RSA", "n": "5ymq_xwmst1nstPr8YFOTyD1J5N4idYmrph7AyAv95RbWXfDRqy8CMRG7sJq" - "-UWOKVOA4MVrd_NdV-ejj1DE5MPSiG" - "-mZK_5iqRCDFvPYqOyRj539xaTlARNY4jeXZ0N6irZYKqSfYACjkkKxbLKcijSu1pJ48thXOTED0oNa6U", + "-UWOKVOA4MVrd_NdV-ejj1DE5MPSiG" + "-mZK_5iqRCDFvPYqOyRj539xaTlARNY4jeXZ0N6irZYKqSfYACjkkKxbLKcijSu1pJ48thXOTED0oNa6U", "use": "sig", "x5c": [ "MIICWzCCAcSgAwIBAgIJAKVzMH2FfC12MA0GCSqGSIb3DQEBBQUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVib" @@ -181,12 +181,13 @@ def full_path(local_file): { "e": "AQAB", "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b" - "-b112-36a304b66dad/v2.0/", + "-b112-36a304b66dad/v2.0/", "kid": "dEtpjbEvbhfgwUI-bdK5xAU_9UQ", "kty": "RSA", - "n": "x7HNcD9ZxTFRaAgZ7-gdYLkgQua3zvQseqBJIt8Uq3MimInMZoE9QGQeSML7qZPlowb5BUakdLI70ayM4vN36--0ht8-oCHhl8Yj" - "GFQkU-Iv2yahWHEP-1EK6eOEYu6INQP9Lk0HMk3QViLwshwb" - "-KXVD02jdmX2HNdYJdPyc0c", + "n": + "x7HNcD9ZxTFRaAgZ7-gdYLkgQua3zvQseqBJIt8Uq3MimInMZoE9QGQeSML7qZPlowb5BUakdLI70ayM4vN36--0ht8-oCHhl8Yj" + "GFQkU-Iv2yahWHEP-1EK6eOEYu6INQP9Lk0HMk3QViLwshwb" + "-KXVD02jdmX2HNdYJdPyc0c", "use": "sig", "x5c": [ "MIICWzCCAcSgAwIBAgIJAL3MzqqEFMYjMA0GCSqGSIb3DQEBBQUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVib" @@ -278,7 +279,7 @@ def test_ignore_unknown_types(): kb = KeyBundle( { "kid": "q-H9y8iuh3BIKZBbK6S0mH_isBlJsk" - "-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw", + "-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw", "use": "sig", "alg": "EdDSA", "kty": "OKP", @@ -618,14 +619,16 @@ def test_loads_1(): "kty": "RSA", "use": "sig", "e": "AQAB", - "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", + "n": + "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", "kid": "1", }, { "kty": "RSA", "use": "enc", "e": "AQAB", - "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", + "n": + "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", "kid": "2", }, ] @@ -658,7 +661,8 @@ def test_dump_jwk(): JWKS_DICT = { "keys": [ { - "n": u"zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFYInq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVbCGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znanLwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MXsGxBHf3AKT5w", + "n": + u"zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFYInq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVbCGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znanLwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MXsGxBHf3AKT5w", "e": u"AQAB", "kty": "RSA", "kid": "5-VBFv40P8D4I-7SFz7hMugTbPs", @@ -1101,3 +1105,16 @@ def test_exclude_attributes(): kb2 = KeyBundle(cache_time=600, ignore_invalid_keys=False).load(exp) assert kb2.cache_time == 600 assert kb2.ignore_invalid_keys is False + + +def test_remote_dump_json(): + source = "https://example.com/keys.json" + # Mock response + with responses.RequestsMock() as rsps: + rsps.add(method="GET", url=source, json=JWKS_DICT, status=200) + httpc_params = {"timeout": (2, 2)} # connect, read timeouts in seconds + kb = KeyBundle(source=source, httpc=requests.request, httpc_params=httpc_params) + kb.do_remote() + + exp = kb.dump() + assert json.dumps(exp) diff --git a/tests/test_04_key_issuer.py b/tests/test_04_key_issuer.py index fedad978..ae4778d1 100755 --- a/tests/test_04_key_issuer.py +++ b/tests/test_04_key_issuer.py @@ -1,3 +1,4 @@ +import json import os import shutil import time @@ -743,6 +744,13 @@ def test_dump(): assert nkj.get("sig", "rsa", kid="MnC_VZcATfM5pOYiJHMba9goEKY") +def test_dump_json(): + issuer = KeyIssuer() + issuer.add_kb(KeyBundle(JWK2["keys"])) + + res = issuer.dump() + assert json.dumps(res) + def test_contains(): issuer = KeyIssuer() issuer.add_kb(KeyBundle(JWK1["keys"])) diff --git a/tests/test_04_key_jar.py b/tests/test_04_key_jar.py index 53cb5ef5..b9b17ebf 100755 --- a/tests/test_04_key_jar.py +++ b/tests/test_04_key_jar.py @@ -1033,6 +1033,16 @@ def test_dump(): assert nkj.get_signing_key("rsa", "C", kid="MnC_VZcATfM5pOYiJHMba9goEKY") +def test_dump_json(): + kj = KeyJar() + kj.add_kb("Alice", KeyBundle(JWK0["keys"])) + kj.add_kb("Bob", KeyBundle(JWK1["keys"])) + kj.add_kb("C", KeyBundle(JWK2["keys"])) + + res = kj.dump() + assert json.dumps(res) + + def test_contains(): kj = KeyJar() kj.add_kb("Alice", KeyBundle(JWK0["keys"])) From 99f3780ced702b6ed10e6d5cc0683c01e63c956a Mon Sep 17 00:00:00 2001 From: roland Date: Sat, 20 Mar 2021 16:04:51 +0100 Subject: [PATCH 12/12] isort&back --- tests/test_03_key_bundle.py | 64 +++++++++++++++++-------------------- tests/test_04_key_issuer.py | 1 + tests/test_04_key_jar.py | 2 +- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/tests/test_03_key_bundle.py b/tests/test_03_key_bundle.py index 5d8a4cfc..d32af9a9 100755 --- a/tests/test_03_key_bundle.py +++ b/tests/test_03_key_bundle.py @@ -1,14 +1,14 @@ # pylint: disable=missing-docstring,no-self-use import json import os -from pathlib import Path import shutil import time +from pathlib import Path -from cryptography.hazmat.primitives.asymmetric import rsa import pytest import requests import responses +from cryptography.hazmat.primitives.asymmetric import rsa from cryptojwt.exception import UnknownKeyType from cryptojwt.jwk.ec import ECKey @@ -53,8 +53,8 @@ def full_path(local_file): "e": "AQAB", "kid": "abc", "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY" - "2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfK" - "qoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", + "2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfK" + "qoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", } ] } @@ -63,11 +63,11 @@ def full_path(local_file): "keys": [ { "n": "zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S" - "_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFY" - "Inq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVb" - "CGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znan" - "LwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MX" - "sGxBHf3AKT5w", + "_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFY" + "Inq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVb" + "CGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znan" + "LwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MX" + "sGxBHf3AKT5w", "e": "AQAB", "kty": "RSA", "kid": "rsa1", @@ -87,11 +87,11 @@ def full_path(local_file): "kid": "kriMPdmBvx68skT8-mPAB3BseeA", "kty": "RSA", "n": "kSCWg6q9iYxvJE2NIhSyOiKvqoWCO2GFipgH0sTSAs5FalHQosk9ZNTztX0ywS" - "_AHsBeQPqYygfYVJL6_EgzVuwRk5txr9e3n1uml94fLyq_AXbwo9yAduf4dCHT" - "P8CWR1dnDR-Qnz_4PYlWVEuuHHONOw_blbfdMjhY-C_BYM2E3pRxbohBb3x__C" - "fueV7ddz2LYiH3wjz0QS_7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd_" - "GTgWN8A-6SN1r4hzpjFKFLbZnBt77ACSiYx-IHK4Mp-NaVEi5wQtSsjQtI--Xs" - "okxRDqYLwus1I1SihgbV_STTg5enufuw", + "_AHsBeQPqYygfYVJL6_EgzVuwRk5txr9e3n1uml94fLyq_AXbwo9yAduf4dCHT" + "P8CWR1dnDR-Qnz_4PYlWVEuuHHONOw_blbfdMjhY-C_BYM2E3pRxbohBb3x__C" + "fueV7ddz2LYiH3wjz0QS_7kjPiNCsXcNyKQEOTkbHFi3mu0u13SQwNddhcynd_" + "GTgWN8A-6SN1r4hzpjFKFLbZnBt77ACSiYx-IHK4Mp-NaVEi5wQtSsjQtI--Xs" + "okxRDqYLwus1I1SihgbV_STTg5enufuw", "use": "sig", "x5c": [ "MIIDPjCCAiqgAwIBAgIQsRiM0jheFZhKk49YD0SK1TAJBgUrDgMCHQUAMC0xKz" @@ -121,11 +121,11 @@ def full_path(local_file): "kid": "MnC_VZcATfM5pOYiJHMba9goEKY", "kty": "RSA", "n": "vIqz-4-ER_vNWLON9yv8hIYV737JQ6rCl6XfzOC628seYUPf0TaGk91CFxefhz" - "h23V9Tkq-RtwN1Vs_z57hO82kkzL-cQHZX3bMJD-GEGOKXCEXURN7VMyZWMAuz" - "QoW9vFb1k3cR1RW_EW_P-C8bb2dCGXhBYqPfHyimvz2WarXhntPSbM5XyS5v5y" - "Cw5T_Vuwqqsio3V8wooWGMpp61y12NhN8bNVDQAkDPNu2DT9DXB1g0CeFINp_K" - "AS_qQ2Kq6TSvRHJqxRR68RezYtje9KAqwqx4jxlmVAQy0T3-T-IAbsk1wRtWDn" - "dhO6s1Os-dck5TzyZ_dNOhfXgelixLUQ", + "h23V9Tkq-RtwN1Vs_z57hO82kkzL-cQHZX3bMJD-GEGOKXCEXURN7VMyZWMAuz" + "QoW9vFb1k3cR1RW_EW_P-C8bb2dCGXhBYqPfHyimvz2WarXhntPSbM5XyS5v5y" + "Cw5T_Vuwqqsio3V8wooWGMpp61y12NhN8bNVDQAkDPNu2DT9DXB1g0CeFINp_K" + "AS_qQ2Kq6TSvRHJqxRR68RezYtje9KAqwqx4jxlmVAQy0T3-T-IAbsk1wRtWDn" + "dhO6s1Os-dck5TzyZ_dNOhfXgelixLUQ", "use": "sig", "x5c": [ "MIIC4jCCAcqgAwIBAgIQQNXrmzhLN4VGlUXDYCRT3zANBgkqhkiG9w0BAQsFADAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb" @@ -152,12 +152,12 @@ def full_path(local_file): { "e": "AQAB", "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b" - "-b112-36a304b66dad/v2.0/", + "-b112-36a304b66dad/v2.0/", "kid": "GvnPApfWMdLRi8PDmisFn7bprKg", "kty": "RSA", "n": "5ymq_xwmst1nstPr8YFOTyD1J5N4idYmrph7AyAv95RbWXfDRqy8CMRG7sJq" - "-UWOKVOA4MVrd_NdV-ejj1DE5MPSiG" - "-mZK_5iqRCDFvPYqOyRj539xaTlARNY4jeXZ0N6irZYKqSfYACjkkKxbLKcijSu1pJ48thXOTED0oNa6U", + "-UWOKVOA4MVrd_NdV-ejj1DE5MPSiG" + "-mZK_5iqRCDFvPYqOyRj539xaTlARNY4jeXZ0N6irZYKqSfYACjkkKxbLKcijSu1pJ48thXOTED0oNa6U", "use": "sig", "x5c": [ "MIICWzCCAcSgAwIBAgIJAKVzMH2FfC12MA0GCSqGSIb3DQEBBQUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVib" @@ -181,13 +181,12 @@ def full_path(local_file): { "e": "AQAB", "issuer": "https://login.microsoftonline.com/9188040d-6c67-4c5b" - "-b112-36a304b66dad/v2.0/", + "-b112-36a304b66dad/v2.0/", "kid": "dEtpjbEvbhfgwUI-bdK5xAU_9UQ", "kty": "RSA", - "n": - "x7HNcD9ZxTFRaAgZ7-gdYLkgQua3zvQseqBJIt8Uq3MimInMZoE9QGQeSML7qZPlowb5BUakdLI70ayM4vN36--0ht8-oCHhl8Yj" - "GFQkU-Iv2yahWHEP-1EK6eOEYu6INQP9Lk0HMk3QViLwshwb" - "-KXVD02jdmX2HNdYJdPyc0c", + "n": "x7HNcD9ZxTFRaAgZ7-gdYLkgQua3zvQseqBJIt8Uq3MimInMZoE9QGQeSML7qZPlowb5BUakdLI70ayM4vN36--0ht8-oCHhl8Yj" + "GFQkU-Iv2yahWHEP-1EK6eOEYu6INQP9Lk0HMk3QViLwshwb" + "-KXVD02jdmX2HNdYJdPyc0c", "use": "sig", "x5c": [ "MIICWzCCAcSgAwIBAgIJAL3MzqqEFMYjMA0GCSqGSIb3DQEBBQUAMCkxJzAlBgNVBAMTHkxpdmUgSUQgU1RTIFNpZ25pbmcgUHVib" @@ -279,7 +278,7 @@ def test_ignore_unknown_types(): kb = KeyBundle( { "kid": "q-H9y8iuh3BIKZBbK6S0mH_isBlJsk" - "-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw", + "-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw", "use": "sig", "alg": "EdDSA", "kty": "OKP", @@ -619,16 +618,14 @@ def test_loads_1(): "kty": "RSA", "use": "sig", "e": "AQAB", - "n": - "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", + "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", "kid": "1", }, { "kty": "RSA", "use": "enc", "e": "AQAB", - "n": - "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", + "n": "wf-wiusGhA-gleZYQAOPQlNUIucPiqXdPVyieDqQbXXOPBe3nuggtVzeq7pVFH1dZz4dY2Q2LA5DaegvP8kRvoSB_87ds3dy3Rfym_GUSc5B0l1TgEobcyaep8jguRoHto6GWHfCfKqoUYZq4N8vh4LLMQwLR6zi6Jtu82nB5k8", "kid": "2", }, ] @@ -661,8 +658,7 @@ def test_dump_jwk(): JWKS_DICT = { "keys": [ { - "n": - u"zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFYInq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVbCGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znanLwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MXsGxBHf3AKT5w", + "n": u"zkpUgEgXICI54blf6iWiD2RbMDCOO1jV0VSff1MFFnujM4othfMsad7H1kRo50YM5S_X9TdvrpdOfpz5aBaKFhT6Ziv0nhtcekq1eRl8mjBlvGKCE5XGk-0LFSDwvqgkJoFYInq7bu0a4JEzKs5AyJY75YlGh879k1Uu2Sv3ZZOunfV1O1Orta-NvS-aG_jN5cstVbCGWE20H0vFVrJKNx0Zf-u-aA-syM4uX7wdWgQ-owoEMHge0GmGgzso2lwOYf_4znanLwEuO3p5aabEaFoKNR4K6GjQcjBcYmDEE4CtfRU9AEmhcD1kleiTB9TjPWkgDmT9MXsGxBHf3AKT5w", "e": u"AQAB", "kty": "RSA", "kid": "5-VBFv40P8D4I-7SFz7hMugTbPs", diff --git a/tests/test_04_key_issuer.py b/tests/test_04_key_issuer.py index ae4778d1..7a4ca372 100755 --- a/tests/test_04_key_issuer.py +++ b/tests/test_04_key_issuer.py @@ -751,6 +751,7 @@ def test_dump_json(): res = issuer.dump() assert json.dumps(res) + def test_contains(): issuer = KeyIssuer() issuer.add_kb(KeyBundle(JWK1["keys"])) diff --git a/tests/test_04_key_jar.py b/tests/test_04_key_jar.py index b9b17ebf..1a472b6a 100755 --- a/tests/test_04_key_jar.py +++ b/tests/test_04_key_jar.py @@ -470,7 +470,7 @@ def test_provider(self): _msg = "{} is not available at this moment!".format(_url) warnings.warn(_msg) else: - assert iss_kes[0].keys() + assert iss_keys[0].keys() def test_import_jwks():