From 97d0a99b70ac665930dbc1142b722edcb25db3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Tue, 13 Apr 2021 15:19:27 -0700 Subject: [PATCH 1/4] Add public_exponent kwarg --- .../azure/keyvault/keys/_client.py | 4 +- .../azure/keyvault/keys/aio/_client.py | 4 +- ..._client.test_rsa_public_exponent_mhsm.yaml | 89 +++++++++++++++++++ ...s_async.test_rsa_public_exponent_mhsm.yaml | 64 +++++++++++++ .../tests/test_key_client.py | 16 +++- .../tests/test_keys_async.py | 17 +++- 6 files changed, 190 insertions(+), 4 deletions(-) create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_key_client.test_rsa_public_exponent_mhsm.yaml create mode 100644 sdk/keyvault/azure-keyvault-keys/tests/recordings/test_keys_async.test_rsa_public_exponent_mhsm.yaml diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py index 2738528d1b88..c2d1e00012a9 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py @@ -60,6 +60,7 @@ def create_key(self, name, key_type, **kwargs): :keyword curve: Elliptic curve name. Applies only to elliptic curve keys. Defaults to the NIST P-256 elliptic curve. To create an elliptic curve key, consider using :func:`create_ec_key` instead. :paramtype curve: ~azure.keyvault.keys.KeyCurveName or str + :keyword int public_exponent: The RSA public exponent to use. Applies only to RSA keys created in a Managed HSM. :keyword key_operations: Allowed key operations :paramtype key_operations: list[~azure.keyvault.keys.KeyOperation or str] :keyword bool enabled: Whether the key is enabled for use. @@ -93,7 +94,8 @@ def create_key(self, name, key_type, **kwargs): key_attributes=attributes, key_ops=kwargs.pop("key_operations", None), tags=kwargs.pop("tags", None), - curve=kwargs.pop("curve", None) + curve=kwargs.pop("curve", None), + public_exponent=kwargs.pop("public_exponent", None) ) bundle = self._client.create_key( diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py index 3b7b1cf070f6..92a8d3615829 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py @@ -58,6 +58,7 @@ async def create_key(self, name: str, key_type: "Union[str, KeyType]", **kwargs: :keyword curve: Elliptic curve name. Applies only to elliptic curve keys. Defaults to the NIST P-256 elliptic curve. To create an elliptic curve key, consider using :func:`create_ec_key` instead. :paramtype curve: ~azure.keyvault.keys.KeyCurveName or str + :keyword int public_exponent: The RSA public exponent to use. Applies only to RSA keys created in a Managed HSM. :keyword key_operations: Allowed key operations :paramtype key_operations: list[~azure.keyvault.keys.KeyOperation or str] :keyword bool enabled: Whether the key is enabled for use. @@ -92,7 +93,8 @@ async def create_key(self, name: str, key_type: "Union[str, KeyType]", **kwargs: key_attributes=attributes, key_ops=kwargs.pop("key_operations", None), tags=kwargs.pop("tags", None), - curve=kwargs.pop("curve", None) + curve=kwargs.pop("curve", None), + public_exponent=kwargs.pop("public_exponent", None) ) bundle = await self._client.create_key( diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_key_client.test_rsa_public_exponent_mhsm.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_key_client.test_rsa_public_exponent_mhsm.yaml new file mode 100644 index 000000000000..097872d0431e --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_key_client.test_rsa_public_exponent_mhsm.yaml @@ -0,0 +1,89 @@ +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.0b5 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://managedhsmname.managedhsm.azure.net/keys/livekvtestrsa-keyaa84129c/create?api-version=7.2-preview + response: + body: + string: '' + headers: + cache-control: + - no-cache + content-length: + - '0' + content-security-policy: + - default-src 'self' + content-type: + - application/json; charset=utf-8 + strict-transport-security: + - max-age=31536000; includeSubDomains + www-authenticate: + - Bearer authorization="https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://managedhsm.azure.net" + x-content-type-options: + - nosniff + x-frame-options: + - SAMEORIGIN + x-ms-server-latency: + - '1' + status: + code: 401 + message: Unauthorized +- request: + body: '{"public_exponent": 17, "kty": "RSA-HSM"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '41' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b5 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://managedhsmname.managedhsm.azure.net/keys/livekvtestrsa-keyaa84129c/create?api-version=7.2-preview + response: + body: + string: '{"attributes":{"created":1618353119,"enabled":true,"exportable":false,"recoverableDays":90,"recoveryLevel":"Recoverable+Purgeable","updated":1618353119},"key":{"e":"EQ","key_ops":["wrapKey","decrypt","encrypt","unwrapKey","sign","verify"],"kid":"https://managedhsmname.managedhsm.azure.net/keys/livekvtestrsa-keyaa84129c/a63a1a240ff003079a3a50fb3116302b","kty":"RSA-HSM","n":"nO6rF2ru8HUAHbf2VyzVge6ic77k_Ju2VGuMKhNaX4nac8S2jMfHOYfkCmNi_NuZ_RUSYEkjtwwwh5LkAKwGP6AjKkEESbZiOyeBPi5bJB5A9g0-JKDT1Yudpnl4nBoXZinhvj0Dgr0LS38r-vu6wJjt_w_37Ofiun_sFCJcLGUfqN6KSGBbAE4XscLOY3GRUl1E3Mcq232R4yRxWsEhGmMDOVEM5VocRUiZOD-LRc0QclHQYX1lwto93UX272VVx5BrRTAtf9XZdTnWajk7xM-JXlYkkhon5KmdTavFL0pMGv23mnSjIMFT5sUPXanEYkwM1RqSJWnIRt2YoyVCzQ"}}' + headers: + cache-control: + - no-cache + content-length: + - '722' + content-security-policy: + - default-src 'self' + content-type: + - application/json; charset=utf-8 + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-frame-options: + - SAMEORIGIN + x-ms-keyvault-network-info: + - conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=Ipv4; + x-ms-keyvault-region: + - eastus2 + x-ms-server-latency: + - '1041' + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_keys_async.test_rsa_public_exponent_mhsm.yaml b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_keys_async.test_rsa_public_exponent_mhsm.yaml new file mode 100644 index 000000000000..2ac25a6c7921 --- /dev/null +++ b/sdk/keyvault/azure-keyvault-keys/tests/recordings/test_keys_async.test_rsa_public_exponent_mhsm.yaml @@ -0,0 +1,64 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b5 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://managedhsmname.managedhsm.azure.net/keys/livekvtestrsa-keyad3012ae/create?api-version=7.2-preview + response: + body: + string: '' + headers: + cache-control: no-cache + content-length: '0' + content-security-policy: default-src 'self' + content-type: application/json; charset=utf-8 + strict-transport-security: max-age=31536000; includeSubDomains + www-authenticate: Bearer authorization="https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47", + resource="https://managedhsm.azure.net" + x-content-type-options: nosniff + x-frame-options: SAMEORIGIN + x-ms-server-latency: '1' + status: + code: 401 + message: Unauthorized + url: https://mcpatinotesthsm.managedhsm.azure.net/keys/livekvtestrsa-keyad3012ae/create?api-version=7.2-preview +- request: + body: '{"public_exponent": 17, "kty": "RSA-HSM"}' + headers: + Accept: + - application/json + Content-Length: + - '41' + Content-Type: + - application/json + User-Agent: + - azsdk-python-keyvault-keys/4.4.0b5 Python/3.5.3 (Windows-10-10.0.19041-SP0) + method: POST + uri: https://managedhsmname.managedhsm.azure.net/keys/livekvtestrsa-keyad3012ae/create?api-version=7.2-preview + response: + body: + string: '{"attributes":{"created":1618353643,"enabled":true,"exportable":false,"recoverableDays":90,"recoveryLevel":"Recoverable+Purgeable","updated":1618353643},"key":{"e":"EQ","key_ops":["wrapKey","decrypt","encrypt","unwrapKey","sign","verify"],"kid":"https://managedhsmname.managedhsm.azure.net/keys/livekvtestrsa-keyad3012ae/d0b837d03f9c069780c5d37fd8bce435","kty":"RSA-HSM","n":"nIkUlKQZuvk31cPRCAzYoHZ-lHpSBUHLfSPQsPpyy5LpUrJPHFozMNUAZ2VUKR_-9S17Znn5CVwbAKXfXPx-5dsq6_hqjvfMtwoWJDU4tPa5vqS-SxZQ-CTYj8N4N1rx2qyF5Z18OSwZGQ3up7vl8RsPSeI1SEIhHWPIg6A4VLe0VhByiYXyOIZeDm7MVnpeisQMgaQoiObgYYzN5xBpbGSFd2_7H-AivK58BgRGoAzfd_FXVS1a9244hHH3gFy7oSo3ccPZyI_kKjXlB4kTmvvZBdQeVbWOeaNDemxsH8TsJy1yR9V1lwkZ08M19iYYbYtomeLpAcws46kPWc-wjQ"}}' + headers: + cache-control: no-cache + content-length: '722' + content-security-policy: default-src 'self' + content-type: application/json; charset=utf-8 + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + x-frame-options: SAMEORIGIN + x-ms-keyvault-network-info: conn_type=Ipv4;addr=172.92.159.124;act_addr_fam=Ipv4; + x-ms-keyvault-region: eastus2 + x-ms-server-latency: '812' + status: + code: 200 + message: OK + url: https://mcpatinotesthsm.managedhsm.azure.net/keys/livekvtestrsa-keyad3012ae/create?api-version=7.2-preview +version: 1 diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py b/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py index 99bbf9ef0770..bed39ec7eaa1 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_key_client.py @@ -11,8 +11,9 @@ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.keyvault.keys import JsonWebKey, KeyClient, KeyCurveName +from azure.keyvault.keys import JsonWebKey, KeyClient from parameterized import parameterized, param +from six import byte2int from _shared.test_case import KeyVaultTestCase from _test_case import KeysTestCase, suffixed_test_name @@ -196,6 +197,19 @@ def test_key_crud_operations(self, **kwargs): self.assertIsNotNone(deleted_key) self.assertEqual(rsa_key.id, deleted_key.id) + def test_rsa_public_exponent_mhsm(self, **kwargs): + """The public exponent of a Managed HSM RSA key can be specified during creation""" + self._skip_if_not_configured(True) + endpoint_url = self.managed_hsm_url + + client = self.create_key_client(endpoint_url) + self.assertIsNotNone(client) + + key_name = self.get_resource_name("rsa-key") + key = self._create_rsa_key(client, key_name, hardware_protected=True, public_exponent=17) + public_exponent = byte2int(key.key.e) + assert public_exponent == 17 + @parameterized.expand([param(is_hsm=b) for b in [True, False]], name_func=suffixed_test_name) def test_backup_restore(self, **kwargs): is_hsm = kwargs.pop("is_hsm") diff --git a/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py b/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py index a92762ce6bd7..52ce74ff22fb 100644 --- a/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py +++ b/sdk/keyvault/azure-keyvault-keys/tests/test_keys_async.py @@ -11,10 +11,11 @@ from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError from azure.core.pipeline.policies import SansIOHTTPPolicy -from azure.keyvault.keys import JsonWebKey, KeyCurveName +from azure.keyvault.keys import JsonWebKey from azure.keyvault.keys.aio import KeyClient from devtools_testutils import PowerShellPreparer from parameterized import parameterized, param +from six import byte2int from _shared.test_case_async import KeyVaultTestCase from _test_case import KeysTestCase, suffixed_test_name @@ -228,6 +229,20 @@ async def test_key_crud_operations(self, **kwargs): self.assertIsNotNone(deleted_key) self.assertEqual(rsa_key.id, deleted_key.id) + @PowerShellPreparer("keyvault") + async def test_rsa_public_exponent_mhsm(self, **kwargs): + """The public exponent of a Managed HSM RSA key can be specified during creation""" + self._skip_if_not_configured(True) + endpoint_url = self.managed_hsm_url + + client = self.create_key_client(endpoint_url, is_async=True) + self.assertIsNotNone(client) + + key_name = self.get_resource_name("rsa-key") + key = await self._create_rsa_key(client, key_name, hardware_protected=True, public_exponent=17) + public_exponent = byte2int(key.key.e) + assert public_exponent == 17 + @parameterized.expand([param(is_hsm=b) for b in [True, False]], name_func=suffixed_test_name) @PowerShellPreparer("keyvault") async def test_backup_restore(self, **kwargs): From 6065f08a05cb5037236cb331add6fc4d1824580e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Tue, 13 Apr 2021 16:33:46 -0700 Subject: [PATCH 2/4] Update pipeline config --- sdk/keyvault/azure-keyvault-keys/platform-matrix.json | 10 +++++----- sdk/keyvault/test-resources-post.ps1 | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sdk/keyvault/azure-keyvault-keys/platform-matrix.json b/sdk/keyvault/azure-keyvault-keys/platform-matrix.json index a17e208b5fc5..c97e83c8d3fc 100644 --- a/sdk/keyvault/azure-keyvault-keys/platform-matrix.json +++ b/sdk/keyvault/azure-keyvault-keys/platform-matrix.json @@ -2,11 +2,11 @@ "include": [ { "Agent": { - "ubuntu-18.04": { - "OSVmImage": "MMSUbuntu18.04", - "Pool": "azsdk-pool-mms-ubuntu-1804-general", - "ArmTemplateParameters": "@{ enableHsm = $true }" - } + "ubuntu-18.04_ManagedHSM": { + "OSVmImage": "MMSUbuntu18.04", + "Pool": "azsdk-pool-mms-ubuntu-1804-general", + "ArmTemplateParameters": "@{ enableHsm = $true }" + } }, "PythonVersion": "3.9", "CoverageArg": "" diff --git a/sdk/keyvault/test-resources-post.ps1 b/sdk/keyvault/test-resources-post.ps1 index d1893330cb84..a759b97a5c84 100644 --- a/sdk/keyvault/test-resources-post.ps1 +++ b/sdk/keyvault/test-resources-post.ps1 @@ -108,10 +108,10 @@ az keyvault security-domain download --hsm-name $hsmName --security-domain-file Log "Security domain downloaded to '$sdPath'; Managed HSM is now active at '$hsmUrl'" # Force a sleep to wait for Managed HSM activation to propagate through Cosmos replication. Issue tracked in AzDo. -Log "Sleeping for 30 seconds to allow activation to propagate..." -Start-Sleep -Seconds 30 +Log "Sleeping for 120 seconds to allow activation to propagate..." +Start-Sleep -Seconds 120 Log "Creating additional required role assignments for resource access." -New-AzKeyVaultRoleAssignment -HsmName $hsmName -RoleDefinitionName "Managed HSM Crypto Officer" -ObjectID $DeploymentOutputs["CLIENT_OBJECT_ID"] -New-AzKeyVaultRoleAssignment -HsmName $hsmName -RoleDefinitionName "Managed HSM Crypto User" -ObjectID $DeploymentOutputs["CLIENT_OBJECT_ID"] +New-AzKeyVaultRoleAssignment -HsmName $hsmName -RoleDefinitionName "Managed HSM Crypto Officer" -ObjectID $DeploymentOutputs["CLIENT_OBJECTID"] +New-AzKeyVaultRoleAssignment -HsmName $hsmName -RoleDefinitionName "Managed HSM Crypto User" -ObjectID $DeploymentOutputs["CLIENT_OBJECTID"] Log "Done." From ae491c203b73a160293f7f7574392387f961bf7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Wed, 14 Apr 2021 18:21:48 -0700 Subject: [PATCH 3/4] Thanks, Charles! --- sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py | 1 + .../azure-keyvault-keys/azure/keyvault/keys/aio/_client.py | 1 + 2 files changed, 2 insertions(+) diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py index c2d1e00012a9..6fd98797d9d6 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/_client.py @@ -116,6 +116,7 @@ def create_rsa_key(self, name, **kwargs): :param str name: The name for the new key. :keyword int size: Key size in bits, for example 2048, 3072, or 4096. + :keyword int public_exponent: The RSA public exponent to use. Applies only to RSA keys created in a Managed HSM. :keyword bool hardware_protected: Whether the key should be created in a hardware security module. Defaults to ``False``. :keyword key_operations: Allowed key operations diff --git a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py index 92a8d3615829..53f7e218c602 100644 --- a/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py +++ b/sdk/keyvault/azure-keyvault-keys/azure/keyvault/keys/aio/_client.py @@ -114,6 +114,7 @@ async def create_rsa_key(self, name: str, **kwargs: "Any") -> KeyVaultKey: :param str name: The name for the new key. :keyword int size: Key size in bits, for example 2048, 3072, or 4096. + :keyword int public_exponent: The RSA public exponent to use. Applies only to RSA keys created in a Managed HSM. :keyword bool hardware_protected: Whether the key should be created in a hardware security module. Defaults to ``False``. :keyword key_operations: Allowed key operations From bb4034b244530b74ed4d8f718ab196cf0a8ebf18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?McCoy=20Pati=C3=B1o?= Date: Fri, 16 Apr 2021 10:42:57 -0700 Subject: [PATCH 4/4] Thanks, Ben! --- eng/pipelines/templates/jobs/live.tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/pipelines/templates/jobs/live.tests.yml b/eng/pipelines/templates/jobs/live.tests.yml index bd552430ae78..48466cf96480 100644 --- a/eng/pipelines/templates/jobs/live.tests.yml +++ b/eng/pipelines/templates/jobs/live.tests.yml @@ -119,7 +119,7 @@ jobs: Location: ${{ coalesce(parameters.Location, parameters.CloudConfig.Location) }} ServiceDirectory: '${{ parameters.ServiceDirectory }}' SubscriptionConfiguration: ${{ parameters.CloudConfig.SubscriptionConfiguration }} - ArmTemplateParameters: ${{ coalesce(parameters.CloudConfig.ArmTemplateParameters, '@{}') }} + ArmTemplateParameters: $(ArmTemplateParameters) - template: ../steps/build-test.yml parameters: