diff --git a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp index b68c7d3c89..f31a7bef45 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp +++ b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client.hpp @@ -409,6 +409,21 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { ImportKeyOptions const& importKeyOptions, Azure::Core::Context const& context = Azure::Core::Context()) const; + /** + * @brief Creates a new key version, stores it, then returns key parameters, attributes and + * policy to the client. + * + * @remark The operation will rotate the key based on the key policy. It requires the + * keys/rotate permission. + * + * @param name The name of the key + * @param context A #Azure::Core::Context controlling the request lifetime. + * @return Azure::Response + */ + Azure::Response RotateKey( + std::string const& name, + Azure::Core::Context const& context = Azure::Core::Context()) const; + /** * @brief Lists the policy for a key. * @@ -434,7 +449,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @param context A #Azure::Core::Context controlling the request lifetime. * @return Azure::Response */ - Azure::Response PutKeyRotationPolicy( + Azure::Response UpdateKeyRotationPolicy( std::string const& name, KeyRotationPolicy const& rotationPolicy, Azure::Core::Context const& context = Azure::Core::Context()) const; diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp index ca6621390c..505fdca574 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp @@ -381,6 +381,20 @@ Azure::Response KeyClient::ImportKey( return Azure::Response(std::move(value), std::move(rawResponse)); } +Azure::Response KeyClient::RotateKey( + std::string const& name, + Azure::Core::Context const& context) const +{ + // Request with no payload + auto request + = CreateRequest(HttpMethod::Post, {_detail::KeysPath, name, _detail::RotateActionsValue}); + + // Send and parse respone + auto rawResponse = SendRequest(request, context); + auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, *rawResponse); + return Azure::Response(std::move(value), std::move(rawResponse)); +} + Azure::Response KeyClient::GetKeyRotationPolicy( std::string const& name, Azure::Core::Context const& context) const @@ -395,7 +409,7 @@ Azure::Response KeyClient::GetKeyRotationPolicy( return Azure::Response(std::move(value), std::move(rawResponse)); } -Azure::Response KeyClient::PutKeyRotationPolicy( +Azure::Response KeyClient::UpdateKeyRotationPolicy( std::string const& name, KeyRotationPolicy const& rotationPolicy, Azure::Core::Context const& context) const diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_rotation_policy_test_live.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_rotation_policy_test_live.cpp index ef4f053f01..a7ff1235c4 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_rotation_policy_test_live.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_rotation_policy_test_live.cpp @@ -17,6 +17,29 @@ using namespace Azure; using namespace Azure::Security::KeyVault::Keys; using namespace Azure::Security::KeyVault::Keys::_detail; +TEST_F(KeyVaultKeyClient, RotateKey) +{ + auto const keyName = GetTestName(); + auto const& client = GetClientForTest(keyName); + + auto createKeyResponse = client.CreateEcKey(CreateEcKeyOptions(keyName)); + CheckValidResponse(createKeyResponse); + + std::string input + = "{\"id\":\"https://redacted.vault.azure.net/keys/GetKeyRotationPolicy/" + "rotationpolicy\",\"lifetimeActions\":[{\"trigger\":{\"timeAfterCreate\":\"P18M\"}," + "\"action\":{\"type\":\"Rotate\"}},{\"trigger\":{\"timeBeforeExpiry\":\"P30D\"},\"action\":" + "{\"type\":\"Notify\"}}],\"attributes\":{\"expiryTime\":\"P48M\",\"created\":1649797765," + "\"updated\":1649797765}}"; + + auto policy = KeyRotationPolicySerializer::KeyRotationPolicyDeserialize( + std::vector(input.begin(), input.end())); + + auto putPolicy = client.UpdateKeyRotationPolicy(keyName, policy).Value; + auto originalKey = client.GetKey(keyName); + auto rotatedKey = client.RotateKey(keyName); + EXPECT_NE(originalKey.Value.Properties.Version, rotatedKey.Value.Properties.Version); +} TEST_F(KeyVaultKeyClient, GetKeyRotationPolicy) { auto const keyName = GetTestName(); @@ -35,7 +58,7 @@ TEST_F(KeyVaultKeyClient, GetKeyRotationPolicy) auto policy = KeyRotationPolicySerializer::KeyRotationPolicyDeserialize( std::vector(input.begin(), input.end())); - auto putPolicy = client.PutKeyRotationPolicy(keyName, policy).Value; + auto putPolicy = client.UpdateKeyRotationPolicy(keyName, policy).Value; auto rotationPolicy = client.GetKeyRotationPolicy(keyName).Value; EXPECT_EQ(rotationPolicy.Attributes.ExpiryTime.Value(), policy.Attributes.ExpiryTime.Value()); diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/recordings/KeyVaultKeyClient.RotateKey.json b/sdk/keyvault/azure-security-keyvault-keys/test/ut/recordings/KeyVaultKeyClient.RotateKey.json new file mode 100644 index 0000000000..8f1aed813f --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/recordings/KeyVaultKeyClient.RotateKey.json @@ -0,0 +1,110 @@ +{ + "networkCallRecords": [ + { + "Headers": { + "content-type": "application/json", + "user-agent": "azsdk-cpp-keyvault-keys/4.3.0-beta.1 (Windows 10 Enterprise 6.3 22000 22000.1.amd64fre.co_release.210604-1628)", + "x-ms-client-request-id": "632e3568-6ec4-4b20-4bd5-185894de8d65" + }, + "Method": "POST", + "Response": { + "BODY": "{\"key\":{\"kid\":\"https://REDACTED.vault.azure.net/keys/RotateKey/df9e586eb0d94a2bae281d067a2c1e2d\",\"kty\":\"EC\",\"key_ops\":[\"sign\",\"verify\"],\"crv\":\"P-256\",\"x\":\"U_VctIPLKGs0ebSUXP_1RQgWP4__X1rmTIAzvY4-_yQ\",\"y\":\"sYN6Gcx_qyugxWFEmzeKitC9TSsiCMZ0S7SKR3PRj40\"},\"attributes\":{\"enabled\":true,\"exp\":1777413701,\"created\":1651183301,\"updated\":1651183301,\"recoveryLevel\":\"Recoverable+Purgeable\",\"recoverableDays\":90}}", + "REASON_PHRASE": "OK", + "STATUS_CODE": "200", + "cache-control": "no-cache", + "content-length": "403", + "content-type": "application/json; charset=utf-8", + "date": "Thu, 28 Apr 2022 22:01:41 GMT", + "expires": "-1", + "pragma": "no-cache", + "strict-transport-security": "max-age=31536000;includeSubDomains", + "x-content-type-options": "nosniff", + "x-ms-client-request-id": "632e3568-6ec4-4b20-4bd5-185894de8d65", + "x-ms-keyvault-network-info": "conn_type=Ipv4;addr=24.22.157.72;act_addr_fam=InterNetwork;", + "x-ms-keyvault-region": "westus3", + "x-ms-keyvault-service-version": "1.9.378.1", + "x-ms-request-id": "12a962c0-9b31-4fbb-9872-804e2cec4f8f" + }, + "Url": "https://REDACTED.vault.azure.net/keys/RotateKey/create?api-version=7.3" + }, + { + "Headers": { + "content-type": "application/json", + "user-agent": "azsdk-cpp-keyvault-keys/4.3.0-beta.1 (Windows 10 Enterprise 6.3 22000 22000.1.amd64fre.co_release.210604-1628)", + "x-ms-client-request-id": "80917450-ea33-487a-609a-3d502bcd975c" + }, + "Method": "PUT", + "Response": { + "BODY": "{\"id\":\"https://REDACTED.vault.azure.net/keys/RotateKey/rotationpolicy\",\"lifetimeActions\":[{\"trigger\":{\"timeAfterCreate\":\"P18M\"},\"action\":{\"type\":\"Rotate\"}},{\"trigger\":{\"timeBeforeExpiry\":\"P30D\"},\"action\":{\"type\":\"Notify\"}}],\"attributes\":{\"expiryTime\":\"P48M\",\"created\":1651182792,\"updated\":1651182792}}", + "REASON_PHRASE": "OK", + "STATUS_CODE": "200", + "cache-control": "no-cache", + "content-length": "303", + "content-type": "application/json; charset=utf-8", + "date": "Thu, 28 Apr 2022 22:01:41 GMT", + "expires": "-1", + "pragma": "no-cache", + "strict-transport-security": "max-age=31536000;includeSubDomains", + "x-content-type-options": "nosniff", + "x-ms-client-request-id": "80917450-ea33-487a-609a-3d502bcd975c", + "x-ms-keyvault-network-info": "conn_type=Ipv4;addr=24.22.157.72;act_addr_fam=InterNetwork;", + "x-ms-keyvault-region": "westus3", + "x-ms-keyvault-service-version": "1.9.378.1", + "x-ms-request-id": "24db8ffd-f721-4827-b569-9712b212e069" + }, + "Url": "https://REDACTED.vault.azure.net/keys/RotateKey/rotationpolicy?api-version=7.3" + }, + { + "Headers": { + "user-agent": "azsdk-cpp-keyvault-keys/4.3.0-beta.1 (Windows 10 Enterprise 6.3 22000 22000.1.amd64fre.co_release.210604-1628)", + "x-ms-client-request-id": "f16cc707-40b2-4e8a-5035-b332c7954c85" + }, + "Method": "GET", + "Response": { + "BODY": "{\"key\":{\"kid\":\"https://REDACTED.vault.azure.net/keys/RotateKey/df9e586eb0d94a2bae281d067a2c1e2d\",\"kty\":\"EC\",\"key_ops\":[\"sign\",\"verify\"],\"crv\":\"P-256\",\"x\":\"U_VctIPLKGs0ebSUXP_1RQgWP4__X1rmTIAzvY4-_yQ\",\"y\":\"sYN6Gcx_qyugxWFEmzeKitC9TSsiCMZ0S7SKR3PRj40\"},\"attributes\":{\"enabled\":true,\"exp\":1777413701,\"created\":1651183301,\"updated\":1651183301,\"recoveryLevel\":\"Recoverable+Purgeable\",\"recoverableDays\":90}}", + "REASON_PHRASE": "OK", + "STATUS_CODE": "200", + "cache-control": "no-cache", + "content-length": "403", + "content-type": "application/json; charset=utf-8", + "date": "Thu, 28 Apr 2022 22:01:41 GMT", + "expires": "-1", + "pragma": "no-cache", + "strict-transport-security": "max-age=31536000;includeSubDomains", + "x-content-type-options": "nosniff", + "x-ms-client-request-id": "f16cc707-40b2-4e8a-5035-b332c7954c85", + "x-ms-keyvault-network-info": "conn_type=Ipv4;addr=24.22.157.72;act_addr_fam=InterNetwork;", + "x-ms-keyvault-region": "westus3", + "x-ms-keyvault-service-version": "1.9.378.1", + "x-ms-request-id": "1a38162f-d03e-4a56-a766-63152fa7d7dc" + }, + "Url": "https://REDACTED.vault.azure.net/keys/RotateKey?api-version=7.3" + }, + { + "Headers": { + "user-agent": "azsdk-cpp-keyvault-keys/4.3.0-beta.1 (Windows 10 Enterprise 6.3 22000 22000.1.amd64fre.co_release.210604-1628)", + "x-ms-client-request-id": "fed4ae56-7898-468f-5427-af1ed528565c" + }, + "Method": "POST", + "Response": { + "BODY": "{\"key\":{\"kid\":\"https://REDACTED.vault.azure.net/keys/RotateKey/05105ef03138429b8df43e0835f8218c\",\"kty\":\"EC\",\"key_ops\":[\"sign\",\"verify\"],\"crv\":\"P-256\",\"x\":\"jMNIidUSEqH4KQQHCiunDQsxCRLSK4i2Auz1DGOtTo0\",\"y\":\"bMXg2Xb_QDnnEq71piF1HhUrb-priRx6mxt0aFNYO-s\"},\"attributes\":{\"enabled\":true,\"exp\":1777413702,\"created\":1651183302,\"updated\":1651183302,\"recoveryLevel\":\"Recoverable+Purgeable\",\"recoverableDays\":90}}", + "REASON_PHRASE": "OK", + "STATUS_CODE": "200", + "cache-control": "no-cache", + "content-length": "403", + "content-type": "application/json; charset=utf-8", + "date": "Thu, 28 Apr 2022 22:01:41 GMT", + "expires": "-1", + "pragma": "no-cache", + "strict-transport-security": "max-age=31536000;includeSubDomains", + "x-content-type-options": "nosniff", + "x-ms-client-request-id": "fed4ae56-7898-468f-5427-af1ed528565c", + "x-ms-keyvault-network-info": "conn_type=Ipv4;addr=24.22.157.72;act_addr_fam=InterNetwork;", + "x-ms-keyvault-region": "westus3", + "x-ms-keyvault-service-version": "1.9.378.1", + "x-ms-request-id": "d0cb9ee1-4822-462c-a726-32db11e49a55" + }, + "Url": "https://REDACTED.vault.azure.net/keys/RotateKey/rotate?api-version=7.3" + } + ] +}