-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Key Vault] Add local-only mode to CryptographyClient #16565
Conversation
f3ef95b
to
22e32c4
Compare
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
22e32c4
to
1ee77f7
Compare
1ee77f7
to
41ef114
Compare
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
|
||
mock_client = mock.Mock() | ||
jwk = mock.Mock(spec=JsonWebKey) | ||
client = CryptographyClient.from_jwk(jwk=jwk) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We expect no request, so I would use a mock transport that raises when the client tries to send e.g.
mock.Mock(send=mock.Mock(side_effect=Exception("client shouldn't send a request"))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(That is, if it would be a bug for the client to send a request in local-only mode.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one that I've made a note of to revisit -- I'm not too familiar with Mock and wasn't able to randomly turn enough dials to get a better understanding. I figure that asserting that the underlying client doesn't call get_key is sufficient for the time being
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
cd63ab5
to
219f32f
Compare
219f32f
to
218a312
Compare
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_models.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
@@ -106,16 +107,20 @@ def __init__(self, key, credential, **kwargs): | |||
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything we need for local crypto is in the JWK. Do we really need to jam that into KeyVaultKey?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the local crypto providers and operations assume that they're working with a KeyVaultKey, so we'd have to do so unless we refactor them to accept a JsonWebKey (unless I'm mistaken)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's unreasonable by any means to make local providers accept JWKs, but it seems like a design question of whether we do that (and preserve the current definition of a KeyVaultKey) or make a smaller tweak to accept KeyVaultKeys intended for local-only use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that's what I'm getting at. Their expectation of KeyVaultKey appears to be driving additional complexity here but that expectation isn't a requirement. Actually they only need the JWK. If they took that up front, maybe it wouldn't be necessary to complicate KeyVaultKey?
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_providers/__init__.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_key_validity.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
"""The full identifier of the provider's key. | ||
|
||
:rtype: str | ||
""" | ||
return self._key.id | ||
return self._key_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be either a valid Key Vault identifier or whatever the user gave us:
return self._key_id | |
return self._key.get("kid") |
Does that remove the need to ask a caller to give us _key_id
separately?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking here is that a KeyVaultKey provided to CryptographyClient could have a valid Key Vault identifier for its id
, but that the JsonWebKey could have a different kid
. I assumed it made more sense to return the Key Vault identifier in the operation result if possible, which is why I added the _key_id
keyword argument
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would happen only when someone does KeyVaultKey(key_id, jwk=jwk)
with key_id != jwk["kid"]
. Granted, that is possible, but seems unlikely and given KeyVaultKey's docs ask for a Key Vault identifier for key_id, it seems reasonable not to special case it. My $0.02 🤑
e670d05
to
801ba6d
Compare
801ba6d
to
fb36a25
Compare
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/_client.py
Outdated
Show resolved
Hide resolved
"""The full identifier of the provider's key. | ||
|
||
:rtype: str | ||
""" | ||
return self._key.id | ||
return self._key_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would happen only when someone does KeyVaultKey(key_id, jwk=jwk)
with key_id != jwk["kid"]
. Granted, that is possible, but seems unlikely and given KeyVaultKey's docs ask for a Key Vault identifier for key_id, it seems reasonable not to special case it. My $0.02 🤑
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py
Outdated
Show resolved
Hide resolved
6c843b8
to
5ca931d
Compare
sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/crypto/aio/_client.py
Outdated
Show resolved
Hide resolved
@@ -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): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also possible to test private operations locally, using an imported key for public operations (the neighboring keys.py
has suitable keys). Doesn't need to be in this PR but it's a test gap to fill before the next stable release. Also, need to cover EC keys as well.
status: | ||
code: 401 | ||
message: Unauthorized | ||
url: https://mcpatinokv.vault.azure.net/keys/livekvtestwrap-localfe02144b/create?api-version=7.2-preview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know why we've stopped replacing the vault name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vault names aren't being replaced in responses with the PowerShellPreparer -- this is another item on my list of things to investigate 🕵️♀️
Fix Swagger for SecurityInsights - Add teamInformation to IncidentProperties (Azure#16565)
Resolves #16619.
Aligns Python's CryptographyClient with other languages, in providing a local-only mode by means of a factory method.