From 13dd7a26f02da2bff33decc29cfd3f5e857a04c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Fri, 5 Feb 2021 01:04:43 -0800 Subject: [PATCH 01/18] First prototype of from_jwk --- .../azure/keyvault/keys/crypto/_client.py | 37 +++++++++++++++---- .../azure/keyvault/keys/crypto/aio/_client.py | 37 +++++++++++++++---- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index c457f15f5bc2..9dd6ee6f9b1e 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -114,6 +114,7 @@ def __init__(self, key, credential, **kwargs): self._local_provider = NoLocalCryptography() self._initialized = False + self._local_only = kwargs.pop("local_only", False) super(CryptographyClient, self).__init__(vault_url=self._key_id.vault_url, credential=credential, **kwargs) @@ -126,6 +127,16 @@ def key_id(self): """ return self._key_id.source_id + @classmethod + def from_jkw(cls, key_id, jwk): + # type: (str, dict) -> CryptographyClient + """Creates a client that can only perform cryptographic operations locally. + + :param str key_id: the full identifier of an Azure Key Vault key with a version. + :param dict jwk: the key's cryptographic material, as a dictionary. + """ + return cls(KeyVaultKey(key_id, jwk), object, local_only=True) + @distributed_trace def _initialize(self, **kwargs): # type: (**Any) -> None @@ -133,7 +144,7 @@ def _initialize(self, **kwargs): return # try to get the key material, if we don't have it and aren't forbidden to do so - if not (self._key or self._keys_get_forbidden): + if not (self._key or self._keys_get_forbidden or self._local_only): try: key_bundle = self._client.get_key( self._key_id.vault_url, self._key_id.name, self._key_id.version, **kwargs @@ -180,11 +191,13 @@ def encrypt(self, algorithm, plaintext, **kwargs): _validate_arguments(operation=KeyOperation.encrypt, algorithm=algorithm, iv=iv, aad=aad) self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.encrypt, algorithm): + if self._local_provider.supports(KeyOperation.encrypt, algorithm) or self._local_only: raise_if_time_invalid(self._key) try: return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = self._client.encrypt( @@ -235,10 +248,12 @@ def decrypt(self, algorithm, ciphertext, **kwargs): _validate_arguments(operation=KeyOperation.decrypt, algorithm=algorithm, iv=iv, tag=tag, aad=aad) self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.decrypt, algorithm): + if self._local_provider.supports(KeyOperation.decrypt, algorithm) or self._local_only: try: return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = self._client.decrypt( @@ -271,11 +286,13 @@ def wrap_key(self, algorithm, key, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.wrap_key, algorithm): + if self._local_provider.supports(KeyOperation.wrap_key, algorithm) or self._local_only: raise_if_time_invalid(self._key) try: return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = self._client.wrap_key( @@ -306,10 +323,12 @@ def unwrap_key(self, algorithm, encrypted_key, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.unwrap_key, algorithm): + if self._local_provider.supports(KeyOperation.unwrap_key, algorithm) or self._local_only: try: return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = self._client.unwrap_key( @@ -339,11 +358,13 @@ def sign(self, algorithm, digest, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.sign, algorithm): + if self._local_provider.supports(KeyOperation.sign, algorithm) or self._local_only: raise_if_time_invalid(self._key) try: return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = self._client.sign( @@ -376,10 +397,12 @@ def verify(self, algorithm, digest, signature, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.verify, algorithm): + if self._local_provider.supports(KeyOperation.verify, algorithm) or self._local_only: try: return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = self._client.verify( diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 580e3884f6ba..672acc52c0b4 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -68,6 +68,7 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden self._local_provider = NoLocalCryptography() self._initialized = False + self._local_only = kwargs.pop("local_only", False) super().__init__(vault_url=self._key_id.vault_url, credential=credential, **kwargs) @@ -79,6 +80,16 @@ def key_id(self) -> str: """ return self._key_id.source_id + @classmethod + def from_jkw(cls, key_id, jwk): + # type: (str, dict) -> CryptographyClient + """Creates a client that can only perform cryptographic operations locally. + + :param str key_id: the full identifier of an Azure Key Vault key with a version. + :param dict jwk: the key's cryptographic material, as a dictionary. + """ + return cls(KeyVaultKey(key_id, jwk), object, local_only=True) + @distributed_trace_async async def _initialize(self, **kwargs): # type: (**Any) -> None @@ -86,7 +97,7 @@ async def _initialize(self, **kwargs): return # try to get the key material, if we don't have it and aren't forbidden to do so - if not (self._key or self._keys_get_forbidden): + if not (self._key or self._keys_get_forbidden or self._local_only): try: key_bundle = await self._client.get_key( self._key_id.vault_url, self._key_id.name, self._key_id.version, **kwargs @@ -132,11 +143,13 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw _validate_arguments(operation=KeyOperation.encrypt, algorithm=algorithm, iv=iv, aad=aad) await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.encrypt, algorithm): + if self._local_provider.supports(KeyOperation.encrypt, algorithm) or self._local_only: raise_if_time_invalid(self._key) try: return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = await self._client.encrypt( @@ -186,10 +199,12 @@ async def decrypt(self, algorithm: "EncryptionAlgorithm", ciphertext: bytes, **k _validate_arguments(operation=KeyOperation.decrypt, algorithm=algorithm, iv=iv, tag=tag, aad=aad) await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.decrypt, algorithm): + if self._local_provider.supports(KeyOperation.decrypt, algorithm) or self._local_only: try: return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = await self._client.decrypt( @@ -221,11 +236,13 @@ async def wrap_key(self, algorithm: "KeyWrapAlgorithm", key: bytes, **kwargs: "A :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.wrap_key, algorithm): + if self._local_provider.supports(KeyOperation.wrap_key, algorithm) or self._local_only: raise_if_time_invalid(self._key) try: return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = await self._client.wrap_key( @@ -255,10 +272,12 @@ async def unwrap_key(self, algorithm: "KeyWrapAlgorithm", encrypted_key: bytes, :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.unwrap_key, algorithm): + if self._local_provider.supports(KeyOperation.unwrap_key, algorithm) or self._local_only: try: return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = await self._client.unwrap_key( @@ -288,11 +307,13 @@ async def sign(self, algorithm: "SignatureAlgorithm", digest: bytes, **kwargs: " :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.sign, algorithm): + if self._local_provider.supports(KeyOperation.sign, algorithm) or self._local_only: raise_if_time_invalid(self._key) try: return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = await self._client.sign( @@ -326,10 +347,12 @@ async def verify( :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.verify, algorithm): + if self._local_provider.supports(KeyOperation.verify, algorithm) or self._local_only: try: return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except + if self._local_only: + raise _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) operation_result = await self._client.verify( From 41ef114adcbb50550e1a24fc398b83d2bd35af96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Wed, 24 Feb 2021 17:58:54 -0800 Subject: [PATCH 02/18] Add tests --- .../tests/test_crypto_client.py | 63 +++++++++++++++++- .../tests/test_crypto_client_async.py | 65 ++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index 2466cb244bda..3575164ed5e3 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -12,7 +12,7 @@ except ImportError: import mock -from azure.core.exceptions import HttpResponseError +from azure.core.exceptions import AzureError, HttpResponseError from azure.core.pipeline.policies import SansIOHTTPPolicy from azure.keyvault.keys import JsonWebKey, KeyClient, KeyCurveName, KeyType, KeyVaultKey from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm @@ -491,6 +491,67 @@ def test_calls_service_for_operations_unsupported_locally(): assert supports_nothing.wrap_key.call_count == 0 +def test_local_only_mode_no_service_calls(): + """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" + + mock_client = mock.Mock() + jwk = mock.Mock(spec=JsonWebKey) + client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + client._client = mock_client + + supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) + with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): + client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") + assert mock_client.decrypt.call_count == 0 + assert supports_nothing.decrypt.call_count == 1 + + client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + assert mock_client.encrypt.call_count == 0 + assert supports_nothing.encrypt.call_count == 1 + + client.sign(SignatureAlgorithm.rs256, b"...") + assert mock_client.sign.call_count == 0 + assert supports_nothing.sign.call_count == 1 + + client.verify(SignatureAlgorithm.rs256, b"...", b"...") + assert mock_client.verify.call_count == 0 + assert supports_nothing.verify.call_count == 1 + + client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + assert mock_client.unwrap_key.call_count == 0 + assert supports_nothing.unwrap_key.call_count == 1 + + client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + assert mock_client.wrap_key.call_count == 0 + assert supports_nothing.wrap_key.call_count == 1 + + +def test_local_only_mode_raise(): + """A local-only CryptographyClient should raise an exception if an operation can't be performed locally""" + + jwk = {"kty":"RSA", "key_ops":["decrypt", "verify", "unwrapKey"], "n":b"10011", "e":b"10001"} + client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + + # Algorithm not supported locally + with pytest.raises(NotImplementedError): + client.decrypt(EncryptionAlgorithm.a256_gcm, b"...") + # Operation not included in JWK permissions + with pytest.raises(AzureError): + client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + # Algorithm not supported locally + with pytest.raises(NotImplementedError): + client.verify(SignatureAlgorithm.es256, b"...", b"...") + # Algorithm not supported locally, and operation not included in JWK permissions + with pytest.raises(NotImplementedError): + client.sign(SignatureAlgorithm.rs256, b"...") + # Algorithm not supported locally + with pytest.raises(NotImplementedError): + client.unwrap_key(KeyWrapAlgorithm.aes_256, b"...") + # Operation not included in JWK permissions + with pytest.raises(AzureError): + client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + + def test_prefers_local_provider(): """The client should complete operations locally whenever possible""" diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index d39c9880e262..4fc68954f299 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -9,7 +9,7 @@ import os from unittest import mock -from azure.core.exceptions import HttpResponseError +from azure.core.exceptions import AzureError, HttpResponseError from azure.core.pipeline.policies import SansIOHTTPPolicy from azure.keyvault.keys import JsonWebKey, KeyCurveName, KeyVaultKey from azure.keyvault.keys.aio import KeyClient @@ -515,6 +515,69 @@ async def __call__(self, *args, **kwargs): assert supports_nothing.wrap_key.call_count == 0 +@pytest.mark.asyncio +async def test_local_only_mode_no_service_calls(): + """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" + + mock_client = mock.Mock() + jwk = mock.Mock(spec=JsonWebKey) + client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + client._client = mock_client + + supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) + with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): + await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") + assert mock_client.decrypt.call_count == 0 + assert supports_nothing.decrypt.call_count == 1 + + await client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + assert mock_client.encrypt.call_count == 0 + assert supports_nothing.encrypt.call_count == 1 + + await client.sign(SignatureAlgorithm.rs256, b"...") + assert mock_client.sign.call_count == 0 + assert supports_nothing.sign.call_count == 1 + + await client.verify(SignatureAlgorithm.rs256, b"...", b"...") + assert mock_client.verify.call_count == 0 + assert supports_nothing.verify.call_count == 1 + + await client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + assert mock_client.unwrap_key.call_count == 0 + assert supports_nothing.unwrap_key.call_count == 1 + + await client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + assert mock_client.wrap_key.call_count == 0 + assert supports_nothing.wrap_key.call_count == 1 + + +@pytest.mark.asyncio +async def test_local_only_mode_raise(): + """A local-only CryptographyClient should raise an exception if an operation can't be performed locally""" + + jwk = {"kty":"RSA", "key_ops":["decrypt", "verify", "unwrapKey"], "n":b"10011", "e":b"10001"} + client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + + # Algorithm not supported locally + with pytest.raises(NotImplementedError): + await client.decrypt(EncryptionAlgorithm.a256_gcm, b"...") + # Operation not included in JWK permissions + with pytest.raises(AzureError): + await client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + # Algorithm not supported locally + with pytest.raises(NotImplementedError): + await client.verify(SignatureAlgorithm.es256, b"...", b"...") + # Algorithm not supported locally, and operation not included in JWK permissions + with pytest.raises(NotImplementedError): + await client.sign(SignatureAlgorithm.rs256, b"...") + # Algorithm not supported locally + with pytest.raises(NotImplementedError): + await client.unwrap_key(KeyWrapAlgorithm.aes_256, b"...") + # Operation not included in JWK permissions + with pytest.raises(AzureError): + await client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + + @pytest.mark.asyncio async def test_prefers_local_provider(): """The client should complete operations locally whenever possible""" From fad4bc0b0df94b9906fb513d2003a0f854fdd12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Mon, 1 Mar 2021 18:51:35 -0800 Subject: [PATCH 03/18] Incorporate feedback --- .../azure/keyvault/keys/crypto/_client.py | 50 +++++++++++----- .../azure/keyvault/keys/crypto/aio/_client.py | 51 ++++++++++++----- .../tests/test_crypto_client.py | 57 ++++++++++++------- .../tests/test_crypto_client_async.py | 57 ++++++++++++------- 4 files changed, 147 insertions(+), 68 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 9dd6ee6f9b1e..a87cc1d4a561 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -98,6 +98,7 @@ class CryptographyClient(KeyVaultClientBase): def __init__(self, key, credential, **kwargs): # type: (Union[KeyVaultKey, str], TokenCredential, **Any) -> None + self._local_only = kwargs.pop("_local_only", False) if isinstance(key, KeyVaultKey): self._key = key @@ -109,12 +110,11 @@ def __init__(self, key, credential, **kwargs): else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") - if not self._key_id.version: + if not (self._key_id.version or self._local_only): raise ValueError("'key' must include a version") self._local_provider = NoLocalCryptography() self._initialized = False - self._local_only = kwargs.pop("local_only", False) super(CryptographyClient, self).__init__(vault_url=self._key_id.vault_url, credential=credential, **kwargs) @@ -128,14 +128,14 @@ def key_id(self): return self._key_id.source_id @classmethod - def from_jkw(cls, key_id, jwk): - # type: (str, dict) -> CryptographyClient + def from_jwk(cls, jwk): + # type: (dict) -> CryptographyClient """Creates a client that can only perform cryptographic operations locally. - :param str key_id: the full identifier of an Azure Key Vault key with a version. :param dict jwk: the key's cryptographic material, as a dictionary. """ - return cls(KeyVaultKey(key_id, jwk), object, local_only=True) + key_id = "https://key-vault.vault.azure.net/keys/local-key" + return cls(KeyVaultKey(key_id, jwk), object, _local_only=True) @distributed_trace def _initialize(self, **kwargs): @@ -144,7 +144,7 @@ def _initialize(self, **kwargs): return # try to get the key material, if we don't have it and aren't forbidden to do so - if not (self._key or self._keys_get_forbidden or self._local_only): + if not (self._key or self._keys_get_forbidden): try: key_bundle = self._client.get_key( self._key_id.vault_url, self._key_id.name, self._key_id.version, **kwargs @@ -191,7 +191,7 @@ def encrypt(self, algorithm, plaintext, **kwargs): _validate_arguments(operation=KeyOperation.encrypt, algorithm=algorithm, iv=iv, aad=aad) self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.encrypt, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.encrypt, algorithm): raise_if_time_invalid(self._key) try: return self._local_provider.encrypt(algorithm, plaintext) @@ -199,6 +199,10 @@ def encrypt(self, algorithm, plaintext, **kwargs): if self._local_only: raise _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "encrypt" operation with algorithm "{}"'.format(algorithm) + ) operation_result = self._client.encrypt( vault_base_url=self._key_id.vault_url, @@ -248,13 +252,17 @@ def decrypt(self, algorithm, ciphertext, **kwargs): _validate_arguments(operation=KeyOperation.decrypt, algorithm=algorithm, iv=iv, tag=tag, aad=aad) self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.decrypt, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.decrypt, algorithm): try: return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except if self._local_only: raise _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "decrypt" operation with algorithm "{}"'.format(algorithm) + ) operation_result = self._client.decrypt( vault_base_url=self._key_id.vault_url, @@ -286,7 +294,7 @@ def wrap_key(self, algorithm, key, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.wrap_key, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.wrap_key, algorithm): raise_if_time_invalid(self._key) try: return self._local_provider.wrap_key(algorithm, key) @@ -294,6 +302,10 @@ def wrap_key(self, algorithm, key, **kwargs): if self._local_only: raise _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "wrapKey" operation with algorithm "{}"'.format(algorithm) + ) operation_result = self._client.wrap_key( vault_base_url=self._key_id.vault_url, @@ -323,13 +335,17 @@ def unwrap_key(self, algorithm, encrypted_key, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.unwrap_key, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.unwrap_key, algorithm): try: return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except if self._local_only: raise _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "unwrapKey" operation with algorithm "{}"'.format(algorithm) + ) operation_result = self._client.unwrap_key( vault_base_url=self._key_id.vault_url, @@ -358,7 +374,7 @@ def sign(self, algorithm, digest, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.sign, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.sign, algorithm): raise_if_time_invalid(self._key) try: return self._local_provider.sign(algorithm, digest) @@ -366,6 +382,10 @@ def sign(self, algorithm, digest, **kwargs): if self._local_only: raise _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "sign" operation with algorithm "{}"'.format(algorithm) + ) operation_result = self._client.sign( vault_base_url=self._key_id.vault_url, @@ -397,13 +417,17 @@ def verify(self, algorithm, digest, signature, **kwargs): :dedent: 8 """ self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.verify, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.verify, algorithm): try: return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except if self._local_only: raise _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "verify" operation with algorithm "{}"'.format(algorithm) + ) operation_result = self._client.verify( vault_base_url=self._key_id.vault_url, diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 672acc52c0b4..0916ce6bbcb2 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -53,6 +53,8 @@ class CryptographyClient(AsyncKeyVaultClientBase): """ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCredential", **kwargs: "Any") -> None: + self._local_only = kwargs.pop("_local_only", False) + if isinstance(key, KeyVaultKey): self._key = key self._key_id = parse_key_vault_id(key.id) @@ -63,12 +65,11 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") - if not self._key_id.version: + if not (self._key_id.version or self._local_only): raise ValueError("'key' must include a version") self._local_provider = NoLocalCryptography() self._initialized = False - self._local_only = kwargs.pop("local_only", False) super().__init__(vault_url=self._key_id.vault_url, credential=credential, **kwargs) @@ -81,14 +82,14 @@ def key_id(self) -> str: return self._key_id.source_id @classmethod - def from_jkw(cls, key_id, jwk): - # type: (str, dict) -> CryptographyClient + def from_jwk(cls, jwk): + # type: (dict) -> CryptographyClient """Creates a client that can only perform cryptographic operations locally. - :param str key_id: the full identifier of an Azure Key Vault key with a version. :param dict jwk: the key's cryptographic material, as a dictionary. """ - return cls(KeyVaultKey(key_id, jwk), object, local_only=True) + key_id = "https://key-vault.vault.azure.net/keys/local-key" + return cls(KeyVaultKey(key_id, jwk), object, _local_only=True) @distributed_trace_async async def _initialize(self, **kwargs): @@ -97,7 +98,7 @@ async def _initialize(self, **kwargs): return # try to get the key material, if we don't have it and aren't forbidden to do so - if not (self._key or self._keys_get_forbidden or self._local_only): + if not (self._key or self._keys_get_forbidden): try: key_bundle = await self._client.get_key( self._key_id.vault_url, self._key_id.name, self._key_id.version, **kwargs @@ -143,7 +144,7 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw _validate_arguments(operation=KeyOperation.encrypt, algorithm=algorithm, iv=iv, aad=aad) await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.encrypt, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.encrypt, algorithm): raise_if_time_invalid(self._key) try: return self._local_provider.encrypt(algorithm, plaintext) @@ -151,6 +152,10 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw if self._local_only: raise _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "encrypt" operation with algorithm "{}"'.format(algorithm) + ) operation_result = await self._client.encrypt( vault_base_url=self._key_id.vault_url, @@ -199,13 +204,17 @@ async def decrypt(self, algorithm: "EncryptionAlgorithm", ciphertext: bytes, **k _validate_arguments(operation=KeyOperation.decrypt, algorithm=algorithm, iv=iv, tag=tag, aad=aad) await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.decrypt, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.decrypt, algorithm): try: return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except if self._local_only: raise _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "decrypt" operation with algorithm "{}"'.format(algorithm) + ) operation_result = await self._client.decrypt( vault_base_url=self._key_id.vault_url, @@ -236,7 +245,7 @@ async def wrap_key(self, algorithm: "KeyWrapAlgorithm", key: bytes, **kwargs: "A :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.wrap_key, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.wrap_key, algorithm): raise_if_time_invalid(self._key) try: return self._local_provider.wrap_key(algorithm, key) @@ -244,6 +253,10 @@ async def wrap_key(self, algorithm: "KeyWrapAlgorithm", key: bytes, **kwargs: "A if self._local_only: raise _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "wrapKey" operation with algorithm "{}"'.format(algorithm) + ) operation_result = await self._client.wrap_key( vault_base_url=self._key_id.vault_url, @@ -272,13 +285,17 @@ async def unwrap_key(self, algorithm: "KeyWrapAlgorithm", encrypted_key: bytes, :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.unwrap_key, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.unwrap_key, algorithm): try: return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except if self._local_only: raise _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "unwrapKey" operation with algorithm "{}"'.format(algorithm) + ) operation_result = await self._client.unwrap_key( vault_base_url=self._key_id.vault_url, @@ -307,7 +324,7 @@ async def sign(self, algorithm: "SignatureAlgorithm", digest: bytes, **kwargs: " :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.sign, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.sign, algorithm): raise_if_time_invalid(self._key) try: return self._local_provider.sign(algorithm, digest) @@ -315,6 +332,10 @@ async def sign(self, algorithm: "SignatureAlgorithm", digest: bytes, **kwargs: " if self._local_only: raise _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "sign" operation with algorithm "{}"'.format(algorithm) + ) operation_result = await self._client.sign( vault_base_url=self._key_id.vault_url, @@ -347,13 +368,17 @@ async def verify( :dedent: 8 """ await self._initialize(**kwargs) - if self._local_provider.supports(KeyOperation.verify, algorithm) or self._local_only: + if self._local_provider.supports(KeyOperation.verify, algorithm): try: return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except if self._local_only: raise _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) + elif self._local_only: + raise NotImplementedError( + 'This key does not support the "verify" operation with algorithm "{}"'.format(algorithm) + ) operation_result = await self._client.verify( vault_base_url=self._key_id.vault_url, diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index 3575164ed5e3..d9978177fb0d 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -14,7 +14,7 @@ from azure.core.exceptions import AzureError, HttpResponseError from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.keyvault.keys import JsonWebKey, KeyClient, KeyCurveName, KeyType, KeyVaultKey +from azure.keyvault.keys import JsonWebKey, KeyClient, KeyCurveName, KeyOperation, KeyVaultKey from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm from azure.keyvault.keys.crypto._key_validity import _UTC from azure.keyvault.keys._shared import HttpChallengeCache @@ -496,60 +496,75 @@ def test_local_only_mode_no_service_calls(): mock_client = mock.Mock() jwk = mock.Mock(spec=JsonWebKey) - client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): - client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 - assert supports_nothing.decrypt.call_count == 1 - client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.encrypt.call_count == 0 - assert supports_nothing.encrypt.call_count == 1 - client.sign(SignatureAlgorithm.rs256, b"...") + with pytest.raises(NotImplementedError): + client.sign(SignatureAlgorithm.rs256, b"...") assert mock_client.sign.call_count == 0 - assert supports_nothing.sign.call_count == 1 - client.verify(SignatureAlgorithm.rs256, b"...", b"...") + with pytest.raises(NotImplementedError): + client.verify(SignatureAlgorithm.rs256, b"...", b"...") assert mock_client.verify.call_count == 0 - assert supports_nothing.verify.call_count == 1 - client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.unwrap_key.call_count == 0 - assert supports_nothing.unwrap_key.call_count == 1 - client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.wrap_key.call_count == 0 - assert supports_nothing.wrap_key.call_count == 1 def test_local_only_mode_raise(): """A local-only CryptographyClient should raise an exception if an operation can't be performed locally""" jwk = {"kty":"RSA", "key_ops":["decrypt", "verify", "unwrapKey"], "n":b"10011", "e":b"10001"} - client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + client = CryptographyClient.from_jwk(jwk=jwk) # Algorithm not supported locally - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: client.decrypt(EncryptionAlgorithm.a256_gcm, b"...") + assert EncryptionAlgorithm.a256_gcm in str(ex.value) + assert KeyOperation.decrypt in str(ex.value) + # Operation not included in JWK permissions - with pytest.raises(AzureError): + with pytest.raises(AzureError) as ex: client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + assert KeyOperation.encrypt in str(ex.value) + # Algorithm not supported locally - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: client.verify(SignatureAlgorithm.es256, b"...", b"...") + assert SignatureAlgorithm.es256 in str(ex.value) + assert KeyOperation.verify in str(ex.value) + # Algorithm not supported locally, and operation not included in JWK permissions - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: client.sign(SignatureAlgorithm.rs256, b"...") + assert SignatureAlgorithm.rs256 in str(ex.value) + assert KeyOperation.sign in str(ex.value) + # Algorithm not supported locally - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: client.unwrap_key(KeyWrapAlgorithm.aes_256, b"...") + assert KeyWrapAlgorithm.aes_256 in str(ex.value) + assert KeyOperation.unwrap_key in str(ex.value) + # Operation not included in JWK permissions - with pytest.raises(AzureError): + with pytest.raises(AzureError) as ex: client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + assert KeyOperation.wrap_key in str(ex.value) def test_prefers_local_provider(): diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index 4fc68954f299..5dcb89f12135 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -11,7 +11,7 @@ from azure.core.exceptions import AzureError, HttpResponseError from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.keyvault.keys import JsonWebKey, KeyCurveName, KeyVaultKey +from azure.keyvault.keys import JsonWebKey, KeyCurveName, KeyOperation, KeyVaultKey from azure.keyvault.keys.aio import KeyClient from azure.keyvault.keys.crypto._key_validity import _UTC from azure.keyvault.keys.crypto.aio import CryptographyClient, EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm @@ -521,34 +521,34 @@ async def test_local_only_mode_no_service_calls(): mock_client = mock.Mock() jwk = mock.Mock(spec=JsonWebKey) - client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): - await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 - assert supports_nothing.decrypt.call_count == 1 - await client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + await client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.encrypt.call_count == 0 - assert supports_nothing.encrypt.call_count == 1 - await client.sign(SignatureAlgorithm.rs256, b"...") + with pytest.raises(NotImplementedError): + await client.sign(SignatureAlgorithm.rs256, b"...") assert mock_client.sign.call_count == 0 - assert supports_nothing.sign.call_count == 1 - await client.verify(SignatureAlgorithm.rs256, b"...", b"...") + with pytest.raises(NotImplementedError): + await client.verify(SignatureAlgorithm.rs256, b"...", b"...") assert mock_client.verify.call_count == 0 - assert supports_nothing.verify.call_count == 1 - await client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + await client.unwrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.unwrap_key.call_count == 0 - assert supports_nothing.unwrap_key.call_count == 1 - await client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + await client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") assert mock_client.wrap_key.call_count == 0 - assert supports_nothing.wrap_key.call_count == 1 @pytest.mark.asyncio @@ -556,26 +556,41 @@ async def test_local_only_mode_raise(): """A local-only CryptographyClient should raise an exception if an operation can't be performed locally""" jwk = {"kty":"RSA", "key_ops":["decrypt", "verify", "unwrapKey"], "n":b"10011", "e":b"10001"} - client = CryptographyClient.from_jkw(key_id="https://localhost/fake/key/version", jwk=jwk) + client = CryptographyClient.from_jwk(jwk=jwk) # Algorithm not supported locally - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: await client.decrypt(EncryptionAlgorithm.a256_gcm, b"...") + assert EncryptionAlgorithm.a256_gcm in str(ex.value) + assert KeyOperation.decrypt in str(ex.value) + # Operation not included in JWK permissions - with pytest.raises(AzureError): + with pytest.raises(AzureError) as ex: await client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + assert KeyOperation.encrypt in str(ex.value) + # Algorithm not supported locally - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: await client.verify(SignatureAlgorithm.es256, b"...", b"...") + assert SignatureAlgorithm.es256 in str(ex.value) + assert KeyOperation.verify in str(ex.value) + # Algorithm not supported locally, and operation not included in JWK permissions - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: await client.sign(SignatureAlgorithm.rs256, b"...") + assert SignatureAlgorithm.rs256 in str(ex.value) + assert KeyOperation.sign in str(ex.value) + # Algorithm not supported locally - with pytest.raises(NotImplementedError): + with pytest.raises(NotImplementedError) as ex: await client.unwrap_key(KeyWrapAlgorithm.aes_256, b"...") + assert KeyWrapAlgorithm.aes_256 in str(ex.value) + assert KeyOperation.unwrap_key in str(ex.value) + # Operation not included in JWK permissions - with pytest.raises(AzureError): + with pytest.raises(AzureError) as ex: await client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + assert KeyOperation.wrap_key in str(ex.value) @pytest.mark.asyncio From 9ecdf218ad5c62b8dbfeada9f7baa6626076b091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Thu, 4 Mar 2021 10:08:04 -0800 Subject: [PATCH 04/18] Log before raising --- .../azure/keyvault/keys/crypto/_client.py | 12 ++++++------ .../azure/keyvault/keys/crypto/aio/_client.py | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index a87cc1d4a561..29e6762c10e2 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -196,9 +196,9 @@ def encrypt(self, algorithm, plaintext, **kwargs): try: return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "encrypt" operation with algorithm "{}"'.format(algorithm) @@ -256,9 +256,9 @@ def decrypt(self, algorithm, ciphertext, **kwargs): try: return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "decrypt" operation with algorithm "{}"'.format(algorithm) @@ -299,9 +299,9 @@ def wrap_key(self, algorithm, key, **kwargs): try: return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "wrapKey" operation with algorithm "{}"'.format(algorithm) @@ -339,9 +339,9 @@ def unwrap_key(self, algorithm, encrypted_key, **kwargs): try: return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "unwrapKey" operation with algorithm "{}"'.format(algorithm) @@ -379,9 +379,9 @@ def sign(self, algorithm, digest, **kwargs): try: return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "sign" operation with algorithm "{}"'.format(algorithm) @@ -421,9 +421,9 @@ def verify(self, algorithm, digest, signature, **kwargs): try: return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "verify" operation with algorithm "{}"'.format(algorithm) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 0916ce6bbcb2..2a639c17bd72 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -149,9 +149,9 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw try: return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "encrypt" operation with algorithm "{}"'.format(algorithm) @@ -208,9 +208,9 @@ async def decrypt(self, algorithm: "EncryptionAlgorithm", ciphertext: bytes, **k try: return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "decrypt" operation with algorithm "{}"'.format(algorithm) @@ -250,9 +250,9 @@ async def wrap_key(self, algorithm: "KeyWrapAlgorithm", key: bytes, **kwargs: "A try: return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "wrapKey" operation with algorithm "{}"'.format(algorithm) @@ -289,9 +289,9 @@ async def unwrap_key(self, algorithm: "KeyWrapAlgorithm", encrypted_key: bytes, try: return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "unwrapKey" operation with algorithm "{}"'.format(algorithm) @@ -329,9 +329,9 @@ async def sign(self, algorithm: "SignatureAlgorithm", digest: bytes, **kwargs: " try: return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "sign" operation with algorithm "{}"'.format(algorithm) @@ -372,9 +372,9 @@ async def verify( try: return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except + _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) if self._local_only: raise - _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) elif self._local_only: raise NotImplementedError( 'This key does not support the "verify" operation with algorithm "{}"'.format(algorithm) From b801f12d51a935c1e534781a73211a67875dd41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Thu, 4 Mar 2021 13:33:23 -0800 Subject: [PATCH 05/18] Accept JsonWebKey object --- .../azure/keyvault/keys/crypto/_client.py | 17 ++++++++++++----- .../azure/keyvault/keys/crypto/aio/_client.py | 18 ++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 29e6762c10e2..9c5a0674247e 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -13,7 +13,7 @@ from ._key_validity import raise_if_time_invalid from ._providers import get_local_cryptography_provider, NoLocalCryptography from .. import KeyOperation -from .._models import KeyVaultKey +from .._models import JsonWebKey, KeyVaultKey from .._shared import KeyVaultClientBase, parse_key_vault_id if TYPE_CHECKING: @@ -129,13 +129,20 @@ def key_id(self): @classmethod def from_jwk(cls, jwk): - # type: (dict) -> CryptographyClient + # type: (Union[JsonWebKey, dict]) -> CryptographyClient """Creates a client that can only perform cryptographic operations locally. - :param dict jwk: the key's cryptographic material, as a dictionary. + :param jwk: the key's cryptographic material, as a JsonWebKey or dictionary. + :type jwk: JsonWebKey or dict + :rtype: CryptographyClient """ - key_id = "https://key-vault.vault.azure.net/keys/local-key" - return cls(KeyVaultKey(key_id, jwk), object, _local_only=True) + if isinstance(jwk, JsonWebKey): + key = vars(jwk) + key_id = jwk.kid + else: + key = jwk + key_id = jwk.get("kid") + return cls(KeyVaultKey(key_id, key), object(), _local_only=True) @distributed_trace def _initialize(self, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 2a639c17bd72..a5aabffd6f1b 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -13,7 +13,7 @@ from .._key_validity import raise_if_time_invalid from .._providers import get_local_cryptography_provider, NoLocalCryptography from ... import KeyOperation -from ..._models import KeyVaultKey +from ..._models import JsonWebKey, KeyVaultKey from ..._shared import AsyncKeyVaultClientBase, parse_key_vault_id if TYPE_CHECKING: @@ -82,14 +82,20 @@ def key_id(self) -> str: return self._key_id.source_id @classmethod - def from_jwk(cls, jwk): - # type: (dict) -> CryptographyClient + def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": """Creates a client that can only perform cryptographic operations locally. - :param dict jwk: the key's cryptographic material, as a dictionary. + :param jwk: the key's cryptographic material, as a JsonWebKey or dictionary. + :type jwk: JsonWebKey or dict + :rtype: CryptographyClient """ - key_id = "https://key-vault.vault.azure.net/keys/local-key" - return cls(KeyVaultKey(key_id, jwk), object, _local_only=True) + if isinstance(jwk, JsonWebKey): + key = vars(jwk) + key_id = jwk.kid + else: + key = jwk + key_id = jwk.get("kid") + return cls(KeyVaultKey(key_id, key), object(), _local_only=True) @distributed_trace_async async def _initialize(self, **kwargs): From ae2967ba1fe5dec48fd88ce117b072c142702e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Thu, 4 Mar 2021 14:51:30 -0800 Subject: [PATCH 06/18] Allow None key_id, try JWK's .kid --- .../azure/keyvault/keys/_models.py | 14 ++++++++++---- .../azure/keyvault/keys/crypto/_client.py | 18 ++++++++++++------ .../azure/keyvault/keys/crypto/aio/_client.py | 18 ++++++++++++------ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py index 4e9879cec068..14d70ce66c6d 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py @@ -68,9 +68,12 @@ def __init__(self, key_id, attributes=None, **kwargs): # type: (str, Optional[_models.KeyAttributes], **Any) -> None self._attributes = attributes self._id = key_id - self._vault_id = parse_key_vault_id(key_id) self._managed = kwargs.get("managed", None) self._tags = kwargs.get("tags", None) + try: + self._vault_id = parse_key_vault_id(key_id) + except: + self._vault_id = None def __repr__(self): # type () -> str @@ -106,7 +109,8 @@ def name(self): :rtype: str """ - return self._vault_id.name + if self._vault_id: + return self._vault_id.name @property def version(self): @@ -115,7 +119,8 @@ def version(self): :rtype: str """ - return self._vault_id.version + if self._vault_id: + return self._vault_id.version @property def enabled(self): @@ -169,7 +174,8 @@ def vault_url(self): :rtype: str """ - return self._vault_id.vault_url + if self._vault_id: + return self._vault_id.vault_url @property def recoverable_days(self): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 9c5a0674247e..53f643162538 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -102,7 +102,12 @@ def __init__(self, key, credential, **kwargs): if isinstance(key, KeyVaultKey): self._key = key - self._key_id = parse_key_vault_id(key.id) + try: + self._key_id = parse_key_vault_id(key.id) + except ValueError: + if not self._local_only: + raise + self._key_id = None elif isinstance(key, six.string_types): self._key = None self._key_id = parse_key_vault_id(key) @@ -110,13 +115,14 @@ def __init__(self, key, credential, **kwargs): else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") - if not (self._key_id.version or self._local_only): + if not (self._local_only or self._key_id.version): raise ValueError("'key' must include a version") self._local_provider = NoLocalCryptography() self._initialized = False - super(CryptographyClient, self).__init__(vault_url=self._key_id.vault_url, credential=credential, **kwargs) + vault_url = "vault_url" if not self._key_id else self._key_id.vault_url + super(CryptographyClient, self).__init__(vault_url=vault_url, credential=credential, **kwargs) @property def key_id(self): @@ -125,7 +131,8 @@ def key_id(self): :rtype: str """ - return self._key_id.source_id + if self._key_id: + return self._key_id.source_id @classmethod def from_jwk(cls, jwk): @@ -138,10 +145,9 @@ def from_jwk(cls, jwk): """ if isinstance(jwk, JsonWebKey): key = vars(jwk) - key_id = jwk.kid else: key = jwk - key_id = jwk.get("kid") + key_id = key.get("kid") return cls(KeyVaultKey(key_id, key), object(), _local_only=True) @distributed_trace diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index a5aabffd6f1b..872060e67b9c 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -57,7 +57,12 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden if isinstance(key, KeyVaultKey): self._key = key - self._key_id = parse_key_vault_id(key.id) + try: + self._key_id = parse_key_vault_id(key.id) + except ValueError: + if not self._local_only: + raise + self._key_id = None elif isinstance(key, str): self._key = None self._key_id = parse_key_vault_id(key) @@ -65,13 +70,14 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") - if not (self._key_id.version or self._local_only): + if not (self._local_only or self._key_id.version): raise ValueError("'key' must include a version") self._local_provider = NoLocalCryptography() self._initialized = False - super().__init__(vault_url=self._key_id.vault_url, credential=credential, **kwargs) + vault_url = "vault_url" if not self._key_id else self._key_id.vault_url + super().__init__(vault_url=vault_url, credential=credential, **kwargs) @property def key_id(self) -> str: @@ -79,7 +85,8 @@ def key_id(self) -> str: :rtype: str """ - return self._key_id.source_id + if self._key_id: + return self._key_id.source_id @classmethod def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": @@ -91,10 +98,9 @@ def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": """ if isinstance(jwk, JsonWebKey): key = vars(jwk) - key_id = jwk.kid else: key = jwk - key_id = jwk.get("kid") + key_id = key.get("kid") return cls(KeyVaultKey(key_id, key), object(), _local_only=True) @distributed_trace_async From 0d2519f4ab96237d73196a13f414fcb11b9ee511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Thu, 4 Mar 2021 18:22:42 -0800 Subject: [PATCH 07/18] Use JsonWebKey in tests for .kid --- sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py | 2 +- .../azure-keyvault-keys/tests/test_crypto_client_async.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index d9978177fb0d..7382f8685034 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -495,7 +495,7 @@ def test_local_only_mode_no_service_calls(): """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" mock_client = mock.Mock() - jwk = mock.Mock(spec=JsonWebKey) + jwk = JsonWebKey() client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index 5dcb89f12135..0b07a464b118 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -520,7 +520,7 @@ async def test_local_only_mode_no_service_calls(): """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" mock_client = mock.Mock() - jwk = mock.Mock(spec=JsonWebKey) + jwk = JsonWebKey() client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client From 218a312b8cdbb40a363b561530d6e13dcb11ca3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Thu, 4 Mar 2021 18:42:27 -0800 Subject: [PATCH 08/18] Add .from_jwk example --- .../azure/keyvault/keys/crypto/_client.py | 7 +++++++ .../azure/keyvault/keys/crypto/aio/_client.py | 7 +++++++ .../tests/test_examples_crypto.py | 14 +++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 53f643162538..fa8fafa7628c 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -142,6 +142,13 @@ def from_jwk(cls, jwk): :param jwk: the key's cryptographic material, as a JsonWebKey or dictionary. :type jwk: JsonWebKey or dict :rtype: CryptographyClient + + .. literalinclude:: ../tests/test_examples_crypto.py + :start-after: [START from_jwk] + :end-before: [END from_jwk] + :caption: Create a CryptographyClient from a JsonWebKey + :language: python + :dedent: 8 """ if isinstance(jwk, JsonWebKey): key = vars(jwk) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 872060e67b9c..bd3a9d60756a 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -95,6 +95,13 @@ def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": :param jwk: the key's cryptographic material, as a JsonWebKey or dictionary. :type jwk: JsonWebKey or dict :rtype: CryptographyClient + + .. literalinclude:: ../tests/test_examples_crypto.py + :start-after: [START from_jwk] + :end-before: [END from_jwk] + :caption: Create a CryptographyClient from a JsonWebKey + :language: python + :dedent: 8 """ if isinstance(jwk, JsonWebKey): key = vars(jwk) diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py b/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py index c5f0da5b6517..eb4413e61b13 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py @@ -4,7 +4,7 @@ # ------------------------------------ import functools -from azure.keyvault.keys import KeyClient +from azure.keyvault.keys import JsonWebKey, KeyClient from azure.keyvault.keys.crypto import CryptographyClient from azure.keyvault.keys._shared import HttpChallengeCache from devtools_testutils import PowerShellPreparer @@ -18,6 +18,18 @@ ) +def test_create_client_from_jwk(): + # [START from_jwk] + # create a CryptographyClient using a JsonWebKey instance + key = JsonWebKey(kty="RSA") + crypto_client = CryptographyClient.from_jwk(jwk=key) + + # or a dictionary with JsonWebKey properties + key_dict = {"kty":"RSA"} + crypto_client = CryptographyClient.from_jwk(jwk=key_dict) + # [END from_jwk] + + class TestCryptoExamples(KeyVaultTestCase): def __init__(self, *args, **kwargs): kwargs["match_body"] = False From 8a602c1d61e7244c6e625c1ce67529fad3d83946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Fri, 5 Mar 2021 09:11:44 -0800 Subject: [PATCH 09/18] Address pylint --- .../azure-keyvault-keys/azure/keyvault/keys/_models.py | 9 ++++++--- .../azure/keyvault/keys/crypto/_client.py | 3 ++- .../azure/keyvault/keys/crypto/aio/_client.py | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py index 14d70ce66c6d..efb660431f5e 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py @@ -104,23 +104,25 @@ def id(self): @property def name(self): - # type: () -> str + # type: () -> Optional[str] """The key's name :rtype: str """ if self._vault_id: return self._vault_id.name + return None @property def version(self): - # type: () -> str + # type: () -> Optional[str] """The key's version :rtype: str """ if self._vault_id: return self._vault_id.version + return None @property def enabled(self): @@ -169,13 +171,14 @@ def updated_on(self): @property def vault_url(self): - # type: () -> str + # type: () -> Optional[str] """URL of the vault containing the key :rtype: str """ if self._vault_id: return self._vault_id.vault_url + return None @property def recoverable_days(self): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index fa8fafa7628c..23299eb357d8 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -126,13 +126,14 @@ def __init__(self, key, credential, **kwargs): @property def key_id(self): - # type: () -> str + # type: () -> Optional[str] """The full identifier of the client's key. :rtype: str """ if self._key_id: return self._key_id.source_id + return None @classmethod def from_jwk(cls, jwk): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index bd3a9d60756a..901cb098c2e8 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -80,13 +80,14 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden super().__init__(vault_url=vault_url, credential=credential, **kwargs) @property - def key_id(self) -> str: + def key_id(self) -> "Optional[str]": """The full identifier of the client's key. :rtype: str """ if self._key_id: return self._key_id.source_id + return None @classmethod def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": From 8345eb6b74d19074007aba2b2b8eb1df89553ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Fri, 5 Mar 2021 13:21:44 -0800 Subject: [PATCH 10/18] Pass JWK to crypto client --- .../azure/keyvault/keys/_models.py | 26 ++++------ .../azure/keyvault/keys/crypto/_client.py | 49 +++++++++---------- .../azure/keyvault/keys/crypto/aio/_client.py | 49 +++++++++---------- 3 files changed, 55 insertions(+), 69 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py index efb660431f5e..c83fb338e23e 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py @@ -68,12 +68,9 @@ def __init__(self, key_id, attributes=None, **kwargs): # type: (str, Optional[_models.KeyAttributes], **Any) -> None self._attributes = attributes self._id = key_id + self._vault_id = parse_key_vault_id(key_id) self._managed = kwargs.get("managed", None) self._tags = kwargs.get("tags", None) - try: - self._vault_id = parse_key_vault_id(key_id) - except: - self._vault_id = None def __repr__(self): # type () -> str @@ -104,25 +101,21 @@ def id(self): @property def name(self): - # type: () -> Optional[str] + # type: () -> str """The key's name :rtype: str """ - if self._vault_id: - return self._vault_id.name - return None + return self._vault_id.name @property def version(self): - # type: () -> Optional[str] + # type: () -> str """The key's version :rtype: str """ - if self._vault_id: - return self._vault_id.version - return None + return self._vault_id.version @property def enabled(self): @@ -171,14 +164,12 @@ def updated_on(self): @property def vault_url(self): - # type: () -> Optional[str] + # type: () -> str """URL of the vault containing the key :rtype: str """ - if self._vault_id: - return self._vault_id.vault_url - return None + return self._vault_id.vault_url @property def recoverable_days(self): @@ -254,7 +245,8 @@ class KeyVaultKey(object): def __init__(self, key_id, jwk=None, **kwargs): # type: (str, Optional[dict], **Any) -> None - self._properties = kwargs.pop("properties", None) or KeyProperties(key_id, **kwargs) + if not kwargs.pop("_local_only", False): + self._properties = kwargs.pop("properties", None) or KeyProperties(key_id, **kwargs) if isinstance(jwk, dict): if any(field in kwargs for field in JsonWebKey._FIELDS): # pylint:disable=protected-access raise ValueError( diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 23299eb357d8..c090e9c0aab4 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -98,42 +98,40 @@ class CryptographyClient(KeyVaultClientBase): def __init__(self, key, credential, **kwargs): # type: (Union[KeyVaultKey, str], TokenCredential, **Any) -> None - self._local_only = kwargs.pop("_local_only", False) + self._jwk = kwargs.pop("_jwk", False) if isinstance(key, KeyVaultKey): self._key = key - try: - self._key_id = parse_key_vault_id(key.id) - except ValueError: - if not self._local_only: - raise - self._key_id = None + self._key_id = parse_key_vault_id(key.id) elif isinstance(key, six.string_types): self._key = None self._key_id = parse_key_vault_id(key) self._keys_get_forbidden = None # type: Optional[bool] + elif self._jwk: + self._key_id = key.get("kid", "") + self._key = KeyVaultKey(None, jwk=key, _local_only=True) else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") - if not (self._local_only or self._key_id.version): + if not (self._jwk or self._key_id.version): raise ValueError("'key' must include a version") self._local_provider = NoLocalCryptography() self._initialized = False - vault_url = "vault_url" if not self._key_id else self._key_id.vault_url + vault_url = "vault_url" if self._jwk else self._key_id.vault_url super(CryptographyClient, self).__init__(vault_url=vault_url, credential=credential, **kwargs) @property def key_id(self): - # type: () -> Optional[str] + # type: () -> str """The full identifier of the client's key. :rtype: str """ - if self._key_id: + if not self._jwk: return self._key_id.source_id - return None + return self._key_id @classmethod def from_jwk(cls, jwk): @@ -155,8 +153,7 @@ def from_jwk(cls, jwk): key = vars(jwk) else: key = jwk - key_id = key.get("kid") - return cls(KeyVaultKey(key_id, key), object(), _local_only=True) + return cls(key, object(), _jwk=True) @distributed_trace def _initialize(self, **kwargs): @@ -218,9 +215,9 @@ def encrypt(self, algorithm, plaintext, **kwargs): return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "encrypt" operation with algorithm "{}"'.format(algorithm) ) @@ -278,9 +275,9 @@ def decrypt(self, algorithm, ciphertext, **kwargs): return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "decrypt" operation with algorithm "{}"'.format(algorithm) ) @@ -321,9 +318,9 @@ def wrap_key(self, algorithm, key, **kwargs): return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "wrapKey" operation with algorithm "{}"'.format(algorithm) ) @@ -361,9 +358,9 @@ def unwrap_key(self, algorithm, encrypted_key, **kwargs): return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "unwrapKey" operation with algorithm "{}"'.format(algorithm) ) @@ -401,9 +398,9 @@ def sign(self, algorithm, digest, **kwargs): return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "sign" operation with algorithm "{}"'.format(algorithm) ) @@ -443,9 +440,9 @@ def verify(self, algorithm, digest, signature, **kwargs): return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "verify" operation with algorithm "{}"'.format(algorithm) ) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 901cb098c2e8..24aff439f693 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -53,41 +53,39 @@ class CryptographyClient(AsyncKeyVaultClientBase): """ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCredential", **kwargs: "Any") -> None: - self._local_only = kwargs.pop("_local_only", False) + self._jwk = kwargs.pop("_jwk", False) if isinstance(key, KeyVaultKey): self._key = key - try: - self._key_id = parse_key_vault_id(key.id) - except ValueError: - if not self._local_only: - raise - self._key_id = None + self._key_id = parse_key_vault_id(key.id) elif isinstance(key, str): self._key = None self._key_id = parse_key_vault_id(key) self._keys_get_forbidden = None # type: Optional[bool] + elif self._jwk: + self._key_id = key.get("kid", "") + self._key = KeyVaultKey(None, jwk=key, _local_only=True) else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") - if not (self._local_only or self._key_id.version): + if not (self._jwk or self._key_id.version): raise ValueError("'key' must include a version") self._local_provider = NoLocalCryptography() self._initialized = False - vault_url = "vault_url" if not self._key_id else self._key_id.vault_url + vault_url = "vault_url" if self._jwk else self._key_id.vault_url super().__init__(vault_url=vault_url, credential=credential, **kwargs) @property - def key_id(self) -> "Optional[str]": + def key_id(self) -> str: """The full identifier of the client's key. :rtype: str """ - if self._key_id: + if not self._jwk: return self._key_id.source_id - return None + return self._key_id @classmethod def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": @@ -108,8 +106,7 @@ def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": key = vars(jwk) else: key = jwk - key_id = key.get("kid") - return cls(KeyVaultKey(key_id, key), object(), _local_only=True) + return cls(key, object(), _jwk=True) @distributed_trace_async async def _initialize(self, **kwargs): @@ -170,9 +167,9 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local encrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "encrypt" operation with algorithm "{}"'.format(algorithm) ) @@ -229,9 +226,9 @@ async def decrypt(self, algorithm: "EncryptionAlgorithm", ciphertext: bytes, **k return self._local_provider.decrypt(algorithm, ciphertext) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local decrypt operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "decrypt" operation with algorithm "{}"'.format(algorithm) ) @@ -271,9 +268,9 @@ async def wrap_key(self, algorithm: "KeyWrapAlgorithm", key: bytes, **kwargs: "A return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local wrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "wrapKey" operation with algorithm "{}"'.format(algorithm) ) @@ -310,9 +307,9 @@ async def unwrap_key(self, algorithm: "KeyWrapAlgorithm", encrypted_key: bytes, return self._local_provider.unwrap_key(algorithm, encrypted_key) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local unwrap operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "unwrapKey" operation with algorithm "{}"'.format(algorithm) ) @@ -350,9 +347,9 @@ async def sign(self, algorithm: "SignatureAlgorithm", digest: bytes, **kwargs: " return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local sign operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "sign" operation with algorithm "{}"'.format(algorithm) ) @@ -393,9 +390,9 @@ async def verify( return self._local_provider.verify(algorithm, digest, signature) except Exception as ex: # pylint:disable=broad-except _LOGGER.warning("Local verify operation failed: %s", ex, exc_info=_LOGGER.isEnabledFor(logging.DEBUG)) - if self._local_only: + if self._jwk: raise - elif self._local_only: + elif self._jwk: raise NotImplementedError( 'This key does not support the "verify" operation with algorithm "{}"'.format(algorithm) ) From ec7afafaac409203af3d75a83f5c070e971ad424 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Fri, 5 Mar 2021 15:33:09 -0800 Subject: [PATCH 11/18] Add JWK support for local providers --- .../azure/keyvault/keys/_models.py | 3 +- .../azure/keyvault/keys/crypto/_client.py | 10 +- .../keyvault/keys/crypto/_key_validity.py | 5 +- .../keys/crypto/_providers/__init__.py | 18 +- .../keyvault/keys/crypto/_providers/ec.py | 16 +- .../keys/crypto/_providers/local_provider.py | 29 +- .../keyvault/keys/crypto/_providers/rsa.py | 16 +- .../keys/crypto/_providers/symmetric.py | 16 +- .../azure/keyvault/keys/crypto/aio/_client.py | 12 +- ..._client.test_ec_verify_local_from_jwk.yaml | 440 +++++++ ...to_client.test_encrypt_local_from_jwk.yaml | 249 ++++ ...client.test_rsa_verify_local_from_jwk.yaml | 1074 +++++++++++++++++ ...rypto_client.test_wrap_local_from_jwk.yaml | 249 ++++ ...t_async.test_ec_verify_local_from_jwk.yaml | 302 +++++ ...ent_async.test_encrypt_local_from_jwk.yaml | 170 +++ ..._async.test_rsa_verify_local_from_jwk.yaml | 731 +++++++++++ ...client_async.test_wrap_local_from_jwk.yaml | 170 +++ .../tests/test_crypto_client.py | 83 ++ .../tests/test_crypto_client_async.py | 83 ++ 19 files changed, 3633 insertions(+), 43 deletions(-) create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_ec_verify_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_encrypt_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_rsa_verify_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_wrap_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_ec_verify_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_encrypt_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_rsa_verify_local_from_jwk.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_wrap_local_from_jwk.yaml diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py index c83fb338e23e..4e9879cec068 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py @@ -245,8 +245,7 @@ class KeyVaultKey(object): def __init__(self, key_id, jwk=None, **kwargs): # type: (str, Optional[dict], **Any) -> None - if not kwargs.pop("_local_only", False): - self._properties = kwargs.pop("properties", None) or KeyProperties(key_id, **kwargs) + self._properties = kwargs.pop("properties", None) or KeyProperties(key_id, **kwargs) if isinstance(jwk, dict): if any(field in kwargs for field in JsonWebKey._FIELDS): # pylint:disable=protected-access raise ValueError( diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index c090e9c0aab4..1df04aa9d783 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -108,8 +108,8 @@ def __init__(self, key, credential, **kwargs): self._key_id = parse_key_vault_id(key) self._keys_get_forbidden = None # type: Optional[bool] elif self._jwk: - self._key_id = key.get("kid", "") - self._key = KeyVaultKey(None, jwk=key, _local_only=True) + self._key = key + self._key_id = key.kid else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") @@ -127,6 +127,8 @@ def key_id(self): # type: () -> str """The full identifier of the client's key. + This property may be None when a client is constructed with `CryptographyClient.from_jwk`. + :rtype: str """ if not self._jwk: @@ -150,9 +152,9 @@ def from_jwk(cls, jwk): :dedent: 8 """ if isinstance(jwk, JsonWebKey): - key = vars(jwk) - else: key = jwk + else: + key = JsonWebKey(**jwk) return cls(key, object(), _jwk=True) @distributed_trace diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py index 50ded9aade8a..089248c85d37 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py @@ -7,7 +7,8 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from .. import KeyVaultKey + from typing import Union + from .. import JsonWebKey, KeyVaultKey class _UTC_TZ(tzinfo): @@ -29,7 +30,7 @@ def dst(self, dt): def raise_if_time_invalid(key): - # type: (KeyVaultKey) -> None + # type: (Union[JsonWebKey, KeyVaultKey]) -> None try: nbf = key.properties.not_before exp = key.properties.expires_on diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py index 9948dbf24e9e..f62e65bfa945 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py @@ -8,22 +8,28 @@ from .local_provider import LocalCryptographyProvider from .rsa import RsaCryptographyProvider from .symmetric import SymmetricCryptographyProvider -from ... import KeyType +from ... import JsonWebKey, KeyType if TYPE_CHECKING: + from typing import Union from ... import KeyVaultKey def get_local_cryptography_provider(key): - # type: (KeyVaultKey) -> LocalCryptographyProvider - if key.key_type in (KeyType.ec, KeyType.ec_hsm): + # type: (Union[JsonWebKey, KeyVaultKey]) -> LocalCryptographyProvider + if isinstance(key, JsonWebKey): + key_type = key.kty + else: + key_type = key.key_type + + if key_type in (KeyType.ec, KeyType.ec_hsm): return EllipticCurveCryptographyProvider(key) - if key.key_type in (KeyType.rsa, KeyType.rsa_hsm): + if key_type in (KeyType.rsa, KeyType.rsa_hsm): return RsaCryptographyProvider(key) - if key.key_type in (KeyType.oct, KeyType.oct_hsm): + if key_type in (KeyType.oct, KeyType.oct_hsm): return SymmetricCryptographyProvider(key) - raise ValueError('Unsupported key type "{}"'.format(key.key_type)) + raise ValueError('Unsupported key type "{}"'.format(key_type)) class NoLocalCryptography(LocalCryptographyProvider): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py index 1534e1da9927..33cc3c62d5eb 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py @@ -6,10 +6,11 @@ from .local_provider import LocalCryptographyProvider from .._internal import EllipticCurveKey -from ... import KeyOperation, KeyType +from ... import JsonWebKey, KeyOperation, KeyType if TYPE_CHECKING: # pylint:disable=unused-import + from typing import Union from .local_provider import Algorithm from .._internal import Key from ... import KeyVaultKey @@ -19,10 +20,17 @@ class EllipticCurveCryptographyProvider(LocalCryptographyProvider): def _get_internal_key(self, key): - # type: (KeyVaultKey) -> Key - if key.key_type not in (KeyType.ec, KeyType.ec_hsm): + # type: (Union[JsonWebKey, KeyVaultKey]) -> Key + if isinstance(key, JsonWebKey): + key_type = key.kty + jwk = key + else: + key_type = key.key_type + jwk = key.key + + if key_type not in (KeyType.ec, KeyType.ec_hsm): raise ValueError('"key" must be an EC or EC-HSM key') - return EllipticCurveKey.from_jwk(key.key) + return EllipticCurveKey.from_jwk(jwk) def supports(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> bool diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py index 1d81dd897cc6..fbf79e26f9d6 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py @@ -8,7 +8,7 @@ from azure.core.exceptions import AzureError from .. import DecryptResult, EncryptResult, SignResult, UnwrapResult, VerifyResult, WrapResult -from ... import KeyOperation +from ... import JsonWebKey, KeyOperation try: ABC = abc.ABC @@ -17,7 +17,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from typing import Union + from typing import Optional, Union from .._internal.key import Key from .. import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm from ... import KeyVaultKey @@ -27,14 +27,17 @@ class LocalCryptographyProvider(ABC): def __init__(self, key): - # type: (KeyVaultKey) -> None - self._allowed_ops = frozenset(key.key_operations) + # type: (Union[JsonWebKey, KeyVaultKey]) -> None + if isinstance(key, JsonWebKey): + self._allowed_ops = frozenset(key.key_ops) + else: + self._allowed_ops = frozenset(key.key_operations) self._internal_key = self._get_internal_key(key) self._key = key @abc.abstractmethod def _get_internal_key(self, key): - # type: (KeyVaultKey) -> Key + # type: (Union[JsonWebKey, KeyVaultKey]) -> Key pass @abc.abstractmethod @@ -44,11 +47,13 @@ def supports(self, operation, algorithm): @property def key_id(self): - # type: () -> str + # type: () -> Optional[str] """The full identifier of the provider's key. :rtype: str """ + if isinstance(self._key, JsonWebKey): + return self._key.kid return self._key.id def _raise_if_unsupported(self, operation, algorithm): @@ -64,34 +69,34 @@ def encrypt(self, algorithm, plaintext): # type: (EncryptionAlgorithm, bytes) -> EncryptResult self._raise_if_unsupported(KeyOperation.encrypt, algorithm) ciphertext = self._internal_key.encrypt(plaintext, algorithm=algorithm.value) - return EncryptResult(key_id=self._key.id, algorithm=algorithm, ciphertext=ciphertext) + return EncryptResult(key_id=self.key_id, algorithm=algorithm, ciphertext=ciphertext) def decrypt(self, algorithm, ciphertext): # type: (EncryptionAlgorithm, bytes) -> DecryptResult self._raise_if_unsupported(KeyOperation.decrypt, algorithm) plaintext = self._internal_key.decrypt(ciphertext, iv=None, algorithm=algorithm.value) - return DecryptResult(key_id=self._key.id, algorithm=algorithm, plaintext=plaintext) + return DecryptResult(key_id=self.key_id, algorithm=algorithm, plaintext=plaintext) def wrap_key(self, algorithm, key): # type: (KeyWrapAlgorithm, bytes) -> WrapResult self._raise_if_unsupported(KeyOperation.wrap_key, algorithm) encrypted_key = self._internal_key.wrap_key(key, algorithm=algorithm.value) - return WrapResult(key_id=self._key.id, algorithm=algorithm, encrypted_key=encrypted_key) + return WrapResult(key_id=self.key_id, algorithm=algorithm, encrypted_key=encrypted_key) def unwrap_key(self, algorithm, encrypted_key): # type: (KeyWrapAlgorithm, bytes) -> UnwrapResult self._raise_if_unsupported(KeyOperation.unwrap_key, algorithm) unwrapped_key = self._internal_key.unwrap_key(encrypted_key, algorithm=algorithm.value) - return UnwrapResult(key_id=self._key.id, algorithm=algorithm, key=unwrapped_key) + return UnwrapResult(key_id=self.key_id, algorithm=algorithm, key=unwrapped_key) def sign(self, algorithm, digest): # type: (SignatureAlgorithm, bytes) -> SignResult self._raise_if_unsupported(KeyOperation.sign, algorithm) signature = self._internal_key.sign(digest, algorithm=algorithm.value) - return SignResult(key_id=self._key.id, algorithm=algorithm, signature=signature) + return SignResult(key_id=self.key_id, algorithm=algorithm, signature=signature) def verify(self, algorithm, digest, signature): # type: (SignatureAlgorithm, bytes, bytes) -> VerifyResult self._raise_if_unsupported(KeyOperation.verify, algorithm) is_valid = self._internal_key.verify(digest, signature, algorithm=algorithm.value) - return VerifyResult(key_id=self._key.id, algorithm=algorithm, is_valid=is_valid) + return VerifyResult(key_id=self.key_id, algorithm=algorithm, is_valid=is_valid) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py index b7d913a7f7ed..d78808e3d8c0 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py @@ -6,10 +6,11 @@ from .local_provider import LocalCryptographyProvider from .._internal import RsaKey -from ... import KeyOperation, KeyType +from ... import JsonWebKey, KeyOperation, KeyType if TYPE_CHECKING: # pylint:disable=unused-import + from typing import Union from .local_provider import Algorithm from .._internal import Key from ... import KeyVaultKey @@ -19,10 +20,17 @@ class RsaCryptographyProvider(LocalCryptographyProvider): def _get_internal_key(self, key): - # type: (KeyVaultKey) -> Key - if key.key_type not in (KeyType.rsa, KeyType.rsa_hsm): + # type: (Union[JsonWebKey, KeyVaultKey]) -> Key + if isinstance(key, JsonWebKey): + key_type = key.kty + jwk = key + else: + key_type = key.key_type + jwk = key.key + + if key_type not in (KeyType.rsa, KeyType.rsa_hsm): raise ValueError('"key" must be an RSA or RSA-HSM key') - return RsaKey.from_jwk(key.key) + return RsaKey.from_jwk(jwk) def supports(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> bool diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py index 27da1e7224ad..ed8399e1c3ab 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py @@ -6,10 +6,11 @@ from .local_provider import LocalCryptographyProvider from .._internal import SymmetricKey -from ... import KeyOperation, KeyType +from ... import JsonWebKey, KeyOperation, KeyType if TYPE_CHECKING: # pylint:disable=unused-import + from typing import Union from .local_provider import Algorithm from .._internal import Key from ... import KeyVaultKey @@ -17,10 +18,17 @@ class SymmetricCryptographyProvider(LocalCryptographyProvider): def _get_internal_key(self, key): - # type: (KeyVaultKey) -> Key - if key.key_type not in (KeyType.oct, KeyType.oct_hsm): + # type: (Union[JsonWebKey, KeyVaultKey]) -> Key + if isinstance(key, JsonWebKey): + key_type = key.kty + jwk = key + else: + key_type = key.key_type + jwk = key.key + + if key_type not in (KeyType.oct, KeyType.oct_hsm): raise ValueError('"key" must be an oct or oct-HSM (symmetric) key') - return SymmetricKey.from_jwk(key.key) + return SymmetricKey.from_jwk(jwk) def supports(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> bool diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 24aff439f693..b87110bd162d 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -63,8 +63,8 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden self._key_id = parse_key_vault_id(key) self._keys_get_forbidden = None # type: Optional[bool] elif self._jwk: - self._key_id = key.get("kid", "") - self._key = KeyVaultKey(None, jwk=key, _local_only=True) + self._key = key + self._key_id = key.kid else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") @@ -78,9 +78,11 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden super().__init__(vault_url=vault_url, credential=credential, **kwargs) @property - def key_id(self) -> str: + def key_id(self) -> "Optional[str]": """The full identifier of the client's key. + This property may be None when a client is constructed with `CryptographyClient.from_jwk`. + :rtype: str """ if not self._jwk: @@ -103,9 +105,9 @@ def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": :dedent: 8 """ if isinstance(jwk, JsonWebKey): - key = vars(jwk) - else: key = jwk + else: + key = JsonWebKey(**jwk) return cls(key, object(), _jwk=True) @distributed_trace_async diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_ec_verify_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_ec_verify_local_from_jwk.yaml new file mode 100644 index 000000000000..a96e85ff87fa --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_ec_verify_local_from_jwk.yaml @@ -0,0 +1,440 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256e71713d0/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: + - no-cache + content-length: + - '87' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:21 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + www-authenticate: + - Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 401 + message: Unauthorized +- request: + body: '{"kty": "EC", "crv": "P-256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '29' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256e71713d0/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256e71713d0/889e735ae88d49739bc86916a6eb206a","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"kn413jTUQfeMKYSTS_wVAGLzgdmqb3hdXyK5bnk3dSs","y":"PG8pzwEh4Z8kFTiPWgQwew5GTzurfoAN4JmVUkHROak"},"attributes":{"enabled":true,"created":1614986782,"updated":1614986782,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '410' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:22 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "ES256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256e71713d0/889e735ae88d49739bc86916a6eb206a/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256e71713d0/889e735ae88d49739bc86916a6eb206a","value":"Yu7PQ-n1OLBHTaPnqMkg2SiyRDZRKizRfD1th9x9KytyDYoDxHUrKod0GKwRZXRwVIWR0puMJfZ5AmmX8PMVOg"}' + headers: + cache-control: + - no-cache + content-length: + - '213' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:23 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"kty": "EC", "crv": "P-256K"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '30' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256Ke71713d0/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256Ke71713d0/02d02952562a49bc9b2700b790aec8e0","kty":"EC","key_ops":["sign","verify"],"crv":"P-256K","x":"MT9oIuXKOA2qa_RyPiWnXiJZTP8hbMqmGcey1V43kRE","y":"2frXKwM2ok_kRoSkEHYc_5_Fm9EVGnpEs7fZt9i1QwQ"},"attributes":{"enabled":true,"created":1614986783,"updated":1614986783,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '412' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:23 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "ES256K"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '73' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256Ke71713d0/02d02952562a49bc9b2700b790aec8e0/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256Ke71713d0/02d02952562a49bc9b2700b790aec8e0","value":"GgEzWas-7x2eHbJsg3WLs4byiNGszZD_qvlAAe9rIx4W8BktA5LDX04qa7Ef_8O752UL21T2mj5zMI3C9x8QyA"}' + headers: + cache-control: + - no-cache + content-length: + - '214' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:24 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"kty": "EC", "crv": "P-384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '29' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384e71713d0/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384e71713d0/705d6c6fd01341f2a490e5b217899d9a","kty":"EC","key_ops":["sign","verify"],"crv":"P-384","x":"56os745Y6u8-kd4rFFpbFgsiDb-Dipw32K41oYV1_-4-qQcPNPLb9zTX1-HL_KxB","y":"bFNAAgjUJFARDZZixKHqQonq7_5wuLCjpuSmIhxkoR0wjKfQoWWlbBXFbQ3KguuP"},"attributes":{"enabled":true,"created":1614986784,"updated":1614986784,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '452' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:24 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "ES384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384e71713d0/705d6c6fd01341f2a490e5b217899d9a/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384e71713d0/705d6c6fd01341f2a490e5b217899d9a","value":"Jdx-IadMABV9bMUa7lQ8uC_spoUU9Q-GmIIQXigNVo96naHvfCtwikpds94LElMtS-67z03z9pGZFdA4WMG_vP8AZ15MlL7BKkwO584Jq8A_gdui4zDQIfm3dIHXQWdW"}' + headers: + cache-control: + - no-cache + content-length: + - '255' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:25 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"kty": "EC", "crv": "P-521"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '29' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521e71713d0/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521e71713d0/419e3aed3284473588af44b307964065","kty":"EC","key_ops":["sign","verify"],"crv":"P-521","x":"AR2D_VhROOmf-fXCsXdGPBC00fTqqUGlZV5HBl_OtuCe34K0d3tw-2LzEV50AfcXYZWlN-bdTRnFBaxd908vftpx","y":"AEr4s7j679hF8oQO-et9ulPHJ3IGdWW6pHk3jFtyYqCacfy6SiznWum3y9DQGuTlsXHBPvSqxPQa4prR9WGvGQ8w"},"attributes":{"enabled":true,"created":1614986785,"updated":1614986785,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '500' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:25 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "ES512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521e71713d0/419e3aed3284473588af44b307964065/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521e71713d0/419e3aed3284473588af44b307964065","value":"AAMl_OvQngawq7GABRQ640AMp-QCOvKuZGDlM6iy7_gcMttnlVj-nsGxPucJ2mOnHKe-b98wNQN7jPP-2ukJlq38AMaj_eOZbwfgEo0xJSALZD4i9id56aWt5CSmmjh877oCf4wIf6BN5jab9VVyc_YI3SvjgwxqQ9upcavoC4GWMiK2"}' + headers: + cache-control: + - no-cache + content-length: + - '303' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:26 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_encrypt_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_encrypt_local_from_jwk.yaml new file mode 100644 index 000000000000..36d08887b20a --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_encrypt_local_from_jwk.yaml @@ -0,0 +1,249 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: + - no-cache + content-length: + - '87' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:30 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + www-authenticate: + - Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 401 + message: Unauthorized +- request: + body: '{"kty": "RSA", "key_size": 4096}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"sF4-kjQtgXhVXwujAdSkwEllPGmE6bUha87KiKNyN9XjCZmdmoZIkitbW66pK2NO5ckTpnW0aTpSNLovzpk4gmTbokbq0f8I7FCZXGTYsVDF3j6CKsAY8NJD000JDtA1SkK9EZMEjICzMHrCmEzXj4w5UDEr-FsB7Apsv9PT4_92nRQcA5mSDc1eF4JNgL1k2KYD-tYEI-YhFGXDakW0RuCAp2xG1gF8nae0nV3jgnew-Db43SlhiDtD4zdIlQgQ6d7q2aYMHZUSd8AYyJt_pBD6maKgCK3T5tdxDG_kI6a9mIYUIa3ZIlagakgnxLETQNvSOR64unFasYe8yvN1vXA5SKVtHeYXvEVqGAiTjcIrVpFt7mbMqz4PIOHjeotAuiYkxwdvqQzJgbbEIH2LmSOhGM2-eflPqyP2PFZFQUI7TDD3if6iPB6Wgx-r09g9EiGGllzD8BjZUHH0ORJeUZvizd_N_7lOGUN-tfVqScDI7w5kQJTtx4khF4MCXGZaf3EN-N_aPayPGLQeM8-ffRRxK2_dJ9YI6QUsis_ndi6WZzhRFKQz8_Mi2yKRljLW4HtytGdCWVFGcoVrkV2f-Rnbb1V6GIDrh3gPKOYgH-7gGPTN2mwUzHLa4VbkwBBomw151JSRglxvBEh9YzcwoGlOwxwk9SSXSyjd73sIBm0","e":"AQAB"},"attributes":{"enabled":true,"created":1614986792,"updated":1614986792,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '1038' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:32 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "DoCZXIeI59uDwyXTeaqvEtpiVfAvITln2WtZ6ILXoBmzXo6JqYBVxE3jagb5F8r9m1P6X5V2gpOVphGBuP1RS77M2HjVwW2NguUXNPjoDW-FP-OUoSYZBjj_xoscLOMTwO-Z46n6UoRaFTXO05JG_Shj2rR_SD1mtjzF6u2eWlMibdlw_vPX_FLFOkPjx9-q1IM53FMkWbJmeaaV6pEhxXGetACyL_rtbrdLNO-m-CO_tK8ptJx3uSpL34yJArxCIjDdLij-OgHmnpqqxACfiudTJphPNI-2-COGiqMUzl3-_ZTw_sTNRJPJ_zI04ETeFuPCULhOyu6lwmgO1p6DJgBev9WRwmwFqjRWWb6h0dnL9FAG6kKWaAqlDycUM6dofSzbz0nGMutq72JSL_JAKqCuQkMri-20GWAd_RA4ydw9JgOgm792AijysgMBE53L6v9CXRhVMml4X_if5udsCdwuX-tbQj6jdbx02urDtgNINdHCju6cf03eFJWV4eVdbXyDTR_ZjHXoscTAea5ScZ-IqKlO1F8Wg0kqHhglw3QtmZaSn1U5iLlme4WJVuXyfU0QNCsvlynknEcWvQq7sayywJBxZ050z2VlPmWpnIsniPnXdVqG8-yicOkLo19Y8nq2ZDdkH_ceQI3F5hthNcbv6Hb5_Vc2AL24AQKMV8U", + "alg": "RSA-OAEP"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '715' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a/decrypt?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: + - no-cache + content-length: + - '392' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:33 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "QeoGgqwy3bfF5mDg9-HeIRYXBFY3UokRdLVFbXyP4JPHp7opy5w4tikC1jk4toLVXlWzFnAd51fqqmPiPgytbXXDgjh7gDfkZ_HeAnVz9HmmSa9a0f4Sn8-hgTP72ki3ekoL8jBV6x8EtQ35ATlWREIA_1W6FlIyM7Wqsxrsdxn9jbDeGLsHCnGR072RNSnVCLNN6pkHM4Vwgux-7tJ_lTAr-mlkakjIyvg7Z8shf4nkH5KzV0Ieq84w2a5Zopp_BpA7gi4D2YTEzGwn9I-FN5NKPOJAMjKuBe-BoUjFyNG8qCC-tcm2iLHRIMvGNdb2S3IHnORtfqrssUUBiRKtKo8soiC3zWZosEcUbJ7Kw0SVAxBAjCYdCXMeg_fklH3WvJQSTCZT0qBoh3iZ_6rVTQBtnBPEpMdqJnV_049yCSCaLXjBOurF6cWz2zcq23EnD3ImuHraYNSoofIiRmKXdWBQWKuPe1LcIDXTRFPfXnHSMP0XUXuc7yvsmbXYySXupz5eKY4PZgL4g4eQRhRq4Q7DTB0VCpNXLFMgZDYMvG4k7E3BUJtcZusXg2sTpyxjRleZIcM5v6veMl2NU8mzIvkn1u5WmzQYQ0fLCwzXTpEWT11PETDiKf7vGxknRwIlsi2UtGZ3RNxiqotdaidLyA9JZnZoRkcXySAVs3qo8OQ", + "alg": "RSA-OAEP-256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '719' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a/decrypt?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: + - no-cache + content-length: + - '392' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:33 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "npc8UrbMFujwzmhtNXY-d4zoggC7BoitC0IpCNiXJlkR7Edx-E8lttO1muFyiZhBWR3hfDFzDI2gDx1xHt1I2Tm15Rosn-tEWm4r81ngzPZ9ymvmy25_jQ2UPMAe6r6XQ-UU8Du-5it3Csr5QP1b2wMesE6F2dkPQiK-7mmtBMVNKQEMrtCEQKT8ZCuxj4bQkMabLnq4MtICYLMro2mvTi36zdL4Cl7zFeo39qrFbKokLNYP708HVFWmABn8T_m7DiKXoX8LkxqA2xnvfduIvrM5TpasuhVc57s0cTHraaUqm2_kwH_zldxs9PvZ5CYt1JTbpRdl6gfsoy5_NtCOXU3_u-YDbnAfCtFe6I90_9W_vxFrPCOPlcRok0_78D9iQ8gd_wnNjtJHMBouALDb3egG0AYU-BF4k7PQPmJ0rBz5BBBkptG6Tv0OZxpmoDEr609cwu-g5fTcCYWMIMirKtl4AFnOVOQO3R7FteBtSduvqjJgBTjjC1oIrcaTLGYdmUrpO3B5MXCwcHAliFsytbp2rT_MKaDApT2YFjrLPIIePyIq_3DxFdPrqZsHnqsVuHustB4QwP6Eb4l2NXgeHaBRAr0T8S_Yi2jzaXjxei4xCWoeWZTxEXVF9gow1RbMgMlp9qBMCBtMKVw1fcWolqti3PMNQKxzSJvbLmeXeHY", + "alg": "RSA1_5"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '713' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a/decrypt?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-localc2101319/25710e9a40cc4d219f19197920dca00a","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: + - no-cache + content-length: + - '392' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:33 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_rsa_verify_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_rsa_verify_local_from_jwk.yaml new file mode 100644 index 000000000000..46aaa9b2f640 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_rsa_verify_local_from_jwk.yaml @@ -0,0 +1,1074 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: + - no-cache + content-length: + - '87' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:42 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + www-authenticate: + - Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 401 + message: Unauthorized +- request: + body: '{"kty": "RSA", "key_size": 2048}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"yZk30sWgiyrlP36OBUbhGdTcl6rDdvuWmOIYWhzCK6bQi2XxuQZaWDUTSoK4E9584Qz1yOyFyc8Awgj_t17_l8ZZo5f6GinmXXod7pZoumlfOQPaoqxFPNOTWDZtI-8AMiqExsoEu2kH0S22xw5a_tOrqSl4swpdkMtqM6i_HzPcXqeezL_ReSgvBLvjSbrwuzHjvBVP2OuWxX-_xSLkuXrhLYfq7eJ-em_q9MGRGuyWjw_WNU1vlr1CJT7vOkkUvK_W9dkJno9-Tjkf-ZpJyNYOFhdSaKXZZLwaOoVWAewIVhBUDk7r9yXmaZMKMHAfpI-crgOAhMX0oFKB5BknzQ","e":"AQAB"},"attributes":{"enabled":true,"created":1614986803,"updated":1614986803,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '699' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:43 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "PS256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","value":"rklQ7e__x5CM9QOPPszq9OrT3AUnussLl7rOr8_-fdc-7j9RLNJI_CybhnvniqAKz2G964YTV_x2vYxQvWvF5C32u8OU3H9axQzp1MOkQjB72B452bqz9m4ns-kmmjjr6-CxB3jnJIwlYTshAPk-BDalPeDS4WUFLhIDm8IkYG2zg1TY3vW5ytmYL8m5yYoqdpB_H4ZWhR2yv99Pl-vPa6VhcERYXwF7xnvgH-pqzdcQNHfqFVbVXvlM6-y09wkeesyDHSiwZHEZ5y-II636sXPv9D8hZOkoHFuB6WClyVXiQgtbrZFA3d2ZpNPyNBzb7EV1sVmjVKzzGw2LbdKzIQ"}' + headers: + cache-control: + - no-cache + content-length: + - '469' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "PS384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","value":"wrHGT7IaeEiSQOCPA27K9mHqtgtOXZ5jX29d2c1mQz0PTFDQ_apuDQNS6wmHO6oYEqvebxn8Wa7bOmZe-mWYOv-gVo3pEjbDyjfIS4BzvwBhPnUSnMexkrGcm-5tv3iNwUi_h1qAkE-Po5XZjOZv_HQGBI5DCN_J89Z5D7DMP2xdxdjIo-tYuVJVaxG_dvYpvRIt2JiQUqXdCFpbJGJS7rvbFEMp97u7Wk0fGE6HlVuypvpapPyHCQtzoSZLL57DmcZqvfoyc147tcffKgfqGK8daR47W1kyrI8kuubTDe4s0APa6yRDKRjgUge9KtuUARFWG2GtYBrn8TRZ5AsV4g"}' + headers: + cache-control: + - no-cache + content-length: + - '469' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "PS512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","value":"t9YMtaAWVtZOsOu7H0EV4v_tSGMHH4-wHFqCVJoWZPYhQ7GuASgMJSq_4vc8InqaNiW70ZPQt3IwaX4vlq8avd6OdR4dOnd-bNIUsELmhpMAQ4sEk6p2bDnnfrGHopRP6LhtGQY8aswFU2cD_8BQbStaBB659RnALQVjmTLjst37uAkQBulBn-ySnSjC4nn-KB6Xy8TZe61A6cJ3KXZJ6vvD0IT-nBzka43T65jO6EXE5_tdMqdUS7L-4dGL683BzIofrxceDCCYrithtfVbp5xwW6djeg7LSn7bucUe7w8w8biw6w2seey5LDbneOhrbSXzDryI1HzGVKJYEDhitQ"}' + headers: + cache-control: + - no-cache + content-length: + - '469' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "RS256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","value":"oPgF1vtxYg8x6TTq7lBh-M6g_Uozf6_f6Y59Jq1EGCW0Y2vvPB8L6nfXxbJc6eQnqdmJy_aTfUZRnY1oDGKahbjCr47MJ8vUtgy3AGAiXEq30DY9sOa-VrGkYKJwZQbcNUNYz5IZNs_x0gn8gzGNIDxyQcmR0IupSLG1b_GqFFrCPKeSaa9wanKWQHyLnija4PmTMojs3EEvmXoOPaxLg3bUtvNtYA5HPKZlhi84VDCz8h88joYj_0hibCfyhXDviXJJ7dkxOZK-4M-C_yMwdOAiFSPnudNTOiCem8bJR369pYKQCFxLWN4Qt-e1uRITDUV4bieiOcVstIAlypPuiQ"}' + headers: + cache-control: + - no-cache + content-length: + - '469' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "RS384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","value":"su0uOathq-nmAyBw81ppH3YY5eN1sGWzAWLTeCx_ZUR1-sIpGuyfYT1HByP5Z5VwDq9KaK14n0cO3u2dVn4zPyUK1bLS5zuPyA2F28aQIBXu2vNNxDgeQQifojmtV9cXnxaQGsA3i2sIKsF-X51QuUVkEcz3LK7sr3FNDwBdFB1zhnHi8d5Kw3DDQUSpKY3KGWVJFJatVNY8ibZwOr45J9sbuJGBVPZnegou12txgIS5p7VGJ_5v4DF6Cdn8SheUjpcuEobEto-86T7npt4r5EGbYqddpo4ixSpQZ7lhekWNq-vzPF1x_7DPVqy3JUuAh9kNiLJ5aomoVY9bI59Hsw"}' + headers: + cache-control: + - no-cache + content-length: + - '469' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "RS512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-2048fd47144e/93cf1f195576493d8cf03b796a1d9396","value":"Ris2fengQp0FQGHP07WCX65rsjuWaGhZZ_Z4PlcBc2ybvp5p61GdsivFYiRlsM_kbO7i19IGshZiXoYr-plIaUR9C2m-xVptc4W_sYpucD9FzUtwC_h8CtotKJzYrBG4tZilLsG3pNuqE4f47xaxHM27Q_tYsHzcWKU82GGoTbgdLZcFUmhKqEO3xbJWzpuiHlmeYk9x7ohYfFdR1KrR3yREX2vvUuFFdB2TPuhszAw0SEf4q3iDGQpAmx-uOD1mlasU8tApeFmVJqWwYJrgGJ-tcBhYWbLTvTN7z021ThP4WL55tXBw96FW9eMqjrZrbSDuDRxPRL_rHhM4nkj-1w"}' + headers: + cache-control: + - no-cache + content-length: + - '469' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"kty": "RSA", "key_size": 3072}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"y-ODCkBkLFW3xWEnV9IEkpoXSNavUSuHlYmHPZHQWYeb3NE-12fqP2DeuQkbyU6Uk02Lc-J8zRTifDqhiGGDl47MIt9jdo4-E9AkX_81Ab8Zo-Zr_yiFMP1_Z4xnJnDkQrvixKcPEUBI89IEZYKMGS_OroimnEC_PeNYqA3FBc4LkGBwH44hK24jS_IE70603xQvJDomyQnVmra6wQoBYa7qeKYEZAsBrtmEyS48sgEbMTUlbpAlQ4orqgKoielqNIE4KivPOcAeFAyE-RH5DwNG2tRpit3wB0aesB4DH-KkRlbxuTMcy9G1ObhUSPNf1sJhZbGtnecJK1N6kIZR2XfzC5rTZcUcFCp6jO67P7jSAat2HmtD6G7ZKyer5mMvq9bdXjLLmbu-xMKqfUdz_pl9_KqmyrcurbnWuk38qeUORHyf94dtH_yBKpYKHm3KWMKB39Tve6vjOL1X70dDMGX4xqyTt-lbn9P7XMHRkvuU2fz2dGIcYs9GTg8NYvBZ","e":"AQAB"},"attributes":{"enabled":true,"created":1614986805,"updated":1614986805,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '869' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:44 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "PS256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","value":"KAx-eN_rA28woaAqtWOJeID3vKL7P81iGXmuLH5jqhTQeBfzFCp6lPPoKjz-ur3XCiUBM67Pn5DJ2eM_2c0QtYzBPFYd_V4O3UJpPy-8I2RiDva_vCK04BeIvnIVgLvfpg_199UdAvfvjupROvMUcrytdLZAW8tOkQSwQHj2lYa3LNi3hQ-xpst1NmoKx3METNSG5uKIusZQX59jf878DG_2276zE_hrOXFhEA6lCsGhKpGs3jS__59ZqoMzwq2CSGpw-QeSppTDsNb7BUXVCOvQl9BexVLk75tvuPktiVbAruKhTOs4RMLLFjIPkGFMk5MHTisKGHSFbN69TkYHeUI36iZqRcT3cDNmyZejYJxtXacFjmQEn0qvGdXomUsZuR7jmiLZYiC0tHXaSlQj0A3OgngCATMk-WCgNEMO3HQmPH8rUoCORQq9aLhZJrS3WV9-qnMRZNGciB50ksrXOPRRDdkHkjGmN0NSUeAhyHcFT_twUuxWFHOz37IHeBiM"}' + headers: + cache-control: + - no-cache + content-length: + - '639' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "PS384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","value":"cF9OzPr0u1SiSz9Uccg3nCvp44auGYw5z4UXakJ2mA9qdFgutXK8MSGn79DOfUzK4PGQqe4OKqM2JGWPLXlN4kH4zMinpYnKMe6RCyqocrcRGy9Yhxe6yppj5IniWy94beiv7xi1Z0p3dAUH4sSzJmPzYxcl97yei6K6LmWzGpklEeoMoaJxgnIRMaKAGdpWg4qagUExf4tclAxsWZOQJTP_Xe1ZBudg6JhiAQ0tWPvHyrEUhDdsZX7SOAPwgmdALEXFNWRIF0wRL2M14-fzXsiUG0nG_g5eROKd8ZuzGap8DIRBVPnzWrOFY7IlTVqnIqLbvwqgB06pz0ulmdp_GK2fFOkv33kqinf028iGtfW5iXyR2uD8V_LddRxS3xnBGguDwjJ87yLSVdMaRBWFq68DAw36kVA5h1ih6BK8XtMXEUBlOo9Uo1z4Ms3XtkuY70jbCoNkDq-pi7j79q_97AhSojvhrIxhnXmdsxpmsChbBZAitOOyq6CIvlUAB-gC"}' + headers: + cache-control: + - no-cache + content-length: + - '639' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "PS512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","value":"JbSIqWs98iz8M3MWh1f_9FK6VNBbjPTVqoGBoesB-u87-GAZuWzTqMaL9J5ETN2HO4rJTgSB6F-glIXrwtq7jYhHxxrblyVR8tFGtiSAmF7V72cbxBFi0tgp0eeIqK3joDUmdC0AiVfCAxSIYkD9lSz8Ow75lmuhx3vQXvKJLMbFkNFi_3N7FYLT7BVSGkkydujuyVN8MezOKaFharwdLc79fRWAIwlHB8qGCXoYAkrPG4TiDp7gFcIR6bown9nQ0sfxsrCDCRvrg38r00P_TNYwEY7Vi6IeT4FPpJtEaaoHWqS3U5It-SH1L4I76b4U4qYo7CO1C-2ghEVUDtmUq2TtiZLLjkLya2Ri61_gtwptwTE360OzPpgsBqsdDkYkLRM8L2S0ZVEyL3Lv9ikOL3QOCc3wjIV37V9nT3ggmwtfa70p3CwQPGi0P4MpHB58u5ZhJjtGnGfp0R2VdcPD2HcnAqgYg9nHOfVh1MVdm6mnNXvSnBldaYKriEEc9qg5"}' + headers: + cache-control: + - no-cache + content-length: + - '639' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "RS256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","value":"J_4zTcpP6V16Nmpx5YGY7_NbHfg77GfOrciK5UsJrgNUBTMP1qCwc7nvSekVooZfdDJ-JaB_svWoKyyJBIGzbz5YcsHCAKbsjrNRyA6MFcIcNf5M-PiC02sdcRgtf5X0VXjVRG9Vksn2gg4ZbEf6-85G4S1yUoH4CwS4uVqFGBFaqiFy5ZMJItYidirpEHXrJ-UykeM4wADRRT8qmtzAQ4CzuKjqT4p5QfBfLtYIFEFVdAFU0ILOZWnq-dK2Zvydp30Tc8k1IfJH_skQ2xr1H6nEezE8byXBMjHvn4k-LPJkHnkvXzRtl2P-XPtrVB51g0tlQBWxpIo9orygmMAjTKkVjDC0CeN4cckQpKyVlmiVDbN1n3zBFET9_aq3nGXy6MSG7vX4hbKuIiTGCEKAd4aSbCJGxJUxdGUL1V28ffJU00LP61csur6-zH8_BdFHsGp8YFv-wamJzkKY0Os4MwU89ZPsbvE8nuo_zyzYwlOx9Q-Jm73OOMJiT7aR6RvM"}' + headers: + cache-control: + - no-cache + content-length: + - '639' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "RS384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","value":"yTl8WVg5hr6tzvQ9PM9RX4dCy6K5ijeMFp6JwfLPUXBewml9k9ioFAOtDoT61kuJr-MOm5qi2aOrplhhIth8OkoYxuk9m9SpFMwzMFtFv5A5-rh-rVV5xF37r4YUHICHasgJzTr_oFEQXRP3Iw4wpuaBhGnNAoqZVeGHn7uhFVlK6clHB3sMxkvIPsLG30DaVxV_TS6FhNeMc1hDPPdX-Xgx6b6Q_Zdg59NSTxbO4Xbtkhv1PHQWJbzN8lJFaJZjJY9hC-KrOeTjNhEd0XqIxwe8viyrX4Jkvk2PUdixcx36aYisZaJmzKtApRRv6h4_vKQYtU2ZWLwf0JJmAPa4wnDK9H81po7ZChYkpMOjc6932FKVqaXPeTq-FwJH_emb5skj4d7QzUYmYiFZIBl2YKKM62T_XcXuU3sBLtR4-7OylkI80FCR0YW6gnIPxynXYizwEYEx7tY_rDK722r5_vOiTTWnp3lz8SkeYyvStMbJ8VPzrU1I9xy_4EIXYGvS"}' + headers: + cache-control: + - no-cache + content-length: + - '639' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "RS512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-3072fd47144e/86092d9c420f4bdda6de5e2f9b125a78","value":"FEaWrEARG7CIyIx98lGMk63a2sWskE9scOheRU7bqRGb1Klc1x0jSzGfqyYNxLkktqRs5rz7653bGdPW8sHsYz9VuJwOMtxX2BtwqHegCp7u4OFkNxHHZMkqjoL0HfOlhH-G9teQfaCQjBr6CaYoon1299v_jT9lp0CAVYifgwE9fYVDkMeDQWSJMRuChE0X2Gan90DOAm2jyU7AVYgqprzRLUsh9WokMLM_g8Mgwjt8HCdmuTIh01STNYlncRxtcNSaxsYYeWXpXIys1l3w2Wk8jHQtfoxjqFqnKIP_Ji1wW8isPkLI7BX1UZOfEpwdFBtDlVI9u57WyIZRSP4lU3V-kNMYCXexWu5UeXZlTpO4FWW9gMV30_BTzgtnuCPxpLhlcjs2mvjI6Z9wScb7eoB4WoYdIm_wicHF9FiIqeZEg7JpesRFxecqqtDxIziiVW_1iGjox9QtIMnIkD9sR6Xm2VauTc4_2auzui8XxDHEEW48Gv6-pqCenky4rmsY"}' + headers: + cache-control: + - no-cache + content-length: + - '639' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:45 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"kty": "RSA", "key_size": 4096}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"zXNiMb6_Wd39ij9H2isTKJpJDnCSBALE3Kihrx2C7hq0R9p2NSFCQ4KT2KCFJZ_aPZUv486FclymgbTa3RWpRlFD7MoqRFrdtYjYKIMME4iBtjxZy89ZHhlU2O7JhnYYzay5GXw6ec-ZpLOK0D99rESNeqrSHGI1Jlzj6y8Tdpjasjq88On9bLSVTdi6le8KlmVzZAlK5GIz4U5uniE77-WUU2vGfF6TEghBpWNZ2-1q2cQboceGx2L6gQOnkdtAkwvCctQLGayooojVXZdpVpr3vamcr5Pd1t6KXntekvMZhJntPmfusX9J0Dd3nzSEGHgpMWvtf1ZkAIRoBFzHij1w4w4Sxs9NzFGebQNnUYzx552WLnjbEV0PX9td0BmwrUIOAWJfw_5lGxdDfhLeDLnJAMbIVA4QxiCP8kSfwV9sWVxpArN0uwBusq6Aqv1bfcmuBCEPBijnP_PGQf4PG_bjvcds5DQUXj5pRxJMUNIOKHy7R79ymWvbQEz066MmHuVwbp0aPatcKhhA64LcXGCO1yASxsmMjSxsYc1RvoKEMesGgcwjYlyfHZr_wkTkAJmSwLC7TTbf19kSVDFp0C9C_aULmWtv7tuI6lzBnaYClPAhG4ne1T8PcdR7yS4gdGMnMiUL9d8aYRVDRPW91DoxbxiAkeU3LOT3eoOeEDk","e":"AQAB"},"attributes":{"enabled":true,"created":1614986806,"updated":1614986806,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '1040' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:46 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "PS256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","value":"AZ7a9iVelhU3dQZHgePpj67HSrtQuPxMboNak9yO4aPY-6Vysw78keA_dsJIIb3Q44AqA9NoCgcqDByi5d516uLeNgVydvpGP_jP8Key4nCCCYcJdnT2QOldE7-qnIBzkCGAvhCuJpDtWItATodzcoUJx4JbCeSO7vYsTtPJlXdDs8-Ph83GAgKV1SS36xEmEIpe9L-f6YJwn0Ix4wyxg5OTSuyFj9p5m2D6vvyMrlJjbro-1bnmXFChTgiE0g0oatJeVRQ0dzxJ8Xm_seJM4ag3xiU9ALj8ImDp1WkKqw6hIKIOscSDOxDTR1tYiHGVoSMSZzCl_FlUTFK5GdUkJyTumfoXJxuTK5Mnd-uMaz4VWnw6Y-ZUiEalrfg4jGNZSlYDPVDntiRVYem9bvpcUf3DTISJ5hgxDbwe8la1WP2TIqiW108S2vnnCpCEaBxcQOxRN4ffaC-5cyA1y9_1rR8oIoCaZmH1Ryi95HWzKRtH6ybUFwlKvmx8TM6X_-yBgqJnvofT2v3L8kMh7Jf85qqEPgy0pQQfhocpYzL8C-RcVT9hMa_oW6x3W4nI5LJ7o75Dr1AXxZNkglzuiTMQBpcRy4kryYGCW_HOxRfcVB5fPXUlPp3kp_3BZDivjwtEYl7JRAoMUAp_LbWRH6li8nlo3YJMXGZHPjNcyQhXANg"}' + headers: + cache-control: + - no-cache + content-length: + - '810' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:47 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "PS384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","value":"RtPgxVV4EGQTfB93GDH6rLBj2UjzQJOKX-y0u-RbmmVoaiXkwQIeTVlkJmd06APgQReAbpWf9D_HM0sMyR2Bp1HvsKc2zdgyL2MK0JoShbxyMM0ozJ8TPp9jW7ycNTJJGZb4skyrS8fH1GL9ehRAJ4XHqz1kgH21I3yftuTGHiJgIyc_nX4LCqrEjxKk00_UDNz_nZLHWUw14OQU77mr7wJWDIvSpnbYG0wam_ZrZU-0_6UAwrGezd-gw6SZUiqA3kc7HODpZ7pAISgZZF8SqUx2F3IFcaZzthSpzN8e9k452n4jo3oaCUvLWnyHP9aa1bDJVaysxKZ_67j2ULR1oY1SKL1j0CChO_asq2Fe5ulGNsUczS8R6Tkg0svgURaOcOTbbpJK4x6d2C0XmX_96YBSl-p1vjOXFzOitCp0xVxSxhED0EN0SEMfTw40bx6RLDbU7ctuZ7KPyen34-F5JT3BYGavkJd5jw6TBpbluqMd-mMTCAQZC3D6-0xZtrXxH0R1CA9rMcN7TvR44934NXFNZS8chWkN1JuHYZpMojMenKYgNLMpOuGrSBwRJcrLvB8ClxumiPX97eszyUzj09VApRwS0qPQ84O3nUWu7Gk2PbBWR8Q0REqleSTn5zogNYEIR2KS2Cx3brjKzRL4kNLQeTrC1gYWmsqvyfiujIg"}' + headers: + cache-control: + - no-cache + content-length: + - '810' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:47 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "PS512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","value":"wOb3g2sttYUvpz3bAyueUUJxVhbO4P-zzgzH91D2wrUKkOf0W4k-TcvDzi9DCbgS9R-U8sZ75NzVnlAK9AWJTZg3bfUDilDypTs5mUW_aPNiBsSQC78F-CUXQeHz_eNfAfFTB53vLOSFpnfjsZUj7eGyAKUNbqF_Nt4pcu7OJQKMEpLUINhuhtMvXBrhSR8LzU4ekzSEpThhYmG7I8PQL1EBCPwOZTiQqcPeojHO_DvMo9GRKfD_m12YKq958TNxl0GGMhBgIxU0QOu8T_ag5eHMcYYoX4JloQneRe5RVh694Kr5aFs8GrkP90Qv_Ayxy5jSAhyA9Sj4T7zuO-wziwCf7tPEUnPINYNj2zMV9PpWDumfwNIkJrAO5g4LBROXAnStWTTLk1fhLM0plirT1lrSfFWw6prT-cW_WNKVQ4M9ezWQPxhBi-GC3b0XJRAwUh_fRTqsJ2IFUPBYaqWYkyM9sVr43JXmj09llnrxh5LYui1xYuAh6LUTp7q-i2-QNcsJqeUaM20IaI21CSjiRTwLCVAI8SWW6lMDcG9aEBhkC7_ArxsYdZfiTnmBcZkF0pzTWJPmEo7xyniUZ6dc3zq2y15YphS_PbQC9gjstrGj13aTUZy45Szc8jnvhi1KOJRWzPWNoSZCUqdOkBdPfUxoKr2YvQHsQhbc_8wfLwY"}' + headers: + cache-control: + - no-cache + content-length: + - '810' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:47 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg", "alg": "RS256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","value":"utdR-hUyHrXVlycqlxR4bgt4sJ6nyZJuAJ8LsBKEQHW8sfzcPDdS7lrSUdSXhQVzCbAqTsCzD9eUWxLu1wZ31xoIip9UUFeGiNVmcnmupKw7POKlfLvjlVj7Fm2CB3n9IMozB1IygmbItJl9cFmX_9eDTA2Sob9ztzDD3-b1QyXq0VhW5NfkoGG-VInPvo9m3rFV24LBuO4LkvlHsULjUkPnrx8aeBOWVBIvK3eNfmIKk0C6GmQTMaiz0ee9bPk1TpzMd_eq9nKbzI1uhsYPjSPlx78QF4FL25-AhWheqjrKZmIfklpeAZs4CkkLwGknb0DeJFOY-Hjkx4WxHKuk6Yq8Yxi3ov1W3anfUOmTDwpxSMv8L3IJ7u0fCvETDp4ReFvU5YM_lAO91Ud9zcRwGGo-YaKuuj4LK4bdPtwzslmbhLgmWmmU1LhA_EWg5X4qcvhuBX3w-gqjFAfPacCmsUFvT7S4eN3TyZMvric78Y9pSHFYDoFNSPO9oDV6vRK8j0qEDdzqsYUU3ArAHp13ZWqNHYmHAVmgdF7gEuZF-6tMtu1YiCzRxUYS9wy50lOBAm1vncKs7WkysOhQJYGKRc-FYvlAG_jP7ecuuRXbeZ1fHZIqIfCeEuEElTrwox6gDPdoMa31jE44tnY_GD5Aj1ZxFDHnB-_jMfB32rPq4eA"}' + headers: + cache-control: + - no-cache + content-length: + - '810' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:48 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB", + "alg": "RS384"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","value":"B4-anrRSO-TIlGvLRzRQHqKmpNOTAwaKmotLjCiOziiXDvS9r7mzWF7lka1li_k1de26IyngD8YburbXEg0EP6xqRfQUrvKCyk_xhPBlCj0WfnAEiTjNDL_rPjCZCcYn6qL5aAozs7oN8SYH53iR61cJeOfyBs9rNoh54zXa5Hs8MPZ1mfDPIKqaGVAgHsfEvbZa1AQ6MbWYOncLwhme9UXHxfttmR5JOsTWM4cbH_PNN7AZBRIRvQdlZkLharptw0xJXsMoLnyu-9u5SCMy8LvEQA7PFQbXOZcawgnfF0LnzLeSpd2boKJREzQZ_2WU59yQ2KOGgB1NjeogVh7tWoTRNb8PlgL4uUfglXKpbrQBhPLrsfTPyAdGCa4IYQyHCKppLoiUbIxSHmU3qAJi4gdpUihUl7D9n73YB5jDhA_OpJt03IfqQctCl3K6oofS2h0fLOZahcWSiANB3x1pjW1t_DTw3n-yk86p08Qn3ixTj2uxalu5u58x1hBJvz9pdgawGial-WWgc-fBokl7ZQmyMIhGK1u9tzH6D9CWAbxNkp9W5zzsNTfHLW8Gd1XoDctGdDe51z7DJdI8C0O06Meozu1BYGEQmIryBTAgRTii2VGMo4_ftqGXHHimYSATXu0oPrca40l4KXglLW3RtSmSb8gKvipzfTv3zHumEQM"}' + headers: + cache-control: + - no-cache + content-length: + - '810' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:48 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ", + "alg": "RS512"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-4096fd47144e/4cfe37a45d1c46158208f9bcfb19dfec","value":"yRtarVmxe7K5UXCTOwByyJ3fjbJQQ0aTz2mqpY_jiK2upFwHuyPbYJ5yF1OJ9Qgbk9EQXuYYwfuLS4Q--BLfloDDV_9cEHQ8MbGddieL9oD1_nVvq5p2Woaxb2NFDwjhrlwOl3u1znRepVM_6GdYJvD84Nu0b3Ez8w71kBA_xjz4Nerplm9N_N7GGkqGCL-dYNq_nJi4grQp5NAP3u63e4gQBvIAdDQ1sg2W8k3U5I3AWZGsbEo02VMUXi32HWh3IpXeyZGVbOi4bumLS4JTLqMXp9tGbUPteyhjuceJY1fjs9dUSjPOVS3ADZpUsapaHm4wKI_6U8Og8_uZ5FMY6MIEU0X1RQ32bDon9hBYwPSKzaZPmSuRO0ccMJ_goX6nwLODCG2qYy-g77ZTeo7eqmCrKXlZ6iCnAF_PzRkysRh-4J9M8YtH0Td5iZ5ChjDYYYGvHB56TqPDcaMs280RC3pdh6UwgVNFkZe1hOqKL40Bipe8TmuqTtYWz9s6Q92iaa3yFcKldl9kJZzLir_81zUQYKTTSeo-3EjXQYPXi5MUl4pVKXcZhb_ZecBHz6SEfLP4zjYPfHzdPTA-t6mumAuqxoSI24DcIaOlywHfrDlN8K560GBVOKj8eXPFR4bPdXChivk4hujgyC9wr-s1YzA05jat9kjIlgetZINbnY4"}' + headers: + cache-control: + - no-cache + content-length: + - '810' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:48 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_wrap_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_wrap_local_from_jwk.yaml new file mode 100644 index 000000000000..5c7541bbc8e1 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client.test_wrap_local_from_jwk.yaml @@ -0,0 +1,249 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: + - no-cache + content-length: + - '87' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:54 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + www-authenticate: + - Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 401 + message: Unauthorized +- request: + body: '{"kty": "RSA", "key_size": 4096}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"vc2YTpPqvzGRaGET6dZcj7j7bIFf6x77HFiRgqFVM0ehUSoaYsCmaFohUG5Aud8rpd0FtxDwg-2CYNluKwbERgZL6vUHNV_qzn3HK5oYUoU0X7w2zbUFpNI0K3Aa_pF1z_m73ruEj_A0PwPCS7VfKZ0stsO-HejWVw_OfzQ9IDearkM4iYhVRv2ePz0MLTlr2WDUzaOCzHJXEekKekyX6jwbAxlCbi8ODOZlWbZIv7plXvsty_IOSIleN5I0sbMctOdvpJlxpZusEPZnERSA7g672aClgnW36NnOlsq8ys0OmKtbmY_q6aHSiLc_204LwOrj6KdhljLuCWrfQA59vqKLafHF2KzINdSRFETQMs0WSF1Qj4QYUBsMzbtDJKtiuwwPSJFjdDY4GID6m7UttAAp5UWzsY44NnLGdSE3dxAU8rIeCimytINyVC6df-dGt681Tbu-kbIH0FfAPHHd11zmMcsDO1zOjiJPa3vd-TT-On6cbNI4gVg5F8eN7-pIzhMP4nCZAmHgJcGX7HLInlR2ZSWPlZLm98qDKV1hSbAPBVG5g-ktj13SBSw0qzxJPccbusZAgEANMPgwnz2OAbpjLS5FY_LtozkrIFH1sTtxEOPP0D8bNjNWvg6jF4iaIKedptadUdlWAYh_wdThRIZ_qxzjY1SG_F67SkwtK5k","e":"AQAB"},"attributes":{"enabled":true,"created":1614986816,"updated":1614986816,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: + - no-cache + content-length: + - '1035' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:56 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "eFnjbF8jJ_LancuHBW5ZkxTcOQ_KRh4ZJKCdQDaLFe9DW4iK6rqzOGfQSviMmpBNloBYQl2snO-kWNConmHhcuKHjgDDLN1p94nq-GMEUSAFciA-KJHVgCuJeRHSonD221VjymIV2YiybkqMaMSiIcfyoUo5sWj-oDNtcWLsLTwSoT9byXvWgniM8LB8ow2v4x60ikVBmWyLdWWBouxfZSPpEmxNgcT8JBBLsMbDT8PoOjMuX8YNsLzG40MAWgHQOvZz6-p09XCg_3iHKKQ_4cVUFFRKOQflLlXfaej9z0sVwRsSu9F0qbmKPk-fZXN5wAVKbkwCeh-ci_c3tNeiy-FsuKynFoNj_PKneRSlzatJLx6EA5DK60HBya1FTFE2ZDaJQ-H9zPgyhJ6pV5k1t5IRZKiE_pDzpfPMCCSsZHaDliKH2RRrUxSraQWOyv9MeTGOYKjE9zSK3amJJd7qXAVGJmR73nMDnlwfyAivdCzXi1RdHI4RldpDKEiqXjouuA1rd8KC8XhtgRkuD81j_7hND1j0uxXKWlTH6p5qw8nwucfJV1opjtn4rrBG-WVWn0QixU4FMsmI2KaFOvChh9X-0y7155ZvKF5tQaZBOR0zKYibIcOiz3_o7p5T1F4rYe8MMcjj9YEsPEen1MSf3K4n8f-gcDNgsGQKfNvQ288", + "alg": "RSA-OAEP"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '715' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2/unwrapkey?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: + - no-cache + content-length: + - '389' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:56 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "LgqgJ0JRW5eh9n_nrM0FJMC1gmliaJZuDaB75NMQ2LawQU67MjMp21d0H03fgEeKOlvlQyWjR4aPmcNnou1h9upOFL6mUBLposi9WMfKVP8wIsQm9hSeavF4Q5Mzye0_ZQXj5P2Zzhpxq7HGT31wrxF_LEZGAgp6mXVkqFljdHry6O4oc1Fl9TKR6kXP7_QUicrtCpLLgzvDE-4okzwNgbVGFSJFHiHGaAo0-BpotrbCKnHSkZMgmVkNhuYiH_m_Dlf4neRKFNRN9PZMpWGZ7VjKgDY1kIAcq_7ZFy0ITW3hOJaHrpqxEKyHrbWAU5rKXJcEsaY58zC8NZtY7bZqNNcBsnqtQY6CJOCqjSXsnW5J-3Ib07Rp1r64LyqGRVsd9SVGvleCH8ZKiFpiAaa0Z_r37TIBxlXDaEFmi7Yxo62oVBPoBPiZBrRSjCNi9nwQHRiE3wrXcld06-HNmqt3jbd4zzTCfk9IGvZQUs6Uxap1itnE_tPfJPnxzHmaqPyS3X4LVAqRDDHar6UrZnU_aBz5xkRorc9yf_AYnUwspgqRsWDevA98LtdYPOPYUkQt1qYXcVV3kzW28LpPJIgwGM9K3oz7VH0ZIzMkUMg45Rz_kb_l8KiVjLaqXhagzhCKjF3MZV4NYaWP5IRucG1_kuAJ1acubmgwoRFkKJpmRXA", + "alg": "RSA-OAEP-256"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '719' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2/unwrapkey?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: + - no-cache + content-length: + - '389' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:56 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +- request: + body: '{"value": "AZyV13GhF9vAOV8Pvpq9pJdHpBwgCe9pXUMT9SlUwVnp_EknVg571rcjraiWqYe7yTt9EBv1uZhWLXVAJ0FjtmEC-gsoI-RhgI8lzw5zhYkwKlnkz7C095v9Yy5X8vCnS9pHxqpKW-MmkFmVvHSsZ7KarRV_OuHIHZPw1jtIn6ZT_xm7EfY8ndh2DLirsgtQPi95kaJeyz7Glql61WEW6S3HfALFwmUF_3B7_dhZ4qV6zYWqUqatUM1cLKF-kfby_xp4cCc4Juyen8h1f4aTGkFF_GJ3kyOYiwcJGuI3O6ti7q7JRC6_S555Fm6PKs3rYb3feuqm2GsAWOGQbOn7_jHBogl1peqhCwKA1W8S6CafDp75jqOag1EckJEiCCVgZ-XOzdRXkGdLEtOY10Nesu-0HiHESGse2QR-NjSsNmVe_WfC1qDIsGKY8O_OvXZGA8sGmJYL123SDogr3-ON2ZE20oy2uA5rcXaZVw-sUwlPWi1lVdKaFeYNssRwDAVns6ZZpBpswmNXc08iAUc1FE91zrWcByyr2HpkSjAgETFk1d0xeZB8SZxuRfN_bRz-mVBsEk53nDdD8fC4zAv6BgWQw43fBSuEr7FxZR333Cp9HR2jeZYF8uZ0bfqtP5Zpm5T4-24LNIBhz7VNxfZNDwYQjLgI4NydUL0MMHnX-ks", + "alg": "RSA1_5"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '713' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2/unwrapkey?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-local897e11ce/10caab44c2594ab289d8a13c7451a4a2","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: + - no-cache + content-length: + - '389' + content-type: + - application/json; charset=utf-8 + date: + - Fri, 05 Mar 2021 23:26:56 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000;includeSubDomains + x-content-type-options: + - nosniff + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: + - westus2 + x-ms-keyvault-service-version: + - 1.2.191.0 + x-powered-by: + - ASP.NET + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_ec_verify_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_ec_verify_local_from_jwk.yaml new file mode 100644 index 000000000000..8b5283e7fcce --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_ec_verify_local_from_jwk.yaml @@ -0,0 +1,302 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: no-cache + content-length: '87' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:04 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + www-authenticate: Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 401 + message: Unauthorized + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/create?api-version=7.2-preview +- request: + body: '{"crv": "P-256", "kty": "EC"}' + headers: + Accept: + - application/json + Content-Length: + - '29' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/b9df70f31adf4421a9716ea42bc93e4c","kty":"EC","key_ops":["sign","verify"],"crv":"P-256","x":"QmKAGdZ_t4jtNYhpFcdqkOWqImIFN8sRp4suSW8IfvA","y":"ivayZMj0Ud-_3WUv538aQZItI947s0xkSIjPBfGqM9Y"},"attributes":{"enabled":true,"created":1614987064,"updated":1614987064,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '410' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:04 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/create?api-version=7.2-preview +- request: + body: '{"alg": "ES256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/b9df70f31adf4421a9716ea42bc93e4c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/b9df70f31adf4421a9716ea42bc93e4c","value":"JYQH5XgzvEgYRFNBQb59lZZYVVzWks4bK2q0krYDrz_BhndjYOynO2Z7e8djQG07Kvm5vs_pBFSYzJvlb_1rig"}' + headers: + cache-control: no-cache + content-length: '213' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:04 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-256681b164d/b9df70f31adf4421a9716ea42bc93e4c/sign?api-version=7.2-preview +- request: + body: '{"crv": "P-256K", "kty": "EC"}' + headers: + Accept: + - application/json + Content-Length: + - '30' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256K681b164d/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256K681b164d/0682c134547246f59a1394dc7e5ba53c","kty":"EC","key_ops":["sign","verify"],"crv":"P-256K","x":"yWmEUDjKm44KGeGzFvEES-Pq9fZU_lReZ9VPA8sXJ6Q","y":"Bw_fxg-5PYvrBwS2FqGSaP9m-3OqROfCWsGf1t6fp10"},"attributes":{"enabled":true,"created":1614987065,"updated":1614987065,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '412' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:05 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-256K681b164d/create?api-version=7.2-preview +- request: + body: '{"alg": "ES256K", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '73' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256K681b164d/0682c134547246f59a1394dc7e5ba53c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-256K681b164d/0682c134547246f59a1394dc7e5ba53c","value":"oGDNGD2sQB29TYwpKcZUu-inCsl4olKdcaqpHZpF6ih4nc3W-gZv_jtxr3r8yNcQoPZLrIsYItKAUvG0RnaKfw"}' + headers: + cache-control: no-cache + content-length: '214' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:05 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-256K681b164d/0682c134547246f59a1394dc7e5ba53c/sign?api-version=7.2-preview +- request: + body: '{"crv": "P-384", "kty": "EC"}' + headers: + Accept: + - application/json + Content-Length: + - '29' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384681b164d/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384681b164d/2b8b4083ea93442c8dc1a61562730f9b","kty":"EC","key_ops":["sign","verify"],"crv":"P-384","x":"z33sExmi-UGsTsYKT6G3JQO9ZDKeqxLx1qyHXY6q9zJEDwKQqm9JZfVONno9blZf","y":"QmETaqZgy9_xbA8TDP_cUHo4DrJAfNO4vurEJe6Ou_DFKn4uRt11Gc3WvfTp2sd3"},"attributes":{"enabled":true,"created":1614987065,"updated":1614987065,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '452' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:05 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-384681b164d/create?api-version=7.2-preview +- request: + body: '{"alg": "ES384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384681b164d/2b8b4083ea93442c8dc1a61562730f9b/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-384681b164d/2b8b4083ea93442c8dc1a61562730f9b","value":"UZeFbLXSPEMO2tJiW9P8G9fxRxNVKnd1MxjHJZAsubHwuZO-jehIPyg3Iu6XqWwwQRbglEc2qYzRszUp5xfn7ons8ssqgIUM-zYr-iV-_gRkwmR9cFw6pVUIZz90eyWR"}' + headers: + cache-control: no-cache + content-length: '255' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:05 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-384681b164d/2b8b4083ea93442c8dc1a61562730f9b/sign?api-version=7.2-preview +- request: + body: '{"crv": "P-521", "kty": "EC"}' + headers: + Accept: + - application/json + Content-Length: + - '29' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521681b164d/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521681b164d/75e9e856eb5e42d4bc1ba017926f37c8","kty":"EC","key_ops":["sign","verify"],"crv":"P-521","x":"AVcVB0YjfZtbCd5vB3NCckmHjaircZKLmLRViQLZQMHbDFXobmJVim7PQ8kTccr7Gqc5_YIuWGLD0MRJz3aGUrfT","y":"AIRMBE6Ko0VsyvkVMkiC-NXo59t-ZEXkCel7nt5kXNVFhuKGNijNUMPdhyHU7lGJceLY9Hwb9znu5TLDBGKC80r_"},"attributes":{"enabled":true,"created":1614987066,"updated":1614987066,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '500' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:06 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-521681b164d/create?api-version=7.2-preview +- request: + body: '{"alg": "ES512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521681b164d/75e9e856eb5e42d4bc1ba017926f37c8/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestec-verify-P-521681b164d/75e9e856eb5e42d4bc1ba017926f37c8","value":"AJaJZwqUTowjiCOzXvNzoU7fcKtF-7bQtUEXN93gh1TpdUcF2gdgSh0k69I9Ud5rnydOiNbXGS5EBBWjKySUDDHcAV3J_gTIfD_EkJonL5-PhM55xwi4AWHkn3TTkggwVq3BvqYCEuRaA0mxv_epjRSaWFG7Jqx-ze3ndoN5zWkVApEt"}' + headers: + cache-control: no-cache + content-length: '303' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:07 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestec-verify-P-521681b164d/75e9e856eb5e42d4bc1ba017926f37c8/sign?api-version=7.2-preview +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_encrypt_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_encrypt_local_from_jwk.yaml new file mode 100644 index 000000000000..51efc3cda4f8 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_encrypt_local_from_jwk.yaml @@ -0,0 +1,170 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: no-cache + content-length: '87' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:09 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + www-authenticate: Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 401 + message: Unauthorized + url: https://mcpatinokv.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/create?api-version=7.2-preview +- request: + body: '{"key_size": 4096, "kty": "RSA"}' + headers: + Accept: + - application/json + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"1ePr3emv4M6rdPhZc4XApIrSix2XVyRco8-6SRvKC3VddELrlRyHC57ozCpJOMKg9PNVFmP-UF7Rkd5IOSvbzHdG9uXOjYK735b4tVOdNqzY145SpS9Mi2RvRyke90aymcYHxWnhKOuHwHR-_Liz605SIpYy0iA_1lnbwXgstryQcnXCqDFur0N9Ehv03PHAue1FFI6pM4Pkox49LAhV6WO-qVs4kiyXTv6TCdJnM2BQ393MV049PDwAggce6FuxoAsHYFdWBxsxneRq1ZtuPk2z5UjhwzArOUaMoRwyWWKuu_mTad3_ByjS7YvALSGtfAyhGHaJDcGciRLLt7lA2OL7g88ai9ivAr-eY0oaFJseYM4IhBYDqLTN2mwQy3T3A87mEe1KCxH44mMM0zZKukqiCP_pXpmMw25mHt_Zsz_EQo2OdBhWlds8DuBVVTBsot7RPD_4uU3cmvSGFYixEKIAuN790i0QW5vZcDfz2g7D-4oPlqB1Gv8Aa2KpuS_4efeVWiNWX-e7N64ouUPMvUf_zAjpJNqruXNHiUCXkB_m-dZ9Vi6Ic1yc2RVxt0f5GglZX0HrG8CkgJutwqRWy1YVgLtEn6Sl_xHYaP1KSOXNuTeufUIUM9zhxl7fEF5E9HHqtzOw4amWfdywTTzHdBk0Tbd8aVd81W0h8x2muEk","e":"AQAB"},"attributes":{"enabled":true,"created":1614987070,"updated":1614987070,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '1038' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:10 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/create?api-version=7.2-preview +- request: + body: '{"alg": "RSA-OAEP", "value": "HHEmGnbNmhnJQnLN7MZK0atrshxhWp3BB93ihCj5jQpMgjZHzkSiS5YFtxF2phwCKfW5J7yP4nnl4zedSRAqu_cFsnUB2ugPg2KOlnupZt9hhv1z5UbReyQnkblcFc7yFu0zDz_CEjlRKLAlNt8sbz8l9ScqV3kmJzFzharLtLZLznmcEmyNajscD7eZlQEzcCTKsw9aW-EEV-UZPeW8p54Zr47r4lHaKJHleZdD7yp1saKFYAR8_dHwZxtoP7jr5040NHNS2XXmEa9_WT8GpoAm68lJgX8vjav7lqffrNoTcTCycDuRtK6-FcS06jZZkIcvvGVey1wjXLawVcRE58qtDD9UxYoYTyHe-TLiBWygA_PmkCvF4NIQE5impq1wZFBCmZRPJqvl5oTKwFt-LYIUSWXABiN44JjXuHPrv2SZi7lpuBIX_fv6sbU57bLQ2UW2Tp4XlTVFkSz0NQucqpWJ-lf5koWi-PsfS-WArhd2nS9J6lYzfnIpn_LTfts-4ZtKkeMZBGeSbJaLa4HO6PmF8G55k8UXC9C3p_agAf14zS7eL4Efj_FfG7LvQALQrXQ71Y0WAbm7EtBfRY7H0QT3-ezu5wwxxGAyCFt9snaL4Iz59wYAHnHCJOv5nDt8Lziq8f3Jiqo_i4VwCKchbfzCMTo9dW5x5DQ57MVck0A"}' + headers: + Accept: + - application/json + Content-Length: + - '715' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8/decrypt?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: no-cache + content-length: '392' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:11 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8/decrypt?api-version=7.2-preview +- request: + body: '{"alg": "RSA-OAEP-256", "value": "s2hYkL7h04LjtLXAy6l7NpUML1WclX0hDzrBTdrbs_ORAi1ezKQhzCj0hRFQ4_s43t9VJnma2L8rjOL2ekrGrx5D1M2S3wEVUVmev-KBF1jmD2hZc37O-G7EQutvUKPB3yhGjuvfiUhYi9zR2J49DpedNSPT5OAxWdQkfIPrD7e7KTxau8rStFeHTzBBKyFmOW8FWPP8rWGN8tcdTKqbZl6L-3P1HodV-tq7F8i-kh2PEB9UP7ziPp02rY9nNwkLPpaPNEGE2YzgEBACZ4gpJ3h2-MEjhCnGYpmR_BFOwwuTPGbBT8V6SHbtWoqPMeFQ3XT6IvvSwwmq7e2NIkC0nO4Rw_hpDdcbR3IhVNv8pHraCrt7X-Wf2KL6vsdKfyIpr2kTyd3ZZzs_carH5fMmVsP0u0mNaCxT2RP1zEzQ2ns68KAK_IqsZk4MYIZ8GUgezKhSZ9Ql1hWouuuqexuItTjrvcLJeSnABJlgpRGfMM7ezmSnVckkZ6nGNX0vxK3s4fGL2xVEVwruQCY7_xUn5r0ylcQ-Qxsv939Oxjyo84dQhmkgEeXQ4One2Zd3Ch_PfOuYRpXgCIkQeLpdNXlxeHH0s-8a6X7CBosOPZZSby74Z_0ZDJlkmc784nyAQmvYGcQ_XI4ALz7m0K9SDzwqp_BmO50fi5FUrhqShankx7E"}' + headers: + Accept: + - application/json + Content-Length: + - '719' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8/decrypt?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: no-cache + content-length: '392' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:12 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8/decrypt?api-version=7.2-preview +- request: + body: '{"alg": "RSA1_5", "value": "yD-p28xokCy6rfAE8PltQWR81bIcv6nXUDR_rQPq7_sffshYG9mGBi25gUWg0VI-SSAVgmdEcrur3uBW9iNxH-w8SME935S7Mq3iDIS_8PT31P9QqqVgJeiGImVVZnlbm80oVl3zCsvG_4Va7cpGasNpe38FNhPRkeNFx6xiWaksGwO0hVgCA1FeqaDAeUNafLWSqRoH2ZG0g7Y3tXjUk4lOpEeansHMC2d9jMQzlUvGuBHhiwK-61c1DKjbsP-leyxlVsnoYQqUwuijESJ3UJifNdTNBHlCPyHP9tfDGTYTDbdJK8QJ3NHytApztHWsdmueF07ssy1QAUsaVHLF0yyqRQfcsEzr1VFdegzRTm1WL3etr33v5N-ak9aMqKD3ra7_CAVCrTfJTt13p_1SPKDADPU1diTpD5kAWVhOTdSfEbhuskDGEHAi-CPM-bWQrGsQvEDCE0Umu4v925jnkws2ya97NA9P06GlB2lEaX48qrh5yQqybgRzQdahZiamJaOi3BkfaQp5w0tk8F-XmEjIxJrhKpLgGLwY3ULD3mCsIa0J5Z-uGtsvxAK9FvT6_n6vS-Kc9BHzRwdEw30tGadVJ2FPxhaVcTFjSQ_5nV6S_mWobcYqSP4SLuxpwhwFJ1E426XG7Q0mjQSas4Y6linqUIrzeacVZ_D7aXW4-Oc"}' + headers: + Accept: + - application/json + Content-Length: + - '713' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8/decrypt?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: no-cache + content-length: '392' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:12 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestencrypt-local3e1a1596/4ce76edd277145e49cc09496d62468e8/decrypt?api-version=7.2-preview +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_rsa_verify_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_rsa_verify_local_from_jwk.yaml new file mode 100644 index 000000000000..4614f6e0c343 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_rsa_verify_local_from_jwk.yaml @@ -0,0 +1,731 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: no-cache + content-length: '87' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:17 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + www-authenticate: Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 401 + message: Unauthorized + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/create?api-version=7.2-preview +- request: + body: '{"key_size": 2048, "kty": "RSA"}' + headers: + Accept: + - application/json + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"8_nVC-gyiwI26zo7Z66BcRb8Rd4PkjO3t1HpA6onMnC52UFjaI1SASdyQmvb-wGDZRQ6FibYpv43JZMgDw3Lsnk3HHy70zKoxFx228LAPm7rDAWi34VRCYTWy25XuKeiIEMmfewGJ0o-U4OwA1WjNhc6yWojxcCkzbJXUGLtolZGHtHES2GwyyvgMfVDIeS8i9UgtOfj6AvEkNL7fl3Gf16Zu4ieK6Y5A4HaPx9JbAcvhuvb9Ux5UdD_rsix37UjUWbn2CpCBPQYDpGTHp7arOTi1pHDpsg6bwAlnJOa835d80d-byruG6ZeukL-HKMuyWY21R4KqoM_A87j9aGuoQ","e":"AQAB"},"attributes":{"enabled":true,"created":1614987078,"updated":1614987078,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '699' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/create?api-version=7.2-preview +- request: + body: '{"alg": "PS256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","value":"ZGaS281UnxDF88I_B3Hc-ppK5Yja2uUziNMO22dX3NuZEI-ueX_sJSnC-PxcHJuEJj6l_VxOKYFi0OkSKtxuLruRrhNbed6hpdWTFgecxuAylvtXE5LpzKIrt2wV1JE5j5Pb1evQ3V18mxzqBZJDFeS6Tt8Wu1BSxibcnJWEKhOhTzRkLvPvYL2BDsycktEghU6D9P8apFFsVUd2g9PJRxc-HH7X9qFTjQRLKX5D_L8SWwFAxbGFLvKR55yKvD2U1-YAcB3-KbcYbhQfFXZ8336jJLA_W21OOICJ1kX_z2uLpGf8mtK50St7Wa0K_ptdFxGVD9-SJ2X47yuv-xM9yA"}' + headers: + cache-control: no-cache + content-length: '469' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview +- request: + body: '{"alg": "PS384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","value":"eU9rPW-P6RhrhWxzku4Jgdv3nxSQQ3VYvNs9mQ2UtOYNWIUeyCruNhuvgSlwId7wzWRsBkDCFYQgcjIVm0BV-CwHcSWTWpCPyilq2XARzqsUV_lraA48WUAIc3WFnjFFt3gJRZveUp0iqntO_0NHOXUcz65CnEtgpq_kzCv4-wwpSicO5Eoi2_uWtYoLqOVFoeuCEG5F7BOouilPMmRrkT8VvVKy98rl83RvhZFHVQzPcILyEtYRprYqps6Q65kzZJV935u6t5FjgpDrz5YCqcwMBTRV4yGcR37-hJTQgtFF-CrITmU68Ae77FpXQLydHvMYEBXx-5VUzHIr1dTL4w"}' + headers: + cache-control: no-cache + content-length: '469' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview +- request: + body: '{"alg": "PS512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","value":"Gl0DBsHhf3pDg6Ul5RzhDySdFpe8CJzUocplgoLyNrq8_mrTj2bv4oAKM8RJuX1ifIi_bGQSWP61Z3DT3Akyj_oZAz8ZqtqrZp9Zc-Hx_1DbOG_xhswkKuKjzsl5T2OfgKjKiNpjzwSpj6x1iFdPNR4hNIqzqUc-V4Tz8gt-GlsYMziMW4OIjcD9WzMobmL9e-_PqwA_oTII8I3_LQR07ftGEU8QhTHELnMXC4KmBtNbEXPG7e1y8cnVE3yoqcEF1uzVsyThrKDq2jKeTqMrz9k5UlgXbfD5hqUuCeADD3t9QI7ngDYXffSSGjoZpH3oQyvABCzIl5TIJ8RL8PcjTg"}' + headers: + cache-control: no-cache + content-length: '469' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","value":"JqYvezQLtbunPEAHNj4gPIGza69P8kCUoWUToeizvv8iATme8NnMxEl0YzkI0yQ9U2m8s0YESH2_JujTvFTXExqPT4hW1hjSjl5Tw5gIWPFdNy9N0LOHR5MoIbOEo7unhl81nEJlUIvd4za9hrcpzN0aZia0x6UBL_uS1kABxceInfQqbm6Muvna8wGGoIpMqq8siT0rR1rHtF3y6kgZhziA4nXBqSB8U6wAaos3QY8saF_eGauLOisC9QECZ4tm6gNAX_R2AGc7xB_8VzOJt8Lq674ZV9EzWynQB3j61lPZUhqaQ2cmTkO7mNu3Vgh8WBOt2wTBcJ7XIL7NV6j2Jw"}' + headers: + cache-control: no-cache + content-length: '469' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","value":"72c6bxm3AesQxtX4mhBhvON_8vyHe0I5BZ8R4g8By-L92MiMq2uPlmgrv-i8_RvviRVLMnDd-juzYdFIbkz4RigGBFsDgKvPkEw5Tm6sxO9LJVbJ7LreGb76wBLPYBh9E4nyc25XKh7gI2rOhbkKr5bgOvU1sgRGCBE2OInevSvjRGEdPaAffeqAQPSeVzAsDhfqE-_HD0USEjbHuJf9H7l6bQbsOz5-kIWRlisKYsjkuIN2m7HWgU_zzGe0HHkzFfL2wM80m38OTiqzvap4nseWXmU7bd-uAGhyH3LgLcXWCunlfyzzgNVHkYM3jHIIN5IkQPa0jxliwhqXjB5Nxg"}' + headers: + cache-control: no-cache + content-length: '469' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff","value":"vgHrdWEE99TDd7moMIFocmlYv8mqcM8OpiFDzY4_yQx5G8F8AyB3xViYqvbeYydrF8QJigcH4tnBpfylOyk7F2laE52uKWad-o48D6dYG6ydIy6aCbg0ZgutU27W4uFdFIi7cFsjPgAhiFmhU3oEwKn0eTE17XgBG3IC9ngtxokP3PsNPwx_r7MPpwVaM0R01SjxjqPTflDBqGEERFwwYUQoKpu-YnjOKIj9nCotsbbiWKklrZ-u_r_lZFwqW5iPq__zfoBt37175cZmCRsvlP8ipczT8ZScugbfmWumI-k2c_R1StVxNMgH10WmTQb8yCZHYL9AebK4iW350mg8Ig"}' + headers: + cache-control: no-cache + content-length: '469' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:18 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-204880c816cb/ea5321f7a2024eeaaeaaeef8761097ff/sign?api-version=7.2-preview +- request: + body: '{"key_size": 3072, "kty": "RSA"}' + headers: + Accept: + - application/json + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"tuvgxEz7DkpalrWCnfIc4HJ4-sBUukc5cD4LC8bsmcZzcW5drmIb1Ytuo1VN_CWaK33h8G6AWJXzRaLDzt8EfmHlq1J5Ys1TzH3DODQsZTk1aG1nkUlGRd_cV1X6CXbn3WfPNp5V-Q6UmHhGjkPfm-FkaGhyZ0_ytDtlqeZdXgyNXyh8s6_cxFWilNydT3gnSCJB8O1eCiEYIhBEvhWNKp0HyJF__oOEEvejzAwEe5dMvSFAl1UV3BrVs3CWXQKJQoSAhdH40py41uqNgcTtzi2R6_Mz6CO1_lmMLAROBhIThBv-YrIVvsTMtuE2mvpl78XMnTu2JVR-Hf3NQpm3JHxmbOZC6eT6nS7Avzdhg5-7uaaaKZZMT2T3y9G8mz8KxqNWYPLWmwqPhFa4IdMqIlpLWJSBYmKwz8XhuN31O4lzmGMNn6tYOwdxuUyGZ1IYJWEdwlEPdEQybw-aZyJmpye858t3aMtTRkKLQ9L7Hna33joqPLy8DV_TCJTGtVOt","e":"AQAB"},"attributes":{"enabled":true,"created":1614987078,"updated":1614987078,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '869' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/create?api-version=7.2-preview +- request: + body: '{"alg": "PS256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","value":"kMwBO9VW3qH05i_4xXZ3Q-7I4kzJzEbUX3_WFToSvAZyR3ZQgZrpc8FpBdGWpDi-cs2nH7gIbUHSi3w8BIxFtjE2in8xlVN3r2ibKHZ8jy6em9wik3tzk_4sd1VqkXnq1w6l8IAlMPV7IJOMRUYnmJwevAltdaQGZWEZDjKBfaju5boAY5BG3pFSFzK8dXUUHF5uZMeP4-LdMMYiTCyK5a6gFGqZDSZgwt1VQXUy7vUZJkraFpnbNsFJUQPZKsXzmd1-K4PVnXJkVfarXJUKai9BlSmQNtykpIEMJBFXuWb1MzMwNg3MWu8sqf_QPnhrp2r44l8U4zCXOmX5fIiobRckpQ_XyR1YouZqJiRz-Xi6nOJDZUdnkuu-l-DWNI10t0LiTtr-yQyPm8G8VvjYQwOz1z5K3Xt1eusVEBriEd41gzyV4OUNkoVdM9plzqbD6FD77wEkWC7Zz6OixhOxfj8Xoxl0ijX--4VY7IKPSrrNfNa0-vPW52L_a-pkD1en"}' + headers: + cache-control: no-cache + content-length: '639' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview +- request: + body: '{"alg": "PS384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","value":"UHS9pyintUNr2fT96pgu68PImjKYEFe-0rZ4SUclp2lN88mkEcJ10PKkFMpLBQOHFXSk9WekCIn2LRX_lPdqtqeOulXYT8PTdgKlinZ0NIDtDOwqrhX9SoT4HzfHBPk-LYTOa3DlC1TIXc5lP0x4eJKNMK9w9V4avImTd08gSmw_QlxG6KdBIjpIqUMpixjJsddhLkX2mbZsqYLnNK9SQy-JZxVDgUcX1SjI_6CUwEo1RPW7dmO8O1TMDFT0Yo51hWaiJ4JxutZ1hhD1MYqEOL36ts60AvSqH4Uu9EZ3JxJ1nJRtLUZRrQ6BoWArEscnbIGyAfkzxbGYQzjum3T2dvhBq5n1QjV3jFhHatWEWiTDPkN89-Ajn2eJpb9UOQI25fzvKggUckYgA80AWFqyWSDgmFJBBobZl9A1llqEUnySSeO6dluaNwaP3hWrEJt00WY8DAaoJQljh01vdIfHkOUjS8rnzFh-Nj1gnO7vrG-ucpiREpZ6rzyjQ6S_E0tZ"}' + headers: + cache-control: no-cache + content-length: '639' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview +- request: + body: '{"alg": "PS512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","value":"AD-GPE_ir8rPRV8QYb5vmoOO6aNE04msXYnaINXQ0XYSF_R8UB7sBw8C82CxSUuIPW240Evf6QUUUW2eOB8LSIIK8nqVknDr44kyzRIfEqrpsQXQBUEd_aHphaXHYY7ijuFbhZ2SR15003NWJxaRq5PPJlALRA11O3FXw-uuGveepWVJmYsmcyyirH2BuNv3P3i17AKTwa25Ea4dKkndDjTTMuzVgh_0fbrTjJ3fE9CaUn75bzYmM8UPbOcLJKoEondNeBAHfL4LjmmDoUXEzS-Jc4_jHB0fI-7zc8ePdQmIJpgTFnZxKGjtwaaAZukPPLsn-NTzZ3UpnWdtKc6WJgafEOrhoA2lLIfAYVDVd_pMOp8gxqs47FH3TILireXSUBqJH0ojhYjpzzC8S_8P5rgfBTJK1GD9e6rCtHYxILuad__iTc5dxaDieLlaj4pZcwnzhCJx5szmenQodTA6Pp2e-t4RjnXzusjYlrKihVhzxofNsbFAXe9Rf_iKC7nP"}' + headers: + cache-control: no-cache + content-length: '639' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","value":"FP1dDbQTOPvEJT2d4Zvo_zuGTkLJS-VwDoAIMD3p1U-3NJxkCO3w2QYB7JKEyx3oW4uf5_O-5y8kapps_27XRapU0YBEutp0qQrYqzdK78cobKCDiiMAH1BlomTJAXdFHXlCRG_IJiRtmXgM2z_5posfHfrNNzupIqmwSVBK2WV4Yd6T3iDFDWcFo32GI_xFY9OreMLgW-HI1wkj18YuQamX2_m4n1DBNtgbCrVPHEASxXGj7ZFpWgfm0j_3qk5crEnCTynzXxKBVhYc7cgFQpM_m5lURXv0ox82MM5U3mwM_dHc9ZR52dGAzc4DXTr-rpraqEF4TyjbTyVmRQ_F5Y2zcwvElE80MkBP6n4kk7W1ZgQ_MvBt9VBC1VY4ysWYzI_5ZJ5qHCwIr9Bob-En2kzT0PQgQ4lGk7dL6KZP0xPTS4i47bwoSXxAI8MVGkUxoSa34nonVqsskcuEsSEWkInLnEA8eQ9Q5qaZ3kbXadJBYrAf9Rf8hTWjOXZLMyD4"}' + headers: + cache-control: no-cache + content-length: '639' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","value":"ssRfMUg_ZH7vysrCxDJ7fmWfFW1JzLceODqpAI1F95x3COautjRsHDfqXADSIc0LAfigzPkhl179byQcUm9Q499Zt6N5SVzGBQPSUN0_N-igLiD7xYNVZ-w4a203FBrMIhAD9pBlDGBmTkS_wmKOAybzOgeVYobDQoaHChbCi-50i87_uxLad-e0i_Q_EeJ6LZ6jSwqdCiYHatAJWDGsbCpwLNPWBgOrxRDF6Fd6p1VR1_l7Tpfe4mGk182IGgPwRRa7Qk63s77QPcXiX6iqZUmGU5UpmwL4UTNbRGfURnR4nL4ib9QDQU6vCmupBILZoDYTtOaBK_E3Jzg-6QB8ENyFPxGWbNp39ItrTOFZJuDm7L1EAeRsDNUNH3TP6It72L96EUe8zsfqqYsPQMenZxiay5z4Yn0ZKVd44anAiC6jgAIw07dn43Pgm80mRqHEGnxZ2jjPMR8zWRxqu9d0SLuDoLUy0Fcb2ZrvO9JIVFkSoVXNf2Voc2ENob3UR4Rr"}' + headers: + cache-control: no-cache + content-length: '639' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3","value":"YYbO888typ70FDQRnuT03htLNmwOZHGo9FqL2csKXEFtAPzH4MbBY43hrHtdtGJ9GCqdVTwj0iHG8hTlO1TNQvebBZaWYEzNnhy2XPuLhjEmVnH9UOPDG5eSiMkGhL-m0o40QesEKvFkMOZULEVgWNJ1BM_zMVqRQUhSPPltbu4_n0rMwZ9YIDicHFfLIv-gUY3k-KP0-4OpC8Uh8kUChXQXAaEWkcGkLbgLRgXf8tuVN529ouCc5SYn1VtaGBDxbbMxxYHINpc6__i7t1elwORsSdbRmT573UJr7y39EJ-7b60JzhDoB_AEPInrjzOfJlLmxnGgiBvPBxOizQinUm9SWs1ous-owOSJdZJUiFsvU7MvUcNdyCt31TNHICOlodzp4nInX_iilL7Wwp555QzadBK5ksEYzf_DpjS_zIWnC2Wu7c6DlXi5wHLiGammhsZi-hy5gUZZ7K6t1O4QkD7aWxZlgPoq7mSv36VqCm4HaYeeoDj6gpufxNnKyplm"}' + headers: + cache-control: no-cache + content-length: '639' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:19 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-307280c816cb/6a550b5a58a24dcf92ab80591ae861b3/sign?api-version=7.2-preview +- request: + body: '{"key_size": 4096, "kty": "RSA"}' + headers: + Accept: + - application/json + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"vOAC5c-I2POEE9dCSbfzHTSyqU0yGR8_63kFhbahl20QIMtOF5QYWSA-Yp72BAYJp6ooupjzZWoPICV3nSe9OjLrXOFlK9eizZr9lmTyIDmzh9LH9nfIgm4fbEf1cBgBINW_VmqmdzuHmVASb5L-drjSL9Yu4EMsuLSmu5LKWfl7GLBBoPbtQALVNjhWyHkyEO1NkyPx9a3VqEzJrBTQPBOifl50KVaUC6RcZT4O0siwj1JtZUaQHi5ST3kuSO7aDB5O3tGX-ULhPFXXqxkG-sPjVOvkT0HHGCVXELaiozateUZ_GAWeSAUuWO69vVXkKXd1QcsM7XcbTdC3uJTZTYeKmR67WBwm4icpRgPGqWiy6VDQa0FKNslvwpOGEa0fGhD0VPZvRNy6lxDWZZrbOBRY1Jc9QsjFEwv1kRwv2-_-PAxSFibLhoaR9iGHsF6d3A7UjRhfhXawG6hRV4Fl3i2mvKrLGo6ntnC60n32S7ghM7LdIZT8QKoVN_ekNMirWE_nkw7K0HnKE3g8wwRv1cQTggCTBOqOoC1kLIqJ9JGeLDyv4xII8761hh5LV7v8KjkjmuRoEf1ZY72JSlQWZutmu6F5LyyaP1jtpJAbhWMh6LKr6PaD_lXpFRV8f_mq61yMx8GZPCaqwgar57z4pFl2OzgdqVm0q2JjuIgN2tU","e":"AQAB"},"attributes":{"enabled":true,"created":1614987080,"updated":1614987080,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '1040' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/create?api-version=7.2-preview +- request: + body: '{"alg": "PS256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","value":"mJWHXR6MGxksy06UtvrQn0IQ1xm6UyCkieKTCMfgqsf_jEWRd2hqcqrPZu-uj2KHj-3rvm_hwajZPXElkU970WtuAYC1nVU4lSNii7z3VMuFFy4_96sU5iCRh3cS-2GLIIljIxiMwUipOPbu9HiOVpgK2AwGADpgoelUFGU0Xq85M4TKfREuyfAMjrLfVxtcH-kW2Vd6sKHNIySWJIqxloaEZ-lfCJey4GyAbbUVsmz5DTD9TkpMqcsdS99Is-Yi4gPzt4FA0ZsG9E1uhDwFgv4SxCe9lBa0oGJDGe5wrC6n4t1j_pUiNyllBgneEjgcb3OsJBQ_jZtvoI0occYuOYy7B0QiGqc6L5J7TNIgbFQAHbeP0ZbdsFIVigernYwM2EhSlfHvWXwZx1OeIZlvfOXkbcHxSiJqqg3MJqIQlHbaz6NbQ5KWy6W91SvUWzYdKVlQZt0bo1Dy58WD0P0D6infLMMV2YcpvFemkaQ3DzfBVrubTK49a31VrAVmvYFGT192pn74DSJ7oLuttU4Y9jaCOUsocAAnZTfGCoCrBtVtg4WXfpar2YDJNq5UAUUnwBCwNk-HR7NpKg-rouGodeex3HWDlui4wAUIjilImOERcbCeCZ1-LzfyNRjepIK76CGNZ8lmIagP2TL7747rxB_00727um_HDJwIUZX8SEw"}' + headers: + cache-control: no-cache + content-length: '810' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview +- request: + body: '{"alg": "PS384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","value":"TCxeAGSbCZNmDGpYm-SjSl1VjtFuETjhFD7Cddu3HCZ7lN39yKFTJLWCL0gxwoSWXeAnIbqtyOLo3_OJTlhWo25obJyGCPm9VhPQyKTA_alxUeyqz7MuZ5lIlWYhmEpu0tGISlgm3dzt_mhMPUCwlj6iTLevwX5yLQp25hFxjx7osmDiONhTgATO3NWEOBTjNR00xbyi3PGdpDSkuZXgZL1Y38PcisP-2K2PrrJ4D5DBXZxC2SPFusszU4QVNbotmgSuIRjPDs8zD27xaFMpzgHmU94sEyxZ-eu4yd4ovOQ5fJ1xjRSJrByu1SMoaoMgeUcpic3CrZ_R4LwitTYfx_hpBpofOzeIa5GH44Ft81gysIHVrXNVIMxTs6PBwE5znlCYPHxM9UDFyGqQSPAuMNdhgIsjJX1OI0X5a45iVxYJgCyhmGA5zH8zzALDmMFM6HYagKcIYK2EHkWv4tLmkcaiQ377MFhjBEgWkY3UozrX5pYGhJfAOdNnJ2SKiAj9wfEtAJctaYlqVf6xfkWwu9i5n-KXl36V4_HLJrCuSDqo3FLSaBB_uaJnTnuHMZGqjG5M8DLnRY58aznoQHTQ2yXTGP2GyB6_G2XT-gOV-fRUidyPLlEAAoWcuUxxVEH95dpxN2eVJQdygXxVaACDFzFB8q2qP8c0ZPrRuVC2mvI"}' + headers: + cache-control: no-cache + content-length: '810' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview +- request: + body: '{"alg": "PS512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","value":"VxdLCZ8fj0xN8LKMINvgwVxMMllUBVf_6t6wUF12PMZrT875LzAnrFTCg9cR0YeW5BmucFAIhLcRVq6O0hZAN-JZN1WTO5kCGNKDdKp56pkECExTGkrRzJh1dDubU5Mx_YxHZ2UhsLyE4tAZ3i8fVFM4ehr5E8Zthg22CE4jvxdWv9actHumzEwqu0h6GQEl_aKaAQYCkownI8c3Zd376RyEQ4G2BGOp8LgIMr7mm7THm2aXQJ8ejeNmJZpGO2v-wXR-gymcumRx6_7QknMOUdqC-6p3EX4_DPeoSIaVxaY6wThap1RwdFWBCh4ZieabD1Vvc2m14EVRQe_FaEstuFeLXF3qDEMhmhdBAxgOOy0owQIbtrI70c6qqci8Rj-syqT07iQjFHgkjg6Ft3D741aGPSKwJqA9WYKsLOjjk2QiFTPCmU3r2z0Wu_OQAwbr3QQ4z6TGp-E7Y2gf_L5y6Ikz6TOwoWR99JFuLCfw1mZFEuuyfS-CHYiED44dEiZm51Dnqu8hqRocw1Tue3NTzcqC2lPtjeX5sOSm2bd1_H_tDK_aFtU34xyVYvI19koR3hbc2HaMZ1kJyOjwDXOVoYxMzbJ2i-8_DBzfHnxCiMrLh29wKI7LJYycDvxKZy6bTc_LTieWCJZWoiYQKhYB8vKB0Xgm_yFJaIzlq46gw9Q"}' + headers: + cache-control: no-cache + content-length: '810' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS256", "value": "vgZc0NQUb6WMKX___V2JntcFRO_vszKwSAj7R2rL1zg"}' + headers: + Accept: + - application/json + Content-Length: + - '72' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","value":"ry9PzdABURUjsvzzNKVUhwByL9frjDtFtIXlA2gwYSvpFgtRjz-TqYoUSpntCxP1ikZeniwjcnAJJ2n32Pj1TtKmOQSHw7z8G-CKTdurRL5I0ojZHifs6lejYjXmZOaLibuS0IA5AC2pqKG4KKZnxr96XX8JaeE7SsVKjSGWesYKVfgAJmnIewrjl7rsPFVxmacKRietJt2X840oHWaSpQbVpvCKLs_c9cR811kGmzpDdBJEU0AvFRA3IptYIoC0t8DqKaf7KD4kM8IGyYf52u8xvjJ_eZYscwG99qhCvk1dmv0Aq0XNEAJIFLSbebcgmVxvqMULEj5htoeq8GIHtfHMIJ3BQS0H96x5RWu39pwy7KxJPGeCXHYQ75-CNyQhfRlFu1OsTsXu501eoO_pQWo-hT9bUHeyF4SYY2rNqv4B8nydGvDkUg_wgxqR47tyQR2_w9vzHQf5qLbpQ7jNBQxTj6I8h-ASnkYWzIYLPhp4GgOne2ZBvY1RErcdLJUSGDMHPiY993-Y0hmXUado6RmwBsORgOYOOIAoOWnKxtHqVKnK3KOeQr8oGed8Lgeah3KUL0UgwDZAXyNVygaoPMfq-vvtH2w89XHCjwJvCovplq9jT_0GUHdtX66yxAMCaWAokpSQ7qbIu1qavPFmXDPZdobZwfVa3FQCY_NxhT8"}' + headers: + cache-control: no-cache + content-length: '810' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS384", "value": "OnZY76NXJ8_MBkjnc9b9RiaL5OYscmrTal040wQuLFlRrnLvJFecIvZl2KjXqwVB"}' + headers: + Accept: + - application/json + Content-Length: + - '93' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","value":"cvnSgrlqkr7p0CU7CBlAAFe9mcZ1k-mSACo06iOc-J9ygLu8lcYekH4CEZqz2eNHq8uOFtBr-A15Dxrhp4hfZ7mKCoPZFZnnuN1j8rMhoB22UThsddsWiw1IGr2JNwS6hoelrGd8gb8XSVtKOrYqdqG99abwBFhNhY3r1ITlFEwxgv1JubwcgLCJSTQAZEIBKROp0JQzNtiZRA3sNqLwcIi5_DUb2xZ8oDQmAc3ycrrJAZpP496kyNewdBKaRieoGG2r5UlbAdyICAoN8ek6cAhXLzLRshG8t8aCc7wrY_VSXrnE3K1xgVFln9gw2TYdnt7tr2alE6E7Lc192L1Lo0tINj5IYG7qP1ZAp7wxzzPtI-fCh5JFWjzqf-RcmdYJW4Wg25lZ3qF_0gH54WSJaf3QMYef3Kz66BpyMEAKO1CFvGxy2s8W7GqI-vbXVWmgDBKsILWA0kPHmKdN4ORjOqV7snOzMlSxuAHrgvJMn2WiXxRlGE21m8sBQKbMtQKlprzTMWks1ajPakspDKYf2zv_xVFN51dMl4GfCh5QIOYVH1ZmCWOWmjr54EaniHHvfuf8HJGqRVyqdVmfnwzXlUfdp9YUJAs1uyM8JyxfqXiv8J2ltpmgfDn-6h_LeVCE4K7_gWN9HLboeVb7XpH_nKth-RxwysGixhe9fpbLTIM"}' + headers: + cache-control: no-cache + content-length: '810' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview +- request: + body: '{"alg": "RS512", "value": "zZyL-eOHDnnq34aZaWgBMobx4x2Pm3mPRo4eqnRmLK6sE0jsXZFOFhMXaTcvILQxovTsMMh9JupeojYCnDvfrQ"}' + headers: + Accept: + - application/json + Content-Length: + - '115' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c","value":"fvjkciRlQcJLSSyBY16WAU0M-axnCspNPXTPgqvxKJAd9mqPBkhDw3di59ipIy0AW9hBWNYwZM3suFjiEvItw74AKOtSqHqR3GptPNpGSukIj-rSqPq9NSdwnoaRSBckBai0rSQTzve-f_-Q5zEN5v5aa4nCin6mRRMYvWpAxy3Od1kslizd4RgFKweu-6XM5Nkxt9lSq9_QhoGsVcLiL8rwFByc5DlNEhlzDE8skWWmA4qNvKeDSm78_bF3fESh_BZCKy0neD-EhLn5h0N03FA8hvjhIWj4fUM5Y2HBiC2cpMxC0oXaBuUcqOPeZ0B53W4OqYu14VJVpPmC-pNALSUxH0GbISqaZ7SuAfxU0e00zgSNcKjUi9WkG2XQi8lWCANB_dKHQ4O43Oy-pR8-0qIiBNpHadVsY7vvZPVgie8ghtXzDOD3hl3c2_Pr0kW1FpgD0WUJSD8Ts8SJrXXAqSK2tTA8_LjUahItL1COcRq7BwEQmFlZOUY5CVfjVHmVb4LXdMmMINLE9W76WiNZOA1t5A35HZ7bap-dnp3FwQG6SY21ya30M7mz-dQYOCa0Yn5HymqiWBDbkt0J3qLvSa0fDCF7r23MKzWMpaPbz79yOqb4xdFU44YZsjqnO95t8bHocLMEEU9JInoA1leC4PS09fvcYbXoSQp5bVC7A40"}' + headers: + cache-control: no-cache + content-length: '810' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:20 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestrsa-verify-409680c816cb/99866356c45e43ceae4c41601521426c/sign?api-version=7.2-preview +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_wrap_local_from_jwk.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_wrap_local_from_jwk.yaml new file mode 100644 index 000000000000..20844bad6e3c --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_crypto_client_async.test_wrap_local_from_jwk.yaml @@ -0,0 +1,170 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/create?api-version=7.2-preview + response: + body: + string: '{"error":{"code":"Unauthorized","message":"Request is missing a Bearer + or PoP token."}}' + headers: + cache-control: no-cache + content-length: '87' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:25 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + www-authenticate: Bearer authorization="https://login.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://vault.azure.net" + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 401 + message: Unauthorized + url: https://mcpatinokv.vault.azure.net/keys/livekvtestwrap-localfe02144b/create?api-version=7.2-preview +- request: + body: '{"key_size": 4096, "kty": "RSA"}' + headers: + Accept: + - application/json + Content-Length: + - '32' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/create?api-version=7.2-preview + response: + body: + string: '{"key":{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2","kty":"RSA","key_ops":["encrypt","decrypt","sign","verify","wrapKey","unwrapKey"],"n":"sf9VcnkMYMvPeZRAZFyf5Ie8WZ6Q6l6waQ4r-aMuSYKkWXrUzVFd9HcbO_snsAAYdF1WHpj01NSkcsAhrIf3kCSzEhLmpBHdBgV4eBr8lq_9zWMUpGi7d4WcQ5uDAfiMa9EsEHvyn9CPlINNKkTfQwiXnbZ_8_K9m0lIDxpGTY8x9r7exe8YxJu5FbCWzrvwG-ty94wpkwsMPUX_vPf4L0j77MxprD--2UQSnJZyb0aRIl2uYqWJPiO62R2u4hiXfHVyXUghb8z6TZsFbPDSkek2mYX4JExiHn4e_ye_Sl9tY0KB_dIQTy0bBT4PDUgnrFIzUQtnP82fHw11Cnq_5YMprfKHQATqJEwJQIOCXtI0uZHmwbWj7Xm-ktpP8M8RrOu4QIcOZxG4p-xDrxk2OM157tDlr3H9fxVjZyuXmHMl9tkAApBEE9D-e3lGQ8wyeGp-NvVIiUKZLIyH5722uDSPXk6IggeLMIGjXcZP1YCNiQHjYJ__maDMJgmkGRHxq7avzoSDfgjHnWBo8yz-lnc7SK0teVKo0pNivlJQwCoRde9PNeyqfHGNf67NpJEiG-TP7PLwDWrINLOA7apcs06uRWEPYUn3UPMV18mNUMaMlQMBC_E4oDbzCDf6GIQ5VC46Y_JLy64EM9C5ZIQylMtdOIPrwsASrs8ZuozTQMk","e":"AQAB"},"attributes":{"enabled":true,"created":1614987086,"updated":1614987086,"recoveryLevel":"Recoverable+Purgeable","recoverableDays":90}}' + headers: + cache-control: no-cache + content-length: '1035' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:26 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestwrap-localfe02144b/create?api-version=7.2-preview +- request: + body: '{"alg": "RSA-OAEP", "value": "AQdRTgi1SCwoREiaKz9sdnKAYZ53Aj0LdfTFWmAo8m_ZFQKn7WiyI6lP13XT7L90fYwuo0GBmXuBbEdLcFDtzaNIDaRq66hqs2n2AgZK63tyuPHx0ICkNEL0D5OKPTAw0ItWzn7AML3mVeT4pqLJiiIiYFao5FgKm3UqUB6d4bVbWkGHQT-4IxzXxbxiRa4ofRK92Y6fkfcvBO4J8L76tzI36OpQblUPdivkO21R3sQWXdEI1ofoFMC9nCXWig9ynUtrZNwlsEHV2Vko8KpE7BY-0KciuRD7KMFaMeVDf5xGq_m-nz2S7EWpLhYBkz_UFHV2tuKPCgtOx5WBRpUX7EctOeMnTvspdRKMxq9abpA6lE-zgusQhCvzFYimvg6HETc4bBN93naju5DzjPfgT7yQE0apoC2aJeCKcgFW7oKl0RJu9Gmj5Sm1aU1iTH0t9Fyu-ueMm21GroxNqYZ0nZRHTGfV-g5KkAaurdQMhes8a9aIbhUcVT5B1iZuBFxHKrMjZqrZI3x2WGJ_ILYdbGyy5umFm6u2sfhLP7Atv3RqUy5uweX6JgqgRLiNfpXi6rlgYTnD3zXgQHVmb4RdChw0Qp8H16P0BbLZ_NCGLiNIP9UCLVSJVIwRj1x8o_c6ovHoBxhq5ns7r56YK9pL4Wiz__xYkEjhz54hcmwafv4"}' + headers: + Accept: + - application/json + Content-Length: + - '715' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2/unwrapkey?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: no-cache + content-length: '389' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:27 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2/unwrapkey?api-version=7.2-preview +- request: + body: '{"alg": "RSA-OAEP-256", "value": "OhBBp_H5OVWFaWfkQr7N-akBF2OhxBC8FV0GSh-SxTOelJqTSTB0EmLr8I2HNDZLN-6rFyGqau08LmfO9_k7K6ncFvQGrNBHxQ9bBVoo0d_9X3l4aFYwn6VEX4AJunE8tHb_Bs_RVGH4ZEqvOgZeoHCLQdph2Su36uwu0Ik2Q_uvA9JR45SJvrFZXHB5m4SYsmZHLDwRHIprCKMd0kM1zdJLgcnuAiQYAdmtLdLse9X-kF5YzCDa-sLhGBOdZ_T-kWOibexjcU3amyLF8obGJpaldgbwaSaf0D2Rb3cNhgTEFZpGPlOpgTdWMfL7ioOFcMKtxhq0Qxct88DWkSIJMCXxpcUMHj8TNxfWVgPwZ0NWXcURIZbuKa300x97j8Y0J7JfrnSFsEj42tZnesUtygOdC6_2RT257fqAOxaL_frQsvRK8HP1_4Kb7qHUzMo2aapNuQezHEsqSuct9jeKuHEj2yjgdHjZBUJEiTtTiu70eOPBtKwb4fD6qxq2TNDK0zgZ8hqsFOZv_RFZ6zDKWeaMyWRAoCNxFGm_Qu0_sB6b96c7EmNTgm1R7O2YG83xx5TbXDRpon_qp-m7Rutg2rGwUFqUbteko3TguBhv4KzjImFrdZ5jdBm7EaaeqodBo8Rktlnz5_9q0XAusQPAGtM3jStWr8WiB8iW5zZgJ2w"}' + headers: + Accept: + - application/json + Content-Length: + - '719' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2/unwrapkey?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: no-cache + content-length: '389' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:27 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2/unwrapkey?api-version=7.2-preview +- request: + body: '{"alg": "RSA1_5", "value": "U_2erIgBrODdMQYAoLC7lTUzwhKc1wVuXYWk9zNYGQD0Sev8KdIjunq4GQSm7URTdkOkVmOtu7_nOPUSolobpw_c5Im0V4OYxtSA9jg7EtKNx-FIO5xEoqfx2F2pO4WflHXk_QIUbSahx8-ntOXva8g93j-DqF3eIIbCW4FA_0fHk6rNuXRbrtZK8OWfx-55xOI1W_2IF6jAqi5wBeLO441kcEXJ9wgA3dQSIKshP6xuP6IOK_Vx5rLWLgVmFhqUnn1FYODiMKnhRTswFkzQuvJhvRG6oGogmbcTDsJlW_ndgC-KPpZuvhvGW2-bqZxXdW8ewXUqX80LBHT5ZcjDJJSMWamHesiZ8rUZerUkMEsvbouaTbjDvAr_8wMRKMIubrdlJTZCL6bGgUXLOwvxFL_Qaf8wtywnCx1vSYQDHjAIMqbmzvbxNWBlLhz9iIxM9eNrRtk6Zt1nKPwjbmUUIqU4eEEsdhumLB7Gj11RMS-0ntS3V16UpKX7pNIN2_pqanxEmecsYQVu-w97IMoBq6ijFOvE92Oh3XkTIMahG5DKkSjZAlHjRJLwY1W-c5NTor3nBnDkH15X5TrCy-_ifkXtPKZG73L8-z4lKbhUOgYfgYdPPKMDKlWrIQbcp_1uuaIX-MzYB6AWGSvnWjrro7nxiqIBli0Qw0YkzTbd2vQ"}' + headers: + Accept: + - application/json + Content-Length: + - '713' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b3 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2/unwrapkey?api-version=7.2-preview + response: + body: + string: '{"kid":"https://vaultname.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2","value":"NTA2M2U2YWFhODQ1ZjE1MDIwMDU0Nzk0NGZkMTk5Njc5Yzk4ZWQ2Zjk5ZGEwYTBiMmRhZmVhZjFmNDY4NDQ5NmZkNTMyYzFjMjI5OTY4Y2I5ZGVlNDQ5NTdmY2VmN2NjZWY1OWNlZGEwYjM2MmU1NmJjZDc4ZmQzZmFlZTU3ODFjNjIzYzBiYjIyYjM1YmVhYmRlMDY2NGZkMzBlMGU4MjRhYmEzZGQxYjBhZmZmYzRhM2Q5NTVlZGUyMGNmNmE4NTRkNTJjZmQ"}' + headers: + cache-control: no-cache + content-length: '389' + content-type: application/json; charset=utf-8 + date: Fri, 05 Mar 2021 23:31:27 GMT + expires: '-1' + pragma: no-cache + strict-transport-security: max-age=31536000;includeSubDomains + x-content-type-options: nosniff + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=InterNetwork; + x-ms-keyvault-region: westus2 + x-ms-keyvault-service-version: 1.2.191.0 + x-powered-by: ASP.NET + status: + code: 200 + message: OK + url: https://mcpatinokv.vault.azure.net/keys/livekvtestwrap-localfe02144b/d0525db10b6741b28127607e46a400f2/unwrapkey?api-version=7.2-preview +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index 7382f8685034..14ea55524f19 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -276,6 +276,23 @@ def test_encrypt_local(self, azure_keyvault_url, **kwargs): result = crypto_client.decrypt(result.algorithm, result.ciphertext) self.assertEqual(result.plaintext, self.plaintext) + @KeyVaultPreparer() + def test_encrypt_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Encrypt locally, decrypt with Key Vault""" + key_client = self.create_key_client(azure_keyvault_url) + key_name = self.get_resource_name("encrypt-local") + key = key_client.create_rsa_key(key_name, size=4096) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + + rsa_encrypt_algorithms = [algo for algo in EncryptionAlgorithm if algo.startswith("RSA")] + for encrypt_algorithm in rsa_encrypt_algorithms: + result = local_client.encrypt(encrypt_algorithm, self.plaintext) + self.assertEqual(result.key_id, key.id) + + result = crypto_client.decrypt(result.algorithm, result.ciphertext) + self.assertEqual(result.plaintext, self.plaintext) + @KeyVaultPreparer() def test_wrap_local(self, azure_keyvault_url, **kwargs): """Wrap locally, unwrap with Key Vault""" @@ -291,6 +308,22 @@ def test_wrap_local(self, azure_keyvault_url, **kwargs): result = crypto_client.unwrap_key(result.algorithm, result.encrypted_key) self.assertEqual(result.key, self.plaintext) + @KeyVaultPreparer() + def test_wrap_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Wrap locally, unwrap with Key Vault""" + key_client = self.create_key_client(azure_keyvault_url) + key_name = self.get_resource_name("wrap-local") + key = key_client.create_rsa_key(key_name, size=4096) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + + for wrap_algorithm in (algo for algo in KeyWrapAlgorithm if algo.startswith("RSA")): + result = local_client.wrap_key(wrap_algorithm, self.plaintext) + self.assertEqual(result.key_id, key.id) + + result = crypto_client.unwrap_key(result.algorithm, result.encrypted_key) + self.assertEqual(result.key, self.plaintext) + @KeyVaultPreparer() def test_rsa_verify_local(self, azure_keyvault_url, **kwargs): """Sign with Key Vault, verify locally""" @@ -315,6 +348,31 @@ def test_rsa_verify_local(self, azure_keyvault_url, **kwargs): result = crypto_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid) + @KeyVaultPreparer() + def test_rsa_verify_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Sign with Key Vault, verify locally""" + key_client = self.create_key_client(azure_keyvault_url) + for size in (2048, 3072, 4096): + key_name = self.get_resource_name("rsa-verify-{}".format(size)) + key = key_client.create_rsa_key(key_name, size=size) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + for signature_algorithm, hash_function in ( + (SignatureAlgorithm.ps256, hashlib.sha256), + (SignatureAlgorithm.ps384, hashlib.sha384), + (SignatureAlgorithm.ps512, hashlib.sha512), + (SignatureAlgorithm.rs256, hashlib.sha256), + (SignatureAlgorithm.rs384, hashlib.sha384), + (SignatureAlgorithm.rs512, hashlib.sha512), + ): + digest = hash_function(self.plaintext).digest() + + result = crypto_client.sign(signature_algorithm, digest) + self.assertEqual(result.key_id, key.id) + + result = local_client.verify(result.algorithm, digest, result.signature) + self.assertTrue(result.is_valid) + @KeyVaultPreparer() def test_ec_verify_local(self, azure_keyvault_url, **kwargs): """Sign with Key Vault, verify locally""" @@ -339,6 +397,31 @@ def test_ec_verify_local(self, azure_keyvault_url, **kwargs): result = crypto_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid) + @KeyVaultPreparer() + def test_ec_verify_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Sign with Key Vault, verify locally""" + key_client = self.create_key_client(azure_keyvault_url) + matrix = { + KeyCurveName.p_256: (SignatureAlgorithm.es256, hashlib.sha256), + KeyCurveName.p_256_k: (SignatureAlgorithm.es256_k, hashlib.sha256), + KeyCurveName.p_384: (SignatureAlgorithm.es384, hashlib.sha384), + KeyCurveName.p_521: (SignatureAlgorithm.es512, hashlib.sha512), + } + + for curve, (signature_algorithm, hash_function) in sorted(matrix.items()): + key_name = self.get_resource_name("ec-verify-{}".format(curve.value)) + key = key_client.create_ec_key(key_name, curve=curve) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + + digest = hash_function(self.plaintext).digest() + + result = crypto_client.sign(signature_algorithm, digest) + self.assertEqual(result.key_id, key.id) + + result = local_client.verify(result.algorithm, digest, result.signature) + self.assertTrue(result.is_valid) + @KeyVaultPreparer() def test_local_validity_period_enforcement(self, azure_keyvault_url, **kwargs): """Local crypto operations should respect a key's nbf and exp properties""" diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index 0b07a464b118..155c2308cfbe 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -273,6 +273,23 @@ async def test_encrypt_local(self, azure_keyvault_url, **kwargs): result = await crypto_client.decrypt(result.algorithm, result.ciphertext) self.assertEqual(result.plaintext, self.plaintext) + @KeyVaultPreparer() + async def test_encrypt_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Encrypt locally, decrypt with Key Vault""" + key_client = self.create_key_client(azure_keyvault_url) + key_name = self.get_resource_name("encrypt-local") + key = await key_client.create_rsa_key(key_name, size=4096) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + + rsa_encrypt_algorithms = [algo for algo in EncryptionAlgorithm if algo.startswith("RSA")] + for encrypt_algorithm in rsa_encrypt_algorithms: + result = await local_client.encrypt(encrypt_algorithm, self.plaintext) + self.assertEqual(result.key_id, key.id) + + result = await crypto_client.decrypt(result.algorithm, result.ciphertext) + self.assertEqual(result.plaintext, self.plaintext) + @KeyVaultPreparer() async def test_wrap_local(self, azure_keyvault_url, **kwargs): """Wrap locally, unwrap with Key Vault""" @@ -288,6 +305,22 @@ async def test_wrap_local(self, azure_keyvault_url, **kwargs): result = await crypto_client.unwrap_key(result.algorithm, result.encrypted_key) self.assertEqual(result.key, self.plaintext) + @KeyVaultPreparer() + async def test_wrap_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Wrap locally, unwrap with Key Vault""" + key_client = self.create_key_client(azure_keyvault_url) + key_name = self.get_resource_name("wrap-local") + key = await key_client.create_rsa_key(key_name, size=4096) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + + for wrap_algorithm in (algo for algo in KeyWrapAlgorithm if algo.startswith("RSA")): + result = await local_client.wrap_key(wrap_algorithm, self.plaintext) + self.assertEqual(result.key_id, key.id) + + result = await crypto_client.unwrap_key(result.algorithm, result.encrypted_key) + self.assertEqual(result.key, self.plaintext) + @KeyVaultPreparer() async def test_rsa_verify_local(self, azure_keyvault_url, **kwargs): """Sign with Key Vault, verify locally""" @@ -312,6 +345,31 @@ async def test_rsa_verify_local(self, azure_keyvault_url, **kwargs): result = await crypto_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid) + @KeyVaultPreparer() + async def test_rsa_verify_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Sign with Key Vault, verify locally""" + key_client = self.create_key_client(azure_keyvault_url) + for size in (2048, 3072, 4096): + key_name = self.get_resource_name("rsa-verify-{}".format(size)) + key = await key_client.create_rsa_key(key_name, size=size) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + for signature_algorithm, hash_function in ( + (SignatureAlgorithm.ps256, hashlib.sha256), + (SignatureAlgorithm.ps384, hashlib.sha384), + (SignatureAlgorithm.ps512, hashlib.sha512), + (SignatureAlgorithm.rs256, hashlib.sha256), + (SignatureAlgorithm.rs384, hashlib.sha384), + (SignatureAlgorithm.rs512, hashlib.sha512), + ): + digest = hash_function(self.plaintext).digest() + + result = await crypto_client.sign(signature_algorithm, digest) + self.assertEqual(result.key_id, key.id) + + result = await local_client.verify(result.algorithm, digest, result.signature) + self.assertTrue(result.is_valid) + @KeyVaultPreparer() async def test_ec_verify_local(self, azure_keyvault_url, **kwargs): """Sign with Key Vault, verify locally""" @@ -336,6 +394,31 @@ async def test_ec_verify_local(self, azure_keyvault_url, **kwargs): result = await crypto_client.verify(result.algorithm, digest, result.signature) self.assertTrue(result.is_valid) + @KeyVaultPreparer() + async def test_ec_verify_local_from_jwk(self, azure_keyvault_url, **kwargs): + """Sign with Key Vault, verify locally""" + key_client = self.create_key_client(azure_keyvault_url) + matrix = { + KeyCurveName.p_256: (SignatureAlgorithm.es256, hashlib.sha256), + KeyCurveName.p_256_k: (SignatureAlgorithm.es256_k, hashlib.sha256), + KeyCurveName.p_384: (SignatureAlgorithm.es384, hashlib.sha384), + KeyCurveName.p_521: (SignatureAlgorithm.es512, hashlib.sha512), + } + + for curve, (signature_algorithm, hash_function) in sorted(matrix.items()): + key_name = self.get_resource_name("ec-verify-{}".format(curve.value)) + key = await key_client.create_ec_key(key_name, curve=curve) + crypto_client = self.create_crypto_client(key) + local_client = CryptographyClient.from_jwk(key.key) + + digest = hash_function(self.plaintext).digest() + + result = await crypto_client.sign(signature_algorithm, digest) + self.assertEqual(result.key_id, key.id) + + result = await local_client.verify(result.algorithm, digest, result.signature) + self.assertTrue(result.is_valid) + @KeyVaultPreparer() async def test_local_validity_period_enforcement(self, azure_keyvault_url, **kwargs): """Local crypto operations should respect a key's nbf and exp properties""" From a4dd8f86023912cac97ecc79cdceccb06233e100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Mon, 8 Mar 2021 11:39:28 -0800 Subject: [PATCH 12/18] Local crypto only needs JWK --- .../azure/keyvault/keys/crypto/_client.py | 27 ++++++++++------ .../keyvault/keys/crypto/_key_validity.py | 27 ++++++---------- .../keys/crypto/_providers/__init__.py | 26 ++++++---------- .../keyvault/keys/crypto/_providers/ec.py | 15 ++------- .../keys/crypto/_providers/local_provider.py | 31 ++++++++----------- .../keyvault/keys/crypto/_providers/rsa.py | 15 ++------- .../keys/crypto/_providers/symmetric.py | 15 ++------- .../azure/keyvault/keys/crypto/aio/_client.py | 25 +++++++++------ .../tests/test_crypto_client.py | 19 ++++++++---- .../tests/test_crypto_client_async.py | 19 ++++++++---- .../tests/test_local_crypto.py | 16 +++++----- 11 files changed, 108 insertions(+), 127 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 1df04aa9d783..75397459fbcb 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -18,9 +18,11 @@ if TYPE_CHECKING: # pylint:disable=unused-import + from datetime import datetime from typing import Any, Optional, Union from azure.core.credentials import TokenCredential from . import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm + from .._shared import KeyVaultResourceId _LOGGER = logging.getLogger(__name__) @@ -99,17 +101,22 @@ class CryptographyClient(KeyVaultClientBase): def __init__(self, key, credential, **kwargs): # type: (Union[KeyVaultKey, str], TokenCredential, **Any) -> None self._jwk = kwargs.pop("_jwk", False) + self._not_before = None # type: Optional[datetime] + self._expires_on = None # type: Optional[datetime] + self._key_id = None # type: Optional[KeyVaultResourceId] if isinstance(key, KeyVaultKey): - self._key = key + self._key = key.key self._key_id = parse_key_vault_id(key.id) + if key.properties._attributes: # pylint:disable=protected-access + self._not_before = key.properties.not_before + self._expires_on = key.properties.expires_on elif isinstance(key, six.string_types): self._key = None self._key_id = parse_key_vault_id(key) self._keys_get_forbidden = None # type: Optional[bool] elif self._jwk: self._key = key - self._key_id = key.kid else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") @@ -124,16 +131,16 @@ def __init__(self, key, credential, **kwargs): @property def key_id(self): - # type: () -> str + # type: () -> Optional[str] """The full identifier of the client's key. - This property may be None when a client is constructed with `CryptographyClient.from_jwk`. + This property may be None when a client is constructed with :func:`from_jwk`. :rtype: str """ if not self._jwk: return self._key_id.source_id - return self._key_id + return self._key.kid @classmethod def from_jwk(cls, jwk): @@ -169,7 +176,7 @@ def _initialize(self, **kwargs): key_bundle = self._client.get_key( self._key_id.vault_url, self._key_id.name, self._key_id.version, **kwargs ) - self._key = KeyVaultKey._from_key_bundle(key_bundle) # pylint:disable=protected-access + self._key = KeyVaultKey._from_key_bundle(key_bundle).key # pylint:disable=protected-access except HttpResponseError as ex: # if we got a 403, we don't have keys/get permission and won't try to get the key again # (other errors may be transient) @@ -177,7 +184,7 @@ def _initialize(self, **kwargs): # if we have the key material, create a local crypto provider with it if self._key: - self._local_provider = get_local_cryptography_provider(self._key) + self._local_provider = get_local_cryptography_provider(self._key, _key_id=self.key_id) self._initialized = True else: # try to get the key again next time unless we know we're forbidden to do so @@ -212,7 +219,7 @@ def encrypt(self, algorithm, plaintext, **kwargs): self._initialize(**kwargs) if self._local_provider.supports(KeyOperation.encrypt, algorithm): - raise_if_time_invalid(self._key) + raise_if_time_invalid(self._not_before, self._expires_on) try: return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except @@ -315,7 +322,7 @@ def wrap_key(self, algorithm, key, **kwargs): """ self._initialize(**kwargs) if self._local_provider.supports(KeyOperation.wrap_key, algorithm): - raise_if_time_invalid(self._key) + raise_if_time_invalid(self._not_before, self._expires_on) try: return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except @@ -395,7 +402,7 @@ def sign(self, algorithm, digest, **kwargs): """ self._initialize(**kwargs) if self._local_provider.supports(KeyOperation.sign, algorithm): - raise_if_time_invalid(self._key) + raise_if_time_invalid(self._not_before, self._expires_on) try: return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py index 089248c85d37..f2ef7d16d7f8 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py @@ -7,8 +7,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from typing import Union - from .. import JsonWebKey, KeyVaultKey + from typing import Optional class _UTC_TZ(tzinfo): @@ -29,20 +28,12 @@ def dst(self, dt): _UTC = _UTC_TZ() -def raise_if_time_invalid(key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> None - try: - nbf = key.properties.not_before - exp = key.properties.expires_on - except AttributeError: - # we consider the key valid because a user must have deliberately created it - # (if it came from Key Vault, it would have those attributes) - return - +def raise_if_time_invalid(not_before, expires_on): + # type: (Optional[datetime], Optional[datetime]) -> None now = datetime.now(_UTC) - if (nbf and exp) and not nbf <= now <= exp: - raise ValueError("This client's key is useable only between {} and {} (UTC)".format(nbf, exp)) - if nbf and nbf > now: - raise ValueError("This client's key is not useable until {} (UTC)".format(nbf)) - if exp and exp <= now: - raise ValueError("This client's key expired at {} (UTC)".format(exp)) + if (not_before and expires_on) and not not_before <= now <= expires_on: + raise ValueError("This client's key is useable only between {} and {} (UTC)".format(not_before, expires_on)) + if not_before and not_before > now: + raise ValueError("This client's key is not useable until {} (UTC)".format(not_before)) + if expires_on and expires_on <= now: + raise ValueError("This client's key expires_onired at {} (UTC)".format(expires_on)) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py index f62e65bfa945..46d2fe4b303b 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py @@ -11,25 +11,19 @@ from ... import JsonWebKey, KeyType if TYPE_CHECKING: - from typing import Union - from ... import KeyVaultKey + from typing import Any -def get_local_cryptography_provider(key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> LocalCryptographyProvider - if isinstance(key, JsonWebKey): - key_type = key.kty - else: - key_type = key.key_type +def get_local_cryptography_provider(key, **kwargs): + # type: (JsonWebKey, **Any) -> LocalCryptographyProvider + if key.kty in (KeyType.ec, KeyType.ec_hsm): + return EllipticCurveCryptographyProvider(key, **kwargs) + if key.kty in (KeyType.rsa, KeyType.rsa_hsm): + return RsaCryptographyProvider(key, **kwargs) + if key.kty in (KeyType.oct, KeyType.oct_hsm): + return SymmetricCryptographyProvider(key, **kwargs) - if key_type in (KeyType.ec, KeyType.ec_hsm): - return EllipticCurveCryptographyProvider(key) - if key_type in (KeyType.rsa, KeyType.rsa_hsm): - return RsaCryptographyProvider(key) - if key_type in (KeyType.oct, KeyType.oct_hsm): - return SymmetricCryptographyProvider(key) - - raise ValueError('Unsupported key type "{}"'.format(key_type)) + raise ValueError('Unsupported key type "{}"'.format(key.kty)) class NoLocalCryptography(LocalCryptographyProvider): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py index 33cc3c62d5eb..7685f2ddc9ea 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py @@ -10,27 +10,18 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from typing import Union from .local_provider import Algorithm from .._internal import Key - from ... import KeyVaultKey _PRIVATE_KEY_OPERATIONS = frozenset((KeyOperation.decrypt, KeyOperation.sign, KeyOperation.unwrap_key)) class EllipticCurveCryptographyProvider(LocalCryptographyProvider): def _get_internal_key(self, key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> Key - if isinstance(key, JsonWebKey): - key_type = key.kty - jwk = key - else: - key_type = key.key_type - jwk = key.key - - if key_type not in (KeyType.ec, KeyType.ec_hsm): + # type: (JsonWebKey) -> Key + if key.kty not in (KeyType.ec, KeyType.ec_hsm): raise ValueError('"key" must be an EC or EC-HSM key') - return EllipticCurveKey.from_jwk(jwk) + return EllipticCurveKey.from_jwk(key) def supports(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> bool diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py index fbf79e26f9d6..2eb673e25918 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py @@ -17,27 +17,24 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from typing import Optional, Union + from typing import Any, Optional, Union from .._internal.key import Key from .. import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm - from ... import KeyVaultKey Algorithm = Union[EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm] class LocalCryptographyProvider(ABC): - def __init__(self, key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> None - if isinstance(key, JsonWebKey): - self._allowed_ops = frozenset(key.key_ops) - else: - self._allowed_ops = frozenset(key.key_operations) + def __init__(self, key, **kwargs): + # type: (JsonWebKey, **Any) -> None + self._allowed_ops = frozenset(key.key_ops) self._internal_key = self._get_internal_key(key) self._key = key + self._key_id = kwargs.pop("_key_id", None) or key.kid @abc.abstractmethod def _get_internal_key(self, key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> Key + # type: (JsonWebKey) -> Key pass @abc.abstractmethod @@ -52,9 +49,7 @@ def key_id(self): :rtype: str """ - if isinstance(self._key, JsonWebKey): - return self._key.kid - return self._key.id + return self._key_id def _raise_if_unsupported(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> None @@ -69,34 +64,34 @@ def encrypt(self, algorithm, plaintext): # type: (EncryptionAlgorithm, bytes) -> EncryptResult self._raise_if_unsupported(KeyOperation.encrypt, algorithm) ciphertext = self._internal_key.encrypt(plaintext, algorithm=algorithm.value) - return EncryptResult(key_id=self.key_id, algorithm=algorithm, ciphertext=ciphertext) + return EncryptResult(key_id=self._key_id, algorithm=algorithm, ciphertext=ciphertext) def decrypt(self, algorithm, ciphertext): # type: (EncryptionAlgorithm, bytes) -> DecryptResult self._raise_if_unsupported(KeyOperation.decrypt, algorithm) plaintext = self._internal_key.decrypt(ciphertext, iv=None, algorithm=algorithm.value) - return DecryptResult(key_id=self.key_id, algorithm=algorithm, plaintext=plaintext) + return DecryptResult(key_id=self._key_id, algorithm=algorithm, plaintext=plaintext) def wrap_key(self, algorithm, key): # type: (KeyWrapAlgorithm, bytes) -> WrapResult self._raise_if_unsupported(KeyOperation.wrap_key, algorithm) encrypted_key = self._internal_key.wrap_key(key, algorithm=algorithm.value) - return WrapResult(key_id=self.key_id, algorithm=algorithm, encrypted_key=encrypted_key) + return WrapResult(key_id=self._key_id, algorithm=algorithm, encrypted_key=encrypted_key) def unwrap_key(self, algorithm, encrypted_key): # type: (KeyWrapAlgorithm, bytes) -> UnwrapResult self._raise_if_unsupported(KeyOperation.unwrap_key, algorithm) unwrapped_key = self._internal_key.unwrap_key(encrypted_key, algorithm=algorithm.value) - return UnwrapResult(key_id=self.key_id, algorithm=algorithm, key=unwrapped_key) + return UnwrapResult(key_id=self._key_id, algorithm=algorithm, key=unwrapped_key) def sign(self, algorithm, digest): # type: (SignatureAlgorithm, bytes) -> SignResult self._raise_if_unsupported(KeyOperation.sign, algorithm) signature = self._internal_key.sign(digest, algorithm=algorithm.value) - return SignResult(key_id=self.key_id, algorithm=algorithm, signature=signature) + return SignResult(key_id=self._key_id, algorithm=algorithm, signature=signature) def verify(self, algorithm, digest, signature): # type: (SignatureAlgorithm, bytes, bytes) -> VerifyResult self._raise_if_unsupported(KeyOperation.verify, algorithm) is_valid = self._internal_key.verify(digest, signature, algorithm=algorithm.value) - return VerifyResult(key_id=self.key_id, algorithm=algorithm, is_valid=is_valid) + return VerifyResult(key_id=self._key_id, algorithm=algorithm, is_valid=is_valid) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py index d78808e3d8c0..0e0381d5d47b 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py @@ -10,27 +10,18 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from typing import Union from .local_provider import Algorithm from .._internal import Key - from ... import KeyVaultKey _PRIVATE_KEY_OPERATIONS = frozenset((KeyOperation.decrypt, KeyOperation.sign, KeyOperation.unwrap_key)) class RsaCryptographyProvider(LocalCryptographyProvider): def _get_internal_key(self, key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> Key - if isinstance(key, JsonWebKey): - key_type = key.kty - jwk = key - else: - key_type = key.key_type - jwk = key.key - - if key_type not in (KeyType.rsa, KeyType.rsa_hsm): + # type: (JsonWebKey) -> Key + if key.kty not in (KeyType.rsa, KeyType.rsa_hsm): raise ValueError('"key" must be an RSA or RSA-HSM key') - return RsaKey.from_jwk(jwk) + return RsaKey.from_jwk(key) def supports(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> bool diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py index ed8399e1c3ab..54f4aff73a65 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py @@ -10,25 +10,16 @@ if TYPE_CHECKING: # pylint:disable=unused-import - from typing import Union from .local_provider import Algorithm from .._internal import Key - from ... import KeyVaultKey class SymmetricCryptographyProvider(LocalCryptographyProvider): def _get_internal_key(self, key): - # type: (Union[JsonWebKey, KeyVaultKey]) -> Key - if isinstance(key, JsonWebKey): - key_type = key.kty - jwk = key - else: - key_type = key.key_type - jwk = key.key - - if key_type not in (KeyType.oct, KeyType.oct_hsm): + # type: (JsonWebKey) -> Key + if key.kty not in (KeyType.oct, KeyType.oct_hsm): raise ValueError('"key" must be an oct or oct-HSM (symmetric) key') - return SymmetricKey.from_jwk(jwk) + return SymmetricKey.from_jwk(key) def supports(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> bool diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index b87110bd162d..cf68b3af5a73 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -18,9 +18,11 @@ if TYPE_CHECKING: # pylint:disable=unused-import + from datetime import datetime from typing import Any, Optional, Union from azure.core.credentials_async import AsyncTokenCredential from .. import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm + from ..._shared import KeyVaultResourceId _LOGGER = logging.getLogger(__name__) @@ -54,17 +56,22 @@ class CryptographyClient(AsyncKeyVaultClientBase): def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCredential", **kwargs: "Any") -> None: self._jwk = kwargs.pop("_jwk", False) + self._not_before = None # type: Optional[datetime] + self._expires_on = None # type: Optional[datetime] + self._key_id = None # type: Optional[KeyVaultResourceId] if isinstance(key, KeyVaultKey): - self._key = key + self._key = key.key self._key_id = parse_key_vault_id(key.id) + if key.properties._attributes: # pylint:disable=protected-access + self._not_before = key.properties.not_before + self._expires_on = key.properties.expires_on elif isinstance(key, str): self._key = None self._key_id = parse_key_vault_id(key) self._keys_get_forbidden = None # type: Optional[bool] elif self._jwk: self._key = key - self._key_id = key.kid else: raise ValueError("'key' must be a KeyVaultKey instance or a key ID string including a version") @@ -81,13 +88,13 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden def key_id(self) -> "Optional[str]": """The full identifier of the client's key. - This property may be None when a client is constructed with `CryptographyClient.from_jwk`. + This property may be None when a client is constructed with :func:`from_jwk`. :rtype: str """ if not self._jwk: return self._key_id.source_id - return self._key_id + return self._key.kid @classmethod def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": @@ -122,7 +129,7 @@ async def _initialize(self, **kwargs): key_bundle = await self._client.get_key( self._key_id.vault_url, self._key_id.name, self._key_id.version, **kwargs ) - self._key = KeyVaultKey._from_key_bundle(key_bundle) # pylint:disable=protected-access + self._key = KeyVaultKey._from_key_bundle(key_bundle).key # pylint:disable=protected-access except HttpResponseError as ex: # if we got a 403, we don't have keys/get permission and won't try to get the key again # (other errors may be transient) @@ -130,7 +137,7 @@ async def _initialize(self, **kwargs): # if we have the key material, create a local crypto provider with it if self._key: - self._local_provider = get_local_cryptography_provider(self._key) + self._local_provider = get_local_cryptography_provider(self._key, _key_id=self.key_id) self._initialized = True else: # try to get the key again next time unless we know we're forbidden to do so @@ -164,7 +171,7 @@ async def encrypt(self, algorithm: "EncryptionAlgorithm", plaintext: bytes, **kw await self._initialize(**kwargs) if self._local_provider.supports(KeyOperation.encrypt, algorithm): - raise_if_time_invalid(self._key) + raise_if_time_invalid(self._not_before, self._expires_on) try: return self._local_provider.encrypt(algorithm, plaintext) except Exception as ex: # pylint:disable=broad-except @@ -265,7 +272,7 @@ async def wrap_key(self, algorithm: "KeyWrapAlgorithm", key: bytes, **kwargs: "A """ await self._initialize(**kwargs) if self._local_provider.supports(KeyOperation.wrap_key, algorithm): - raise_if_time_invalid(self._key) + raise_if_time_invalid(self._not_before, self._expires_on) try: return self._local_provider.wrap_key(algorithm, key) except Exception as ex: # pylint:disable=broad-except @@ -344,7 +351,7 @@ async def sign(self, algorithm: "SignatureAlgorithm", digest: bytes, **kwargs: " """ await self._initialize(**kwargs) if self._local_provider.supports(KeyOperation.sign, algorithm): - raise_if_time_invalid(self._key) + raise_if_time_invalid(self._not_before, self._expires_on) try: return self._local_provider.sign(algorithm, digest) except Exception as ex: # pylint:disable=broad-except diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index 14ea55524f19..608de82acb24 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -483,7 +483,7 @@ def test_initialization_given_key(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: client.verify(SignatureAlgorithm.rs256, b"...", b"...") - get_provider.assert_called_once_with(key) + get_provider.assert_called_once_with(key.key, _key_id=key.id) assert mock_client.get_key.call_count == 0 @@ -503,8 +503,9 @@ def test_initialization_get_key_successful(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: client.verify(SignatureAlgorithm.rs256, b"...", b"...") - args, _ = get_provider.call_args - assert len(args) == 1 and isinstance(args[0], KeyVaultKey) and args[0].id == key_id + args, kwargs = get_provider.call_args + assert len(args) == 1 and isinstance(args[0], JsonWebKey) + assert len(kwargs) == 1 and kwargs["_key_id"] == key_id for _ in range(3): assert mock_client.get_key.call_count == 1 @@ -548,7 +549,9 @@ def test_calls_service_for_operations_unsupported_locally(): client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): + with mock.patch( + CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing + ): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 1 assert supports_nothing.decrypt.call_count == 0 @@ -583,7 +586,9 @@ def test_local_only_mode_no_service_calls(): client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): + with mock.patch( + CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing + ): with pytest.raises(NotImplementedError): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 @@ -665,7 +670,9 @@ def test_prefers_local_provider(): client._client = mock_client supports_everything = mock.Mock(supports=mock.Mock(return_value=True)) - with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_everything): + with mock.patch( + CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_everything + ): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 assert supports_everything.decrypt.call_count == 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index 155c2308cfbe..5c00ff1b03ee 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -497,7 +497,7 @@ async def test_initialization_given_key(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") - get_provider.assert_called_once_with(key) + get_provider.assert_called_once_with(key.key, _key_id=key.id) assert mock_client.get_key.call_count == 0 @@ -518,8 +518,9 @@ async def test_initialization_get_key_successful(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") - args, _ = get_provider.call_args - assert len(args) == 1 and isinstance(args[0], KeyVaultKey) and args[0].id == key_id + args, kwargs = get_provider.call_args + assert len(args) == 1 and isinstance(args[0], JsonWebKey) + assert len(kwargs) == 1 and kwargs["_key_id"] == key_id for _ in range(3): assert mock_client.get_key.call_count == 1 @@ -572,7 +573,9 @@ async def __call__(self, *args, **kwargs): client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): + with mock.patch( + CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing + ): await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 1 assert supports_nothing.decrypt.call_count == 0 @@ -608,7 +611,9 @@ async def test_local_only_mode_no_service_calls(): client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): + with mock.patch( + CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing + ): with pytest.raises(NotImplementedError): await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 @@ -692,7 +697,9 @@ async def test_prefers_local_provider(): client._client = mock_client supports_everything = mock.Mock(supports=mock.Mock(return_value=True)) - with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_everything): + with mock.patch( + CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_everything + ): await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 assert supports_everything.decrypt.call_count == 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py b/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py index 6f3fd0c107f3..bf83b314ecf7 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py @@ -23,7 +23,7 @@ ), ) def test_ec_sign_verify(key, algorithm, hash_function): - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) digest = hash_function(b"message").digest() sign_result = provider.sign(algorithm, digest) verify_result = provider.verify(sign_result.algorithm, digest, sign_result.signature) @@ -33,7 +33,7 @@ def test_ec_sign_verify(key, algorithm, hash_function): @pytest.mark.parametrize("key", RSA_KEYS.values()) @pytest.mark.parametrize("algorithm", (a for a in EncryptionAlgorithm if a.startswith("RSA"))) def test_rsa_encrypt_decrypt(key, algorithm): - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) plaintext = b"plaintext" encrypt_result = provider.encrypt(algorithm, plaintext) decrypt_result = provider.decrypt(encrypt_result.algorithm, encrypt_result.ciphertext) @@ -56,7 +56,7 @@ def test_rsa_encrypt_decrypt(key, algorithm): ) def test_rsa_sign_verify(key, algorithm, hash_function): message = b"message" - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) digest = hash_function(message).digest() sign_result = provider.sign(algorithm, digest) verify_result = provider.verify(sign_result.algorithm, digest, sign_result.signature) @@ -67,7 +67,7 @@ def test_rsa_sign_verify(key, algorithm, hash_function): @pytest.mark.parametrize("algorithm", (a for a in KeyWrapAlgorithm if a.startswith("RSA"))) def test_rsa_wrap_unwrap(key, algorithm): plaintext = b"arbitrary bytes" - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key, _key_id=key.id) wrap_result = provider.wrap_key(algorithm, plaintext) assert wrap_result.key_id == key.id @@ -80,7 +80,7 @@ def test_rsa_wrap_unwrap(key, algorithm): def test_symmetric_wrap_unwrap(algorithm): jwk = {"k": os.urandom(32), "kty": "oct", "key_ops": ("unwrapKey", "wrapKey")} key = KeyVaultKey(key_id="http://localhost/keys/key/version", jwk=jwk) - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) key_bytes = os.urandom(32) wrap_result = provider.wrap_key(algorithm, key_bytes) @@ -98,7 +98,7 @@ def test_symmetric_wrap_unwrap(algorithm): def test_unsupported_rsa_operations(key, algorithm): """The crypto provider should raise NotImplementedError when a key doesn't support an operation or algorithm""" - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) if isinstance(algorithm, EncryptionAlgorithm): with pytest.raises(NotImplementedError): provider.encrypt(algorithm, b"...") @@ -126,7 +126,7 @@ def test_unsupported_rsa_operations(key, algorithm): def test_unsupported_ec_operations(key, algorithm): """The crypto provider should raise NotImplementedError when a key doesn't support an operation or algorithm""" - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) if isinstance(algorithm, EncryptionAlgorithm): with pytest.raises(NotImplementedError): provider.encrypt(algorithm, b"...") @@ -155,7 +155,7 @@ def test_unsupported_symmetric_operations(algorithm): jwk = {"k": os.urandom(32), "kty": "oct", "key_ops": ("unwrapKey", "wrapKey")} key = KeyVaultKey(key_id="http://localhost/keys/key/version", jwk=jwk) - provider = get_local_cryptography_provider(key) + provider = get_local_cryptography_provider(key.key) if isinstance(algorithm, EncryptionAlgorithm): with pytest.raises(NotImplementedError): provider.encrypt(algorithm, b"...") From e6ae5198d6239e8e134a2b5b5caee25a6a9e7980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Mon, 8 Mar 2021 11:52:49 -0800 Subject: [PATCH 13/18] JsonWebKey imports only for type checking --- .../azure/keyvault/keys/crypto/_providers/__init__.py | 3 ++- .../azure/keyvault/keys/crypto/_providers/ec.py | 3 ++- .../azure/keyvault/keys/crypto/_providers/local_provider.py | 3 ++- .../azure/keyvault/keys/crypto/_providers/rsa.py | 3 ++- .../azure/keyvault/keys/crypto/_providers/symmetric.py | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py index 46d2fe4b303b..0b2a3571a9e8 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py @@ -8,10 +8,11 @@ from .local_provider import LocalCryptographyProvider from .rsa import RsaCryptographyProvider from .symmetric import SymmetricCryptographyProvider -from ... import JsonWebKey, KeyType +from ... import KeyType if TYPE_CHECKING: from typing import Any + from ... import JsonWebKey def get_local_cryptography_provider(key, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py index 7685f2ddc9ea..e415474c90ae 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/ec.py @@ -6,12 +6,13 @@ from .local_provider import LocalCryptographyProvider from .._internal import EllipticCurveKey -from ... import JsonWebKey, KeyOperation, KeyType +from ... import KeyOperation, KeyType if TYPE_CHECKING: # pylint:disable=unused-import from .local_provider import Algorithm from .._internal import Key + from ... import JsonWebKey _PRIVATE_KEY_OPERATIONS = frozenset((KeyOperation.decrypt, KeyOperation.sign, KeyOperation.unwrap_key)) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py index 2eb673e25918..a018e92c1831 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py @@ -8,7 +8,7 @@ from azure.core.exceptions import AzureError from .. import DecryptResult, EncryptResult, SignResult, UnwrapResult, VerifyResult, WrapResult -from ... import JsonWebKey, KeyOperation +from ... import KeyOperation try: ABC = abc.ABC @@ -20,6 +20,7 @@ from typing import Any, Optional, Union from .._internal.key import Key from .. import EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm + from ... import JsonWebKey Algorithm = Union[EncryptionAlgorithm, KeyWrapAlgorithm, SignatureAlgorithm] diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py index 0e0381d5d47b..3498072db217 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/rsa.py @@ -6,12 +6,13 @@ from .local_provider import LocalCryptographyProvider from .._internal import RsaKey -from ... import JsonWebKey, KeyOperation, KeyType +from ... import KeyOperation, KeyType if TYPE_CHECKING: # pylint:disable=unused-import from .local_provider import Algorithm from .._internal import Key + from ... import JsonWebKey _PRIVATE_KEY_OPERATIONS = frozenset((KeyOperation.decrypt, KeyOperation.sign, KeyOperation.unwrap_key)) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py index 54f4aff73a65..76f2065359da 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/symmetric.py @@ -6,12 +6,13 @@ from .local_provider import LocalCryptographyProvider from .._internal import SymmetricKey -from ... import JsonWebKey, KeyOperation, KeyType +from ... import KeyOperation, KeyType if TYPE_CHECKING: # pylint:disable=unused-import from .local_provider import Algorithm from .._internal import Key + from ... import JsonWebKey class SymmetricCryptographyProvider(LocalCryptographyProvider): From a2d8c87ac0d68149455a246ae3bc29fe6b634bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Mon, 8 Mar 2021 12:30:56 -0800 Subject: [PATCH 14/18] Appease pylint --- .../azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py | 2 +- .../azure/keyvault/keys/crypto/aio/_client.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index 75397459fbcb..b89364e9149c 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -17,7 +17,7 @@ from .._shared import KeyVaultClientBase, parse_key_vault_id if TYPE_CHECKING: - # pylint:disable=unused-import + # pylint:disable=unused-import,ungrouped-imports from datetime import datetime from typing import Any, Optional, Union from azure.core.credentials import TokenCredential diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index cf68b3af5a73..8b9e47d77dfb 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -17,7 +17,7 @@ from ..._shared import AsyncKeyVaultClientBase, parse_key_vault_id if TYPE_CHECKING: - # pylint:disable=unused-import + # pylint:disable=unused-import,ungrouped-imports from datetime import datetime from typing import Any, Optional, Union from azure.core.credentials_async import AsyncTokenCredential From fb36a2566633a296d0f883db2001a6f461090673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Mon, 8 Mar 2021 16:58:02 -0800 Subject: [PATCH 15/18] Thanks, Charles! --- .../azure/keyvault/keys/crypto/_client.py | 36 ++++++++++++++----- .../keys/crypto/_providers/local_provider.py | 2 +- .../azure/keyvault/keys/crypto/aio/_client.py | 33 ++++++++++++----- .../tests/test_crypto_client.py | 16 ++++----- .../tests/test_crypto_client_async.py | 16 ++++----- .../tests/test_examples_crypto.py | 6 ++-- 6 files changed, 67 insertions(+), 42 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index b89364e9149c..ed5a1bcbb73d 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -123,11 +123,20 @@ def __init__(self, key, credential, **kwargs): if not (self._jwk or self._key_id.version): raise ValueError("'key' must include a version") - self._local_provider = NoLocalCryptography() - self._initialized = False + if self._jwk: + try: + self._local_provider = get_local_cryptography_provider(self._key) + self._initialized = True + except Exception as ex: # pylint:disable=broad-except + raise ValueError("The provided jwk is not valid for local cryptography: {}".format(ex)) + else: + self._local_provider = NoLocalCryptography() + self._initialized = False - vault_url = "vault_url" if self._jwk else self._key_id.vault_url - super(CryptographyClient, self).__init__(vault_url=vault_url, credential=credential, **kwargs) + self._vault_url = None if self._jwk else self._key_id.vault_url + super(CryptographyClient, self).__init__( + vault_url=self._vault_url or "vault_url", credential=credential, **kwargs + ) @property def key_id(self): @@ -142,6 +151,17 @@ def key_id(self): return self._key_id.source_id return self._key.kid + @property + def vault_url(self): + # type: () -> Optional[str] + """The base vault URL of the client's key. + + This property may be None when a client is constructed with :func:`from_jwk`. + + :rtype: str + """ + return self._vault_url + @classmethod def from_jwk(cls, jwk): # type: (Union[JsonWebKey, dict]) -> CryptographyClient @@ -158,11 +178,9 @@ def from_jwk(cls, jwk): :language: python :dedent: 8 """ - if isinstance(jwk, JsonWebKey): - key = jwk - else: - key = JsonWebKey(**jwk) - return cls(key, object(), _jwk=True) + if not isinstance(jwk, JsonWebKey): + jwk = JsonWebKey(**jwk) + return cls(jwk, object(), _jwk=True) @distributed_trace def _initialize(self, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py index a018e92c1831..96355c30dba4 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py @@ -28,7 +28,7 @@ class LocalCryptographyProvider(ABC): def __init__(self, key, **kwargs): # type: (JsonWebKey, **Any) -> None - self._allowed_ops = frozenset(key.key_ops) + self._allowed_ops = frozenset(key.key_ops or []) self._internal_key = self._get_internal_key(key) self._key = key self._key_id = kwargs.pop("_key_id", None) or key.kid diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 8b9e47d77dfb..38ea784b082e 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -78,11 +78,18 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden if not (self._jwk or self._key_id.version): raise ValueError("'key' must include a version") - self._local_provider = NoLocalCryptography() - self._initialized = False + if self._jwk: + try: + self._local_provider = get_local_cryptography_provider(self._key) + self._initialized = True + except Exception as ex: # pylint:disable=broad-except + raise ValueError("The provided jwk is not valid for local cryptography: {}".format(ex)) + else: + self._local_provider = NoLocalCryptography() + self._initialized = False - vault_url = "vault_url" if self._jwk else self._key_id.vault_url - super().__init__(vault_url=vault_url, credential=credential, **kwargs) + self._vault_url = None if self._jwk else self._key_id.vault_url + super().__init__(vault_url=self._vault_url or "vault_url", credential=credential, **kwargs) @property def key_id(self) -> "Optional[str]": @@ -96,6 +103,16 @@ def key_id(self) -> "Optional[str]": return self._key_id.source_id return self._key.kid + @property + def vault_url(self) -> "Optional[str]": + """The base vault URL of the client's key. + + This property may be None when a client is constructed with :func:`from_jwk`. + + :rtype: str + """ + return self._vault_url + @classmethod def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": """Creates a client that can only perform cryptographic operations locally. @@ -111,11 +128,9 @@ def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": :language: python :dedent: 8 """ - if isinstance(jwk, JsonWebKey): - key = jwk - else: - key = JsonWebKey(**jwk) - return cls(key, object(), _jwk=True) + if not isinstance(jwk, JsonWebKey): + jwk = JsonWebKey(**jwk) + return cls(jwk, object(), _jwk=True) @distributed_trace_async async def _initialize(self, **kwargs): diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index 608de82acb24..8884de5b3c1c 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -581,20 +581,16 @@ def test_local_only_mode_no_service_calls(): """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" mock_client = mock.Mock() - jwk = JsonWebKey() + jwk = JsonWebKey(kty="RSA", key_ops=[], n=b"10011", e=b"10001") client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client - supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch( - CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing - ): - with pytest.raises(NotImplementedError): - client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 with pytest.raises(NotImplementedError): - client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + client.encrypt(EncryptionAlgorithm.a256_gcm, b"...") assert mock_client.encrypt.call_count == 0 with pytest.raises(NotImplementedError): @@ -602,7 +598,7 @@ def test_local_only_mode_no_service_calls(): assert mock_client.sign.call_count == 0 with pytest.raises(NotImplementedError): - client.verify(SignatureAlgorithm.rs256, b"...", b"...") + client.verify(SignatureAlgorithm.es256, b"...", b"...") assert mock_client.verify.call_count == 0 with pytest.raises(NotImplementedError): @@ -610,7 +606,7 @@ def test_local_only_mode_no_service_calls(): assert mock_client.unwrap_key.call_count == 0 with pytest.raises(NotImplementedError): - client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + client.wrap_key(KeyWrapAlgorithm.aes_256, b"...") assert mock_client.wrap_key.call_count == 0 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index 5c00ff1b03ee..785094774e65 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -606,20 +606,16 @@ async def test_local_only_mode_no_service_calls(): """A local-only CryptographyClient shouldn't call the service if an operation can't be performed locally""" mock_client = mock.Mock() - jwk = JsonWebKey() + jwk = JsonWebKey(kty="RSA", key_ops=[], n=b"10011", e=b"10001") client = CryptographyClient.from_jwk(jwk=jwk) client._client = mock_client - supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch( - CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing - ): - with pytest.raises(NotImplementedError): - await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") + with pytest.raises(NotImplementedError): + await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 with pytest.raises(NotImplementedError): - await client.encrypt(EncryptionAlgorithm.rsa_oaep, b"...") + await client.encrypt(EncryptionAlgorithm.a256_gcm, b"...") assert mock_client.encrypt.call_count == 0 with pytest.raises(NotImplementedError): @@ -627,7 +623,7 @@ async def test_local_only_mode_no_service_calls(): assert mock_client.sign.call_count == 0 with pytest.raises(NotImplementedError): - await client.verify(SignatureAlgorithm.rs256, b"...", b"...") + await client.verify(SignatureAlgorithm.es256, b"...", b"...") assert mock_client.verify.call_count == 0 with pytest.raises(NotImplementedError): @@ -635,7 +631,7 @@ async def test_local_only_mode_no_service_calls(): assert mock_client.unwrap_key.call_count == 0 with pytest.raises(NotImplementedError): - await client.wrap_key(KeyWrapAlgorithm.rsa_oaep, b"...") + await client.wrap_key(KeyWrapAlgorithm.aes_256, b"...") assert mock_client.wrap_key.call_count == 0 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py b/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py index eb4413e61b13..14faf3ea81ae 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py @@ -4,7 +4,7 @@ # ------------------------------------ import functools -from azure.keyvault.keys import JsonWebKey, KeyClient +from azure.keyvault.keys import JsonWebKey, KeyClient, KeyOperation from azure.keyvault.keys.crypto import CryptographyClient from azure.keyvault.keys._shared import HttpChallengeCache from devtools_testutils import PowerShellPreparer @@ -21,11 +21,11 @@ def test_create_client_from_jwk(): # [START from_jwk] # create a CryptographyClient using a JsonWebKey instance - key = JsonWebKey(kty="RSA") + key = JsonWebKey(kty="RSA", key_ops=[KeyOperation.encrypt], n=b"10011", e=b"10001") crypto_client = CryptographyClient.from_jwk(jwk=key) # or a dictionary with JsonWebKey properties - key_dict = {"kty":"RSA"} + key_dict = {"kty":"RSA", "key_ops":[KeyOperation.encrypt], "n":b"10011", "e":b"10001"} crypto_client = CryptographyClient.from_jwk(jwk=key_dict) # [END from_jwk] From 5ca931ddc6b988d38fbc4cffa3414b86951beca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Tue, 9 Mar 2021 14:59:19 -0800 Subject: [PATCH 16/18] Address feedback --- .../azure/keyvault/keys/crypto/_client.py | 15 ++++----------- .../keys/crypto/_providers/__init__.py | 11 +++++------ .../keys/crypto/_providers/local_provider.py | 19 +++++++++---------- .../azure/keyvault/keys/crypto/aio/_client.py | 16 +++++----------- sdk/keyvault/azure-keyvault-keys/setup.py | 1 + .../tests/test_crypto_client.py | 15 +++++---------- .../tests/test_crypto_client_async.py | 15 +++++---------- .../tests/test_examples_crypto.py | 14 +------------- .../tests/test_local_crypto.py | 3 ++- 9 files changed, 37 insertions(+), 72 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py index ed5a1bcbb73d..490c26d314eb 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py @@ -128,7 +128,7 @@ def __init__(self, key, credential, **kwargs): self._local_provider = get_local_cryptography_provider(self._key) self._initialized = True except Exception as ex: # pylint:disable=broad-except - raise ValueError("The provided jwk is not valid for local cryptography: {}".format(ex)) + six.raise_from(ValueError("The provided jwk is not valid for local cryptography"), ex) else: self._local_provider = NoLocalCryptography() self._initialized = False @@ -145,7 +145,7 @@ def key_id(self): This property may be None when a client is constructed with :func:`from_jwk`. - :rtype: str + :rtype: str or None """ if not self._jwk: return self._key_id.source_id @@ -158,7 +158,7 @@ def vault_url(self): This property may be None when a client is constructed with :func:`from_jwk`. - :rtype: str + :rtype: str or None """ return self._vault_url @@ -170,13 +170,6 @@ def from_jwk(cls, jwk): :param jwk: the key's cryptographic material, as a JsonWebKey or dictionary. :type jwk: JsonWebKey or dict :rtype: CryptographyClient - - .. literalinclude:: ../tests/test_examples_crypto.py - :start-after: [START from_jwk] - :end-before: [END from_jwk] - :caption: Create a CryptographyClient from a JsonWebKey - :language: python - :dedent: 8 """ if not isinstance(jwk, JsonWebKey): jwk = JsonWebKey(**jwk) @@ -202,7 +195,7 @@ def _initialize(self, **kwargs): # if we have the key material, create a local crypto provider with it if self._key: - self._local_provider = get_local_cryptography_provider(self._key, _key_id=self.key_id) + self._local_provider = get_local_cryptography_provider(self._key) self._initialized = True else: # try to get the key again next time unless we know we're forbidden to do so diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py index 0b2a3571a9e8..f13ec67b4dba 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py @@ -11,18 +11,17 @@ from ... import KeyType if TYPE_CHECKING: - from typing import Any from ... import JsonWebKey -def get_local_cryptography_provider(key, **kwargs): - # type: (JsonWebKey, **Any) -> LocalCryptographyProvider +def get_local_cryptography_provider(key): + # type: (JsonWebKey) -> LocalCryptographyProvider if key.kty in (KeyType.ec, KeyType.ec_hsm): - return EllipticCurveCryptographyProvider(key, **kwargs) + return EllipticCurveCryptographyProvider(key) if key.kty in (KeyType.rsa, KeyType.rsa_hsm): - return RsaCryptographyProvider(key, **kwargs) + return RsaCryptographyProvider(key) if key.kty in (KeyType.oct, KeyType.oct_hsm): - return SymmetricCryptographyProvider(key, **kwargs) + return SymmetricCryptographyProvider(key) raise ValueError('Unsupported key type "{}"'.format(key.kty)) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py index 96355c30dba4..e2e26cd929fe 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/local_provider.py @@ -26,12 +26,11 @@ class LocalCryptographyProvider(ABC): - def __init__(self, key, **kwargs): + def __init__(self, key): # type: (JsonWebKey, **Any) -> None self._allowed_ops = frozenset(key.key_ops or []) self._internal_key = self._get_internal_key(key) self._key = key - self._key_id = kwargs.pop("_key_id", None) or key.kid @abc.abstractmethod def _get_internal_key(self, key): @@ -48,9 +47,9 @@ def key_id(self): # type: () -> Optional[str] """The full identifier of the provider's key. - :rtype: str + :rtype: str or None """ - return self._key_id + return self._key.kid def _raise_if_unsupported(self, operation, algorithm): # type: (KeyOperation, Algorithm) -> None @@ -65,34 +64,34 @@ def encrypt(self, algorithm, plaintext): # type: (EncryptionAlgorithm, bytes) -> EncryptResult self._raise_if_unsupported(KeyOperation.encrypt, algorithm) ciphertext = self._internal_key.encrypt(plaintext, algorithm=algorithm.value) - return EncryptResult(key_id=self._key_id, algorithm=algorithm, ciphertext=ciphertext) + return EncryptResult(key_id=self._key.kid, algorithm=algorithm, ciphertext=ciphertext) def decrypt(self, algorithm, ciphertext): # type: (EncryptionAlgorithm, bytes) -> DecryptResult self._raise_if_unsupported(KeyOperation.decrypt, algorithm) plaintext = self._internal_key.decrypt(ciphertext, iv=None, algorithm=algorithm.value) - return DecryptResult(key_id=self._key_id, algorithm=algorithm, plaintext=plaintext) + return DecryptResult(key_id=self._key.kid, algorithm=algorithm, plaintext=plaintext) def wrap_key(self, algorithm, key): # type: (KeyWrapAlgorithm, bytes) -> WrapResult self._raise_if_unsupported(KeyOperation.wrap_key, algorithm) encrypted_key = self._internal_key.wrap_key(key, algorithm=algorithm.value) - return WrapResult(key_id=self._key_id, algorithm=algorithm, encrypted_key=encrypted_key) + return WrapResult(key_id=self._key.kid, algorithm=algorithm, encrypted_key=encrypted_key) def unwrap_key(self, algorithm, encrypted_key): # type: (KeyWrapAlgorithm, bytes) -> UnwrapResult self._raise_if_unsupported(KeyOperation.unwrap_key, algorithm) unwrapped_key = self._internal_key.unwrap_key(encrypted_key, algorithm=algorithm.value) - return UnwrapResult(key_id=self._key_id, algorithm=algorithm, key=unwrapped_key) + return UnwrapResult(key_id=self._key.kid, algorithm=algorithm, key=unwrapped_key) def sign(self, algorithm, digest): # type: (SignatureAlgorithm, bytes) -> SignResult self._raise_if_unsupported(KeyOperation.sign, algorithm) signature = self._internal_key.sign(digest, algorithm=algorithm.value) - return SignResult(key_id=self._key_id, algorithm=algorithm, signature=signature) + return SignResult(key_id=self._key.kid, algorithm=algorithm, signature=signature) def verify(self, algorithm, digest, signature): # type: (SignatureAlgorithm, bytes, bytes) -> VerifyResult self._raise_if_unsupported(KeyOperation.verify, algorithm) is_valid = self._internal_key.verify(digest, signature, algorithm=algorithm.value) - return VerifyResult(key_id=self._key_id, algorithm=algorithm, is_valid=is_valid) + return VerifyResult(key_id=self._key.kid, algorithm=algorithm, is_valid=is_valid) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index 38ea784b082e..db010688a6dd 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -5,6 +5,7 @@ import logging from typing import TYPE_CHECKING +import six from azure.core.exceptions import HttpResponseError from azure.core.tracing.decorator_async import distributed_trace_async @@ -83,7 +84,7 @@ def __init__(self, key: "Union[KeyVaultKey, str]", credential: "AsyncTokenCreden self._local_provider = get_local_cryptography_provider(self._key) self._initialized = True except Exception as ex: # pylint:disable=broad-except - raise ValueError("The provided jwk is not valid for local cryptography: {}".format(ex)) + raise ValueError("The provided jwk is not valid for local cryptography") from ex else: self._local_provider = NoLocalCryptography() self._initialized = False @@ -97,7 +98,7 @@ def key_id(self) -> "Optional[str]": This property may be None when a client is constructed with :func:`from_jwk`. - :rtype: str + :rtype: str or None """ if not self._jwk: return self._key_id.source_id @@ -109,7 +110,7 @@ def vault_url(self) -> "Optional[str]": This property may be None when a client is constructed with :func:`from_jwk`. - :rtype: str + :rtype: str or None """ return self._vault_url @@ -120,13 +121,6 @@ def from_jwk(cls, jwk: "Union[JsonWebKey, dict]") -> "CryptographyClient": :param jwk: the key's cryptographic material, as a JsonWebKey or dictionary. :type jwk: JsonWebKey or dict :rtype: CryptographyClient - - .. literalinclude:: ../tests/test_examples_crypto.py - :start-after: [START from_jwk] - :end-before: [END from_jwk] - :caption: Create a CryptographyClient from a JsonWebKey - :language: python - :dedent: 8 """ if not isinstance(jwk, JsonWebKey): jwk = JsonWebKey(**jwk) @@ -152,7 +146,7 @@ async def _initialize(self, **kwargs): # if we have the key material, create a local crypto provider with it if self._key: - self._local_provider = get_local_cryptography_provider(self._key, _key_id=self.key_id) + self._local_provider = get_local_cryptography_provider(self._key) self._initialized = True else: # try to get the key again next time unless we know we're forbidden to do so diff --git a/sdk/keyvault/azure-keyvault-keys/setup.py b/sdk/keyvault/azure-keyvault-keys/setup.py index 5ad7c9d35cfc..77804fd94872 100644 --- a/sdk/keyvault/azure-keyvault-keys/setup.py +++ b/sdk/keyvault/azure-keyvault-keys/setup.py @@ -85,6 +85,7 @@ "cryptography>=2.1.4", "msrest>=0.6.21", "azure-common~=1.1", + "six>=1.9.0" ], extras_require={ ":python_version<'3.0'": ["azure-keyvault-nspkg"], diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py index 8884de5b3c1c..6b7a79f3e1e4 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client.py @@ -483,7 +483,7 @@ def test_initialization_given_key(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: client.verify(SignatureAlgorithm.rs256, b"...", b"...") - get_provider.assert_called_once_with(key.key, _key_id=key.id) + get_provider.assert_called_once_with(key.key) assert mock_client.get_key.call_count == 0 @@ -503,9 +503,8 @@ def test_initialization_get_key_successful(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: client.verify(SignatureAlgorithm.rs256, b"...", b"...") - args, kwargs = get_provider.call_args - assert len(args) == 1 and isinstance(args[0], JsonWebKey) - assert len(kwargs) == 1 and kwargs["_key_id"] == key_id + args, _ = get_provider.call_args + assert len(args) == 1 and isinstance(args[0], JsonWebKey) and args[0].kid == key_id for _ in range(3): assert mock_client.get_key.call_count == 1 @@ -549,9 +548,7 @@ def test_calls_service_for_operations_unsupported_locally(): client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch( - CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing - ): + with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 1 assert supports_nothing.decrypt.call_count == 0 @@ -666,9 +663,7 @@ def test_prefers_local_provider(): client._client = mock_client supports_everything = mock.Mock(supports=mock.Mock(return_value=True)) - with mock.patch( - CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_everything - ): + with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_everything): client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 assert supports_everything.decrypt.call_count == 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py index 785094774e65..688fadac9263 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_crypto_client_async.py @@ -497,7 +497,7 @@ async def test_initialization_given_key(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") - get_provider.assert_called_once_with(key.key, _key_id=key.id) + get_provider.assert_called_once_with(key.key) assert mock_client.get_key.call_count == 0 @@ -518,9 +518,8 @@ async def test_initialization_get_key_successful(): with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider") as get_provider: await client.verify(SignatureAlgorithm.rs256, b"...", b"...") - args, kwargs = get_provider.call_args - assert len(args) == 1 and isinstance(args[0], JsonWebKey) - assert len(kwargs) == 1 and kwargs["_key_id"] == key_id + args, _ = get_provider.call_args + assert len(args) == 1 and isinstance(args[0], JsonWebKey) and args[0].kid == key_id for _ in range(3): assert mock_client.get_key.call_count == 1 @@ -573,9 +572,7 @@ async def __call__(self, *args, **kwargs): client._client = mock_client supports_nothing = mock.Mock(supports=mock.Mock(return_value=False)) - with mock.patch( - CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_nothing - ): + with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_nothing): await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 1 assert supports_nothing.decrypt.call_count == 0 @@ -693,9 +690,7 @@ async def test_prefers_local_provider(): client._client = mock_client supports_everything = mock.Mock(supports=mock.Mock(return_value=True)) - with mock.patch( - CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *args, **kwargs: supports_everything - ): + with mock.patch(CryptographyClient.__module__ + ".get_local_cryptography_provider", lambda *_: supports_everything): await client.decrypt(EncryptionAlgorithm.rsa_oaep, b"...") assert mock_client.decrypt.call_count == 0 assert supports_everything.decrypt.call_count == 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py b/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py index 14faf3ea81ae..c5f0da5b6517 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_examples_crypto.py @@ -4,7 +4,7 @@ # ------------------------------------ import functools -from azure.keyvault.keys import JsonWebKey, KeyClient, KeyOperation +from azure.keyvault.keys import KeyClient from azure.keyvault.keys.crypto import CryptographyClient from azure.keyvault.keys._shared import HttpChallengeCache from devtools_testutils import PowerShellPreparer @@ -18,18 +18,6 @@ ) -def test_create_client_from_jwk(): - # [START from_jwk] - # create a CryptographyClient using a JsonWebKey instance - key = JsonWebKey(kty="RSA", key_ops=[KeyOperation.encrypt], n=b"10011", e=b"10001") - crypto_client = CryptographyClient.from_jwk(jwk=key) - - # or a dictionary with JsonWebKey properties - key_dict = {"kty":"RSA", "key_ops":[KeyOperation.encrypt], "n":b"10011", "e":b"10001"} - crypto_client = CryptographyClient.from_jwk(jwk=key_dict) - # [END from_jwk] - - class TestCryptoExamples(KeyVaultTestCase): def __init__(self, *args, **kwargs): kwargs["match_body"] = False diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py b/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py index bf83b314ecf7..96b81fc30947 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_local_crypto.py @@ -67,7 +67,8 @@ def test_rsa_sign_verify(key, algorithm, hash_function): @pytest.mark.parametrize("algorithm", (a for a in KeyWrapAlgorithm if a.startswith("RSA"))) def test_rsa_wrap_unwrap(key, algorithm): plaintext = b"arbitrary bytes" - provider = get_local_cryptography_provider(key.key, _key_id=key.id) + key.key.kid = key.id + provider = get_local_cryptography_provider(key.key) wrap_result = provider.wrap_key(algorithm, plaintext) assert wrap_result.key_id == key.id From 08f593528691f105376195bf61d5401c224172b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Tue, 9 Mar 2021 15:34:34 -0800 Subject: [PATCH 17/18] Satisfy frozen six requirement --- sdk/keyvault/azure-keyvault-keys/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-keys/setup.py b/sdk/keyvault/azure-keyvault-keys/setup.py index 77804fd94872..8596c3b955c2 100644 --- a/sdk/keyvault/azure-keyvault-keys/setup.py +++ b/sdk/keyvault/azure-keyvault-keys/setup.py @@ -85,7 +85,7 @@ "cryptography>=2.1.4", "msrest>=0.6.21", "azure-common~=1.1", - "six>=1.9.0" + "six>=1.11.0" ], extras_require={ ":python_version<'3.0'": ["azure-keyvault-nspkg"], From 8afbfe20eba0cdfacfbe84e47d2ddec7f27383f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Tue, 9 Mar 2021 16:05:48 -0800 Subject: [PATCH 18/18] Remove unused import --- .../azure/keyvault/keys/crypto/aio/_client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py index db010688a6dd..1f785f9dcbee 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py @@ -5,7 +5,6 @@ import logging from typing import TYPE_CHECKING -import six from azure.core.exceptions import HttpResponseError from azure.core.tracing.decorator_async import distributed_trace_async