summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2020-12-19 15:40:27 -0800
committerGitHub <noreply@github.com>2020-12-19 18:40:27 -0500
commit9acab9cad0ee536f41aca39f5d4cf09680bf1ffb (patch)
tree2485eb65ab49df32a42fe91bfb63e4ce5fb46aae
parent8bffbb242b5c6c49350cb1b80c4e62979341cec3 (diff)
downloadpyjwt-9acab9cad0ee536f41aca39f5d4cf09680bf1ffb.tar.gz
Add utility functions to assist test skipping (#563)
-rw-r--r--tests/keys/__init__.py5
-rw-r--r--tests/test_algorithms.py126
-rw-r--r--tests/test_api_jwk.py28
-rw-r--r--tests/test_api_jws.py44
-rw-r--r--tests/test_api_jwt.py11
-rw-r--r--tests/test_jwks_client.py6
-rw-r--r--tests/utils.py19
7 files changed, 76 insertions, 163 deletions
diff --git a/tests/keys/__init__.py b/tests/keys/__init__.py
index 050f132..3c11e98 100644
--- a/tests/keys/__init__.py
+++ b/tests/keys/__init__.py
@@ -1,6 +1,7 @@
import json
import os
+from jwt.algorithms import has_crypto
from jwt.utils import base64url_decode
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -22,10 +23,8 @@ try:
from cryptography.hazmat.primitives.asymmetric import ec
from jwt.algorithms import RSAAlgorithm
-
- has_crypto = True
except ImportError:
- has_crypto = False
+ pass
if has_crypto:
diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py
index d88687f..02c3241 100644
--- a/tests/test_algorithms.py
+++ b/tests/test_algorithms.py
@@ -8,7 +8,7 @@ from jwt.exceptions import InvalidKeyError
from jwt.utils import base64url_decode
from .keys import load_hmac_key
-from .utils import key_path
+from .utils import crypto_required, key_path
try:
from jwt.algorithms import (
@@ -19,10 +19,8 @@ try:
)
from .keys import load_ec_pub_key_p_521, load_rsa_pub_key
-
- has_crypto = True
except ImportError:
- has_crypto = False
+ pass
class TestAlgorithms:
@@ -133,45 +131,35 @@ class TestAlgorithms:
with pytest.raises(InvalidKeyError):
algo.from_jwk(keyfile.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_should_parse_pem_public_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
with open(key_path("testkey2_rsa.pub.pem")) as pem_key:
algo.prepare_key(pem_key.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_should_accept_pem_private_key_bytes(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
with open(key_path("testkey_rsa.priv"), "rb") as pem_key:
algo.prepare_key(pem_key.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_should_accept_unicode_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
with open(key_path("testkey_rsa.priv")) as rsa_key:
algo.prepare_key(rsa_key.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_should_reject_non_string_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
with pytest.raises(TypeError):
algo.prepare_key(None)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_verify_should_return_false_if_signature_invalid(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -194,9 +182,7 @@ class TestAlgorithms:
result = algo.verify(message, pub_key, sig)
assert not result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_jwk_public_and_private_keys_should_parse_and_verify(self):
tests = {
"P-256": ECAlgorithm.SHA256,
@@ -215,9 +201,7 @@ class TestAlgorithms:
signature = algo.sign(b"Hello World!", priv_key)
assert algo.verify(b"Hello World!", pub_key, signature)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_jwk_fails_on_invalid_json(self):
algo = ECAlgorithm(ECAlgorithm.SHA512)
@@ -278,9 +262,7 @@ class TestAlgorithms:
'"d": "dGVzdA=="}}'.format(curve, point["x"], point["y"])
)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_jwk_public_and_private_keys_should_parse_and_verify(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -293,9 +275,7 @@ class TestAlgorithms:
signature = algo.sign(b"Hello World!", priv_key)
assert algo.verify(b"Hello World!", pub_key, signature)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_private_key_to_jwk_works_with_from_jwk(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -309,9 +289,7 @@ class TestAlgorithms:
== orig_key.private_numbers().public_numbers
)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_public_key_to_jwk_works_with_from_jwk(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -321,9 +299,7 @@ class TestAlgorithms:
parsed_key = algo.from_jwk(algo.to_jwk(orig_key))
assert parsed_key.public_numbers() == orig_key.public_numbers()
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_jwk_private_key_with_other_primes_is_invalid(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -334,9 +310,7 @@ class TestAlgorithms:
algo.from_jwk(json.dumps(keydata))
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_jwk_private_key_with_missing_values_is_invalid(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -347,9 +321,7 @@ class TestAlgorithms:
algo.from_jwk(json.dumps(keydata))
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_jwk_private_key_can_recover_prime_factors(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -371,9 +343,7 @@ class TestAlgorithms:
assert control_key.dmq1 == parsed_key.dmq1
assert control_key.iqmp == parsed_key.iqmp
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_jwk_private_key_with_missing_required_values_is_invalid(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -384,9 +354,7 @@ class TestAlgorithms:
algo.from_jwk(json.dumps(keydata))
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_jwk_raises_exception_if_not_a_valid_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -398,9 +366,7 @@ class TestAlgorithms:
with pytest.raises(InvalidKeyError):
algo.from_jwk('{"kty": "RSA"}')
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_to_jwk_returns_correct_values_for_public_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -424,9 +390,7 @@ class TestAlgorithms:
}
assert json.loads(key) == expected
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_to_jwk_returns_correct_values_for_private_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -483,18 +447,14 @@ class TestAlgorithms:
}
assert json.loads(key) == expected
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_to_jwk_raises_exception_on_invalid_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
with pytest.raises(InvalidKeyError):
algo.to_jwk({"not": "a valid key"})
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_from_jwk_raises_exception_on_invalid_key(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -502,36 +462,28 @@ class TestAlgorithms:
with pytest.raises(InvalidKeyError):
algo.from_jwk(keyfile.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_should_reject_non_string_key(self):
algo = ECAlgorithm(ECAlgorithm.SHA256)
with pytest.raises(TypeError):
algo.prepare_key(None)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_should_accept_pem_private_key_bytes(self):
algo = ECAlgorithm(ECAlgorithm.SHA256)
with open(key_path("testkey_ec.priv"), "rb") as ec_key:
algo.prepare_key(ec_key.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_should_accept_ssh_public_key_bytes(self):
algo = ECAlgorithm(ECAlgorithm.SHA256)
with open(key_path("testkey_ec_ssh.pub")) as ec_key:
algo.prepare_key(ec_key.read())
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_verify_should_return_false_if_signature_invalid(self):
algo = ECAlgorithm(ECAlgorithm.SHA256)
@@ -552,9 +504,7 @@ class TestAlgorithms:
result = algo.verify(message, pub_key, sig)
assert not result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_verify_should_return_false_if_signature_wrong_length(self):
algo = ECAlgorithm(ECAlgorithm.SHA256)
@@ -568,9 +518,7 @@ class TestAlgorithms:
result = algo.verify(message, pub_key, sig)
assert not result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_pss_sign_then_verify_should_return_true(self):
algo = RSAPSSAlgorithm(RSAPSSAlgorithm.SHA256)
@@ -586,9 +534,7 @@ class TestAlgorithms:
result = algo.verify(message, pub_key, sig)
assert result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_pss_verify_should_return_false_if_signature_invalid(self):
algo = RSAPSSAlgorithm(RSAPSSAlgorithm.SHA256)
@@ -643,9 +589,7 @@ class TestAlgorithmsRFC7520:
result = algo.verify(signing_input, key, signature)
assert result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsa_verify_should_return_true_for_test_vector(self):
"""
This test verifies that RSA PKCS v1.5 verification works with a known
@@ -676,9 +620,7 @@ class TestAlgorithmsRFC7520:
result = algo.verify(signing_input, key, signature)
assert result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_rsapss_verify_should_return_true_for_test_vector(self):
"""
This test verifies that RSA-PSS verification works with a known good
@@ -709,9 +651,7 @@ class TestAlgorithmsRFC7520:
result = algo.verify(signing_input, key, signature)
assert result
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_ec_verify_should_return_true_for_test_vector(self):
"""
This test verifies that ECDSA verification works with a known good
@@ -740,9 +680,7 @@ class TestAlgorithmsRFC7520:
assert result
-@pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography>=2.6 library"
-)
+@crypto_required
class TestEd25519Algorithms:
hello_world_sig = b"Qxa47mk/azzUgmY2StAOguAd4P7YBLpyCfU3JdbaiWnXM4o4WibXwmIHvNYgN3frtE2fcyd8OYEaOiD/KiwkCg=="
hello_world = b"Hello World!"
diff --git a/tests/test_api_jwk.py b/tests/test_api_jwk.py
index ba4dbf2..6a1931f 100644
--- a/tests/test_api_jwk.py
+++ b/tests/test_api_jwk.py
@@ -1,24 +1,17 @@
import json
-import pytest
-
from jwt.api_jwk import PyJWK, PyJWKSet
-from .utils import key_path
+from .utils import crypto_required, key_path
try:
from jwt.algorithms import RSAAlgorithm
-
- has_crypto = True
except ImportError:
- has_crypto = False
+ pass
class TestPyJWK:
- @pytest.mark.skipif(
- not has_crypto,
- reason="Scenario requires cryptography to not be installed",
- )
+ @crypto_required
def test_should_load_key_from_jwk_data_dict(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -39,10 +32,7 @@ class TestPyJWK:
assert jwk.key_id == "keyid-abc123"
assert jwk.public_key_use == "sig"
- @pytest.mark.skipif(
- not has_crypto,
- reason="Scenario requires cryptography to not be installed",
- )
+ @crypto_required
def test_should_load_key_from_jwk_data_json_string(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -65,10 +55,7 @@ class TestPyJWK:
class TestPyJWKSet:
- @pytest.mark.skipif(
- not has_crypto,
- reason="Scenario requires cryptography to not be installed",
- )
+ @crypto_required
def test_should_load_keys_from_jwk_data_dict(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
@@ -90,10 +77,7 @@ class TestPyJWKSet:
assert jwk.key_id == "keyid-abc123"
assert jwk.public_key_use == "sig"
- @pytest.mark.skipif(
- not has_crypto,
- reason="Scenario requires cryptography to not be installed",
- )
+ @crypto_required
def test_should_load_keys_from_jwk_data_json_string(self):
algo = RSAAlgorithm(RSAAlgorithm.SHA256)
diff --git a/tests/test_api_jws.py b/tests/test_api_jws.py
index 2e8dd90..d03f92c 100644
--- a/tests/test_api_jws.py
+++ b/tests/test_api_jws.py
@@ -3,7 +3,7 @@ from decimal import Decimal
import pytest
-from jwt.algorithms import Algorithm
+from jwt.algorithms import Algorithm, has_crypto
from jwt.api_jws import PyJWS
from jwt.exceptions import (
DecodeError,
@@ -13,7 +13,7 @@ from jwt.exceptions import (
)
from jwt.utils import base64url_decode
-from .utils import key_path
+from .utils import crypto_required, key_path, no_crypto_required
try:
from cryptography.hazmat.primitives.serialization import (
@@ -21,10 +21,8 @@ try:
load_pem_public_key,
load_ssh_public_key,
)
-
- has_crypto = True
except ImportError:
- has_crypto = False
+ pass
@pytest.fixture
@@ -240,9 +238,7 @@ class TestJWS:
# Used to test for regressions that could affect both
# encoding / decoding operations equally (causing tests
# to still pass).
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_decodes_valid_es384_jws(self, jws):
example_payload = {"hello": "world"}
with open(key_path("testkey_ec.pub")) as fp:
@@ -263,9 +259,7 @@ class TestJWS:
# Used to test for regressions that could affect both
# encoding / decoding operations equally (causing tests
# to still pass).
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_decodes_valid_rs384_jws(self, jws):
example_payload = {"hello": "world"}
with open(key_path("testkey_rsa.pub")) as fp:
@@ -386,9 +380,7 @@ class TestJWS:
with pytest.raises(NotImplementedError):
jws.encode(payload, "secret", algorithm="HS1024")
- @pytest.mark.skipif(
- has_crypto, reason="Scenario requires cryptography to not be installed"
- )
+ @no_crypto_required
def test_missing_crypto_library_better_error_messages(self, jws, payload):
with pytest.raises(NotImplementedError) as excinfo:
jws.encode(payload, "secret", algorithm="RS256")
@@ -509,9 +501,7 @@ class TestJWS:
assert "Key ID header parameter must be a string" == str(exc.value)
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_encode_decode_with_rsa_sha256(self, jws, payload):
# PEM-formatted RSA key
with open(key_path("testkey_rsa.priv"), "rb") as rsa_priv_file:
@@ -534,9 +524,7 @@ class TestJWS:
pub_rsakey = rsa_pub_file.read()
jws.decode(jws_message, pub_rsakey, algorithms=["RS256"])
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_encode_decode_with_rsa_sha384(self, jws, payload):
# PEM-formatted RSA key
with open(key_path("testkey_rsa.priv"), "rb") as rsa_priv_file:
@@ -558,9 +546,7 @@ class TestJWS:
pub_rsakey = rsa_pub_file.read()
jws.decode(jws_message, pub_rsakey, algorithms=["RS384"])
- @pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
- )
+ @crypto_required
def test_encode_decode_with_rsa_sha512(self, jws, payload):
# PEM-formatted RSA key
with open(key_path("testkey_rsa.priv"), "rb") as rsa_priv_file:
@@ -602,9 +588,7 @@ class TestJWS:
assert "PS384" not in jws_algorithms
assert "PS512" not in jws_algorithms
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_encode_decode_with_ecdsa_sha256(self, jws, payload):
# PEM-formatted EC key
with open(key_path("testkey_ec.priv"), "rb") as ec_priv_file:
@@ -626,9 +610,7 @@ class TestJWS:
pub_eckey = ec_pub_file.read()
jws.decode(jws_message, pub_eckey, algorithms=["ES256"])
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_encode_decode_with_ecdsa_sha384(self, jws, payload):
# PEM-formatted EC key
@@ -651,9 +633,7 @@ class TestJWS:
pub_eckey = ec_pub_file.read()
jws.decode(jws_message, pub_eckey, algorithms=["ES384"])
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_encode_decode_with_ecdsa_sha512(self, jws, payload):
# PEM-formatted EC key
with open(key_path("testkey_ec.priv"), "rb") as ec_priv_file:
diff --git a/tests/test_api_jwt.py b/tests/test_api_jwt.py
index dda896f..e575668 100644
--- a/tests/test_api_jwt.py
+++ b/tests/test_api_jwt.py
@@ -17,8 +17,7 @@ from jwt.exceptions import (
MissingRequiredClaimError,
)
-from .test_api_jws import has_crypto
-from .utils import key_path, utc_timestamp
+from .utils import crypto_required, key_path, utc_timestamp
@pytest.fixture
@@ -242,9 +241,7 @@ class TestJWT:
# Used to test for regressions that could affect both
# encoding / decoding operations equally (causing tests
# to still pass).
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_decodes_valid_es256_jwt(self, jwt):
example_payload = {"hello": "world"}
with open(key_path("testkey_ec.pub")) as fp:
@@ -264,9 +261,7 @@ class TestJWT:
# Used to test for regressions that could affect both
# encoding / decoding operations equally (causing tests
# to still pass).
- @pytest.mark.skipif(
- not has_crypto, reason="Can't run without cryptography library"
- )
+ @crypto_required
def test_decodes_valid_rs384_jwt(self, jwt):
example_payload = {"hello": "world"}
with open(key_path("testkey_rsa.pub")) as fp:
diff --git a/tests/test_jwks_client.py b/tests/test_jwks_client.py
index d263fbb..d607863 100644
--- a/tests/test_jwks_client.py
+++ b/tests/test_jwks_client.py
@@ -9,7 +9,7 @@ from jwt import PyJWKClient
from jwt.api_jwk import PyJWK
from jwt.exceptions import PyJWKClientError
-from .test_algorithms import has_crypto
+from .utils import crypto_required
RESPONSE_DATA = {
"keys": [
@@ -40,9 +40,7 @@ def mocked_response(data):
yield
-@pytest.mark.skipif(
- not has_crypto, reason="Not supported without cryptography library"
-)
+@crypto_required
class TestPyJWKClient:
def test_get_jwk_set(self):
url = "https://dev-87evx9ru.auth0.com/.well-known/jwks.json"
diff --git a/tests/utils.py b/tests/utils.py
index 4b988e6..6847aba 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -2,6 +2,10 @@ import os
from calendar import timegm
from datetime import datetime
+import pytest
+
+from jwt.algorithms import has_crypto
+
def utc_timestamp():
return timegm(datetime.utcnow().utctimetuple())
@@ -11,3 +15,18 @@ def key_path(key_name):
return os.path.join(
os.path.dirname(os.path.realpath(__file__)), "keys", key_name
)
+
+
+def no_crypto_required(class_or_func):
+ decorator = pytest.mark.skipif(
+ has_crypto,
+ reason="Requires cryptography library not installed",
+ )
+ return decorator(class_or_func)
+
+
+def crypto_required(class_or_func):
+ decorator = pytest.mark.skipif(
+ not has_crypto, reason="Requires cryptography library installed"
+ )
+ return decorator(class_or_func)