diff options
author | Jon Dufresne <jon.dufresne@gmail.com> | 2020-12-19 15:40:27 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-19 18:40:27 -0500 |
commit | 9acab9cad0ee536f41aca39f5d4cf09680bf1ffb (patch) | |
tree | 2485eb65ab49df32a42fe91bfb63e4ce5fb46aae | |
parent | 8bffbb242b5c6c49350cb1b80c4e62979341cec3 (diff) | |
download | pyjwt-9acab9cad0ee536f41aca39f5d4cf09680bf1ffb.tar.gz |
Add utility functions to assist test skipping (#563)
-rw-r--r-- | tests/keys/__init__.py | 5 | ||||
-rw-r--r-- | tests/test_algorithms.py | 126 | ||||
-rw-r--r-- | tests/test_api_jwk.py | 28 | ||||
-rw-r--r-- | tests/test_api_jws.py | 44 | ||||
-rw-r--r-- | tests/test_api_jwt.py | 11 | ||||
-rw-r--r-- | tests/test_jwks_client.py | 6 | ||||
-rw-r--r-- | tests/utils.py | 19 |
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) |