From da1f4c399fa358666e3fe69d263d945a4db901ad Mon Sep 17 00:00:00 2001 From: gearama <50641385+gearama@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:16:41 -0700 Subject: [PATCH] Keys update (#6491) * Generate files * GetKey done * Creates done * GetDeletedKey * StartDeleteKey * StartRecoverDeleted * backup/restore * purge/rotate * import * update properties * get/update rotation policy * release key * GetProps of keys * GetVersions * GetDeletedKeys * remove test used for test * cleanup tests * remove some methods * tests * PR pipeline * more PR * fsdfs * clang * update to hsm * PR comments * PR * rwe * Rerecord for HSM and fix get * gdf --- .vscode/cspell.json | 3 +- sdk/keyvault/assets.json | 2 +- .../CMakeLists.txt | 29 + .../inc/azure/keyvault/keys/key_client.hpp | 21 +- .../azure/keyvault/keys/key_client_models.hpp | 84 +- .../keyvault/keys/key_client_options.hpp | 21 +- .../get_deleted_keys_paged_response.cpp | 17 + .../get_key_versions_paged_response.cpp | 17 + .../src/generated/get_keys_paged_response.cpp | 17 + .../src/generated/key_vault_client.cpp | 5751 +++++++++++++++++ .../src/generated/key_vault_client.hpp | 471 ++ .../generated/key_vault_client_options.hpp | 68 + .../key_vault_client_paged_responses.hpp | 88 + .../src/generated/keys.cpp | 85 + .../src/generated/keys_models.hpp | 996 +++ .../src/key_client.cpp | 388 +- .../src/key_client_models.cpp | 573 ++ .../src/key_client_options.cpp | 128 + .../src/key_client_paged_responses.cpp | 57 + .../test/ut/CMakeLists.txt | 2 - .../test/ut/key_client_create_test_live.cpp | 8 +- .../test/ut/key_client_test.cpp | 4 +- .../ut/key_cryptographic_client_test_live.cpp | 3 +- .../test/ut/mocked_client_test.cpp | 203 - .../test/ut/mocked_transport_adapter_test.hpp | 133 - .../tsp-location.yaml | 5 + .../tspconfig.yaml | 23 + .../CMakeLists.txt | 1 - .../azure/keyvault/secrets/secret_client.hpp | 2 - .../src/secret_serializers.cpp | 22 - sdk/keyvault/ci.yml | 4 +- .../test/ut/table_client_test.cpp | 1 - 32 files changed, 8567 insertions(+), 660 deletions(-) create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/get_deleted_keys_paged_response.cpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/get_key_versions_paged_response.cpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/get_keys_paged_response.cpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.cpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.hpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_options.hpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_paged_responses.hpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/keys.cpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/generated/keys_models.hpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/key_client_models.cpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/key_client_options.cpp delete mode 100644 sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_client_test.cpp delete mode 100644 sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_transport_adapter_test.hpp create mode 100644 sdk/keyvault/azure-security-keyvault-keys/tsp-location.yaml create mode 100644 sdk/keyvault/azure-security-keyvault-keys/tspconfig.yaml delete mode 100644 sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 23638dc21..a028b1832 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -46,7 +46,8 @@ "sdk/core/azure-core-amqp/**/rust_amqp/azure_core_amqp/**/*", "*.toml", "sdk/storage/*/NOTICE.txt", - "sdk/tables/*/NOTICE.txt" + "sdk/tables/*/NOTICE.txt", + "sdk/keyvault/azure-security-keyvault-keys/src/generated/*", ], // * Unless configured otherwise, these words are not case sensitive // * Alphabetize the list when making changes so the list is easier for future diff --git a/sdk/keyvault/assets.json b/sdk/keyvault/assets.json index 204aaabe8..c655d04d0 100644 --- a/sdk/keyvault/assets.json +++ b/sdk/keyvault/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "cpp", "TagPrefix": "cpp/keyvault", - "Tag": "cpp/keyvault_682056eb2b" + "Tag": "cpp/keyvault_28cdcba8d8" } diff --git a/sdk/keyvault/azure-security-keyvault-keys/CMakeLists.txt b/sdk/keyvault/azure-security-keyvault-keys/CMakeLists.txt index d5b6db60a..be918639e 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/CMakeLists.txt +++ b/sdk/keyvault/azure-security-keyvault-keys/CMakeLists.txt @@ -45,6 +45,24 @@ elseif(NOT AZ_ALL_LIBRARIES) endif() endif() +option(AZURE_TSP_KV_KEYS_GEN3 "Generate KeyVault Keys from TypeSpec" ON) +message("KeyVault Secrets TSP Generation ${AZURE_TSP_KV_KEYS_GEN}") + +if(AZURE_TSP_KV_KEYS_GEN) + include(TSPCompile) + #typespec related repo information + set(TSP_SERVICE_PATH "Security.KeyVault.Keys") + set(TSP_DESTINATION "keyvault_keys") + + #codegen related repo information + set(CODEGEN_SHA "83758baff29b89a8a7bd28fa26a692225f4f208f") + set(CODEGEN_DESTINATION "typespec-cpp") + + #destination folders + set(GEN_FILES_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}") + #generate code from typespec + GenerateCodeFromTypeSpec(${TSP_DESTINATION} ${TSP_SERVICE_PATH} ${CODEGEN_SHA} ${CODEGEN_DESTINATION} ${GEN_FILES_DESTINATION} OFF) +endif() set( AZURE_KEYVAULT_KEYS_HEADER inc/azure/keyvault/keys.hpp @@ -82,6 +100,8 @@ set( src/json_web_key.cpp src/key_backup.cpp src/key_client.cpp + src/key_client_models.cpp + src/key_client_options.cpp src/key_client_paged_responses.cpp src/key_curve_name.cpp src/key_encryption_algorithm.cpp @@ -94,6 +114,15 @@ set( src/key_type.cpp src/keyvault_key.cpp src/keyvault_protocol.cpp + src/generated/get_deleted_keys_paged_response.cpp + src/generated/get_keys_paged_response.cpp + src/generated/get_key_versions_paged_response.cpp + src/generated/keys.cpp + src/generated/keys_models.hpp + src/generated/key_vault_client.cpp + src/generated/key_vault_client.hpp + src/generated/key_vault_client_options.hpp + src/generated/key_vault_client_paged_responses.hpp src/private/cryptography_internal_access.hpp src/private/cryptography_serializers.hpp src/private/key_backup.hpp 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 623ad1097..dea522e08 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 @@ -28,7 +28,9 @@ namespace Azure { namespace Security { namespace KeyVault { namespace _detail { }}}} // namespace Azure::Security::KeyVault::_detail namespace Azure { namespace Security { namespace KeyVault { namespace Keys { - + namespace _detail { + class KeyVaultClient; + } /** * @brief The KeyClient provides synchronous methods to manage a KeyVaultKe in the Azure Key * Vault. The client supports creating, retrieving, updating, deleting, purging, backing up, @@ -49,6 +51,9 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { /** @brief the HTTP Pipeline used in this KeyClient. */ std::shared_ptr m_pipeline; + private: + std::shared_ptr<_detail::KeyVaultClient> m_client; + public: /** * @brief Destructor. @@ -499,19 +504,5 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @return The key client's primary URL endpoint. */ std::string GetUrl() const { return m_vaultUrl.GetAbsoluteUrl(); } - - private: - std::unique_ptr SendRequest( - Azure::Core::Http::Request& request, - Azure::Core::Context const& context) const; - - Azure::Core::Http::Request CreateRequest( - Azure::Core::Http::HttpMethod method, - std::vector const& path = {}, - Azure::Core::IO::BodyStream* content = nullptr) const; - - Azure::Core::Http::Request ContinuationTokenRequest( - std::vector const& path, - const Azure::Nullable& NextPageToken) const; }; }}}} // namespace Azure::Security::KeyVault::Keys diff --git a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_models.hpp b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_models.hpp index 4ed8e0a48..3876115c0 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_models.hpp +++ b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_models.hpp @@ -31,7 +31,22 @@ #include namespace Azure { namespace Security { namespace KeyVault { namespace Keys { - + class KeyClient; + namespace _detail { + namespace Models { + struct KeyBundle; + struct DeletedKeyBundle; + struct KeyUpdateParameters; + struct KeyRotationPolicy; + struct KeyItem; + struct DeletedKeyItem; + } // namespace Models + class GetKeysPagedResponse; + class GetKeyVersionsPagedResponse; + class GetDeletedKeysPagedResponse; + } // namespace _detail + class KeyPropertiesPagedResponse; + class DeletedKeyPagedResponse; /** * @brief Define a model for a purged key. * @@ -487,7 +502,26 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { */ std::string EncodedPolicy; }; + /** + * @brief The key attestation information. + * + */ + struct KeyAttestation final + { + /// A base64url-encoded string containing certificates in PEM format, used for attestation + /// validation. + Nullable> CertificatePemFile; + /// The attestation blob bytes encoded as base64url string corresponding to a private key. + Nullable> PrivateKeyAttestation; + + /// The attestation blob bytes encoded as base64url string corresponding to a public key in + /// case of asymmetric key. + Nullable> PublicKeyAttestation; + + /// The version of the attestation. + Nullable Version; + }; /** * @brief The resource containing all the properties of the KeyVaultKey except JsonWebKey * properties. @@ -596,6 +630,11 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { */ Azure::Nullable HsmPlatform; + /** + * @brief The key or key version attestation information. + * + */ + Azure::Nullable Attestation; /** * @brief Construct a new Key Properties object. * @@ -608,6 +647,13 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @param name The name of the key. */ KeyProperties(std::string name) : Name(std::move(name)) {} + + private: + friend class KeyClient; + friend class KeyPropertiesPagedResponse; + _detail::Models::KeyUpdateParameters ToKeyUpdateParameters( + Azure::Nullable> const& keyOperations) const; + KeyProperties(_detail::Models::KeyItem const& response); }; /** @@ -675,6 +721,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @return A vector with the supported operations for the key. */ std::vector const& KeyOperations() const { return Key.KeyOperations(); } + + private: + friend class KeyClient; + KeyVaultKey(_detail::Models::KeyBundle const& response); }; /** @@ -714,9 +764,13 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * */ Azure::DateTime ScheduledPurgeDate; - }; - class KeyClient; + private: + friend class KeyClient; + friend class DeletedKeyPagedResponse; + DeletedKey(_detail::Models::DeletedKeyBundle const& response); + DeletedKey(_detail::Models::DeletedKeyItem const& response); + }; /** * @brief Define a single page to list the keys from the Key Vault. @@ -755,6 +809,16 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { { RawResponse = std::move(rawResponse); } + KeyPropertiesPagedResponse( + _detail::GetKeysPagedResponse const& pagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr keyClient, + std::string const& keyName = std::string()); + KeyPropertiesPagedResponse( + _detail::GetKeyVersionsPagedResponse const& pagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr keyClient, + std::string const& keyName = std::string()); public: /** @@ -802,6 +866,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { { RawResponse = std::move(rawResponse); } + DeletedKeyPagedResponse( + _detail::GetDeletedKeysPagedResponse&& pagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr keyClient); public: /** @@ -1109,6 +1177,16 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @brief The key rotation policy attributes. */ KeyRotationPolicyAttributes Attributes; + + /** + * @brief Default constructor. + */ + KeyRotationPolicy() = default; + + private: + friend class KeyClient; + KeyRotationPolicy(_detail::Models::KeyRotationPolicy const& krp); + _detail::Models::KeyRotationPolicy ToKeyRotationPolicy() const; }; /** diff --git a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_options.hpp b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_options.hpp index 585ec6cd8..40bba0ce9 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_options.hpp +++ b/sdk/keyvault/azure-security-keyvault-keys/inc/azure/keyvault/keys/key_client_options.hpp @@ -15,7 +15,12 @@ #include namespace Azure { namespace Security { namespace KeyVault { namespace Keys { - + class KeyClient; + namespace _detail { namespace Models { + struct KeyCreateParameters; + struct KeyImportParameters; + struct KeyReleaseParameters; + }} // namespace _detail::Models /** * @brief The options for calling an operation * #Azure::Security::KeyVault::Keys::KeyClient::GetPropertiesOfKeys. @@ -59,7 +64,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @brief Service Version used. * */ - std::string ApiVersion{"7.5"}; + std::string ApiVersion{"7.6-preview.2"}; }; /** @@ -128,6 +133,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * */ Azure::Nullable Exportable; + + private: + friend class KeyClient; + _detail::Models::KeyCreateParameters ToKeyCreateParameters() const; }; /** @@ -374,6 +383,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * @return The name of the key. */ std::string const& Name() const { return Properties.Name; } + + private: + friend class KeyClient; + _detail::Models::KeyImportParameters ToKeyImportParameters() const; }; /** @@ -418,6 +431,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { * */ Azure::Nullable Version; + + private: + friend class KeyClient; + _detail::Models::KeyReleaseParameters ToKeyReleaseParameters() const; }; }}}} // namespace Azure::Security::KeyVault::Keys diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_deleted_keys_paged_response.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_deleted_keys_paged_response.cpp new file mode 100644 index 000000000..e357c9ed3 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_deleted_keys_paged_response.cpp @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#include "key_vault_client.hpp" +#include "key_vault_client_paged_responses.hpp" + +using namespace Azure::Security::KeyVault::Keys::_detail; + +void GetDeletedKeysPagedResponse::OnNextPage(Core::Context const& context) +{ + const auto pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetDeletedKeys(this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_key_versions_paged_response.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_key_versions_paged_response.cpp new file mode 100644 index 000000000..9426ec8d9 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_key_versions_paged_response.cpp @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#include "key_vault_client.hpp" +#include "key_vault_client_paged_responses.hpp" + +using namespace Azure::Security::KeyVault::Keys::_detail; + +void GetKeyVersionsPagedResponse::OnNextPage(Core::Context const& context) +{ + const auto pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetKeyVersions(this->m_keyName, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_keys_paged_response.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_keys_paged_response.cpp new file mode 100644 index 000000000..36b11b60b --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/get_keys_paged_response.cpp @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#include "key_vault_client.hpp" +#include "key_vault_client_paged_responses.hpp" + +using namespace Azure::Security::KeyVault::Keys::_detail; + +void GetKeysPagedResponse::OnNextPage(Core::Context const& context) +{ + const auto pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetKeys(this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.cpp new file mode 100644 index 000000000..54218c527 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.cpp @@ -0,0 +1,5751 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#include "key_vault_client.hpp" + +#include "../private/package_version.hpp" + +#include +#include +#include +#include +#include +#include +#include + +// codegen: insert after includes +#include "azure/keyvault/shared/keyvault_challenge_based_auth.hpp" +#include "azure/keyvault/shared/keyvault_shared.hpp" + +using Azure::Security::KeyVault::_internal::KeyVaultChallengeBasedAuthenticationPolicy; +using Azure::Security::KeyVault::_internal::UrlScope; +// codegen: end insert after includes +using namespace Azure::Security::KeyVault::Keys::_detail; +// codegen: replace KeyVaultClient::KeyVaultClient +KeyVaultClient::KeyVaultClient( + const std::string& url, + const std::shared_ptr& credential, + const KeyVaultClientOptions& options) + : m_url(url), m_apiVersion(options.ApiVersion) +{ + std::vector> perRetryPolicies; + std::vector> perCallPolicies; + + { + Core::Credentials::TokenRequestContext tokenRequestContext; + tokenRequestContext.Scopes + = {Azure::Security::KeyVault::_internal::UrlScope::GetScopeFromUrl(Azure::Core::Url(url))}; + perRetryPolicies.emplace_back(std::make_unique( + credential, tokenRequestContext)); + } + + m_pipeline = std::make_shared( + options, + "security-keyvault-keys", + _detail::PackageVersion::ToString(), + std::move(perRetryPolicies), + std::move(perCallPolicies)); +} +// codegen: end replace KeyVaultClient::KeyVaultClient + +std::string KeyVaultClient::GetUrl() const { return m_url.GetAbsoluteUrl(); } + +Azure::Response +KeyVaultClient::CreateKey( + const std::string& keyName, + const Models::KeyCreateParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("create"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["kty"] = parameters.Kty.ToString(); + if (parameters.KeySize.HasValue()) + { + jsonRoot["key_size"] = parameters.KeySize.Value(); + } + + if (parameters.PublicExponent.HasValue()) + { + jsonRoot["public_exponent"] = parameters.PublicExponent.Value(); + } + + if (parameters.KeyOps.HasValue()) + { + jsonRoot["key_ops"] = Core::Json::_internal::json::array(); + + const size_t size = parameters.KeyOps.Value().size(); + for (size_t i = 0; i < size; ++i) + { + jsonRoot["key_ops"][i] = parameters.KeyOps.Value()[i].ToString(); + } + } + + if (parameters.KeyAttributes.HasValue()) + { + if (parameters.KeyAttributes.Value().Enabled.HasValue()) + { + jsonRoot["attributes"]["enabled"] = parameters.KeyAttributes.Value().Enabled.Value(); + } + + if (parameters.KeyAttributes.Value().NotBefore.HasValue()) + { + jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().NotBefore.Value()); + } + + if (parameters.KeyAttributes.Value().Expires.HasValue()) + { + jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Expires.Value()); + } + + if (parameters.KeyAttributes.Value().Created.HasValue()) + { + jsonRoot["attributes"]["created"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Created.Value()); + } + + if (parameters.KeyAttributes.Value().Updated.HasValue()) + { + jsonRoot["attributes"]["updated"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Updated.Value()); + } + + if (parameters.KeyAttributes.Value().RecoverableDays.HasValue()) + { + jsonRoot["attributes"]["recoverableDays"] + = parameters.KeyAttributes.Value().RecoverableDays.Value(); + } + + if (parameters.KeyAttributes.Value().RecoveryLevel.HasValue()) + { + jsonRoot["attributes"]["recoveryLevel"] + = parameters.KeyAttributes.Value().RecoveryLevel.Value().ToString(); + } + + if (parameters.KeyAttributes.Value().Exportable.HasValue()) + { + jsonRoot["attributes"]["exportable"] = parameters.KeyAttributes.Value().Exportable.Value(); + } + + if (parameters.KeyAttributes.Value().HsmPlatform.HasValue()) + { + jsonRoot["attributes"]["hsmPlatform"] + = parameters.KeyAttributes.Value().HsmPlatform.Value(); + } + + if (parameters.KeyAttributes.Value().Attestation.HasValue()) + { + if (parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.HasValue()) + { + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + = Core::_internal::Base64Url::Base64UrlEncode( + parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation.HasValue()) + { + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value() + .Attestation.Value() + .PrivateKeyAttestation.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation.HasValue()) + { + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value() + .Attestation.Value() + .PublicKeyAttestation.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().Version.HasValue()) + { + jsonRoot["attributes"]["attestation"]["version"] + = parameters.KeyAttributes.Value().Attestation.Value().Version.Value(); + } + } + } + + if (parameters.Tags.HasValue()) + { + jsonRoot["tags"] = Core::Json::_internal::json::object(); + + for (auto const& kv : parameters.Tags.Value()) + { + jsonRoot["tags"][kv.first] = kv.second; + } + } + + if (parameters.Curve.HasValue()) + { + jsonRoot["crv"] = parameters.Curve.Value().ToString(); + } + + if (parameters.ReleasePolicy.HasValue()) + { + if (parameters.ReleasePolicy.Value().ContentType.HasValue()) + { + jsonRoot["release_policy"]["contentType"] + = parameters.ReleasePolicy.Value().ContentType.Value(); + } + + if (parameters.ReleasePolicy.Value().Immutable.HasValue()) + { + jsonRoot["release_policy"]["immutable"] + = parameters.ReleasePolicy.Value().Immutable.Value(); + } + + if (parameters.ReleasePolicy.Value().EncodedPolicy.HasValue()) + { + jsonRoot["release_policy"]["data"] = Core::_internal::Base64Url::Base64UrlEncode( + parameters.ReleasePolicy.Value().EncodedPolicy.Value()); + } + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::RotateKey(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("rotate"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::ImportKey( + const std::string& keyName, + const Models::KeyImportParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + if (parameters.Hsm.HasValue()) + { + jsonRoot["Hsm"] = parameters.Hsm.Value(); + } + + if (parameters.Key.Kid.HasValue()) + { + jsonRoot["key"]["kid"] = parameters.Key.Kid.Value(); + } + + if (parameters.Key.Kty.HasValue()) + { + jsonRoot["key"]["kty"] = parameters.Key.Kty.Value().ToString(); + } + + if (parameters.Key.KeyOps.HasValue()) + { + jsonRoot["key"]["key_ops"] = Core::Json::_internal::json::array(); + + const size_t size = parameters.Key.KeyOps.Value().size(); + for (size_t i = 0; i < size; ++i) + { + jsonRoot["key"]["key_ops"][i] = parameters.Key.KeyOps.Value()[i]; + } + } + + if (parameters.Key.N.HasValue()) + { + jsonRoot["key"]["n"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.N.Value()); + } + + if (parameters.Key.E.HasValue()) + { + jsonRoot["key"]["e"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.E.Value()); + } + + if (parameters.Key.D.HasValue()) + { + jsonRoot["key"]["d"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.D.Value()); + } + + if (parameters.Key.Dp.HasValue()) + { + jsonRoot["key"]["dp"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Dp.Value()); + } + + if (parameters.Key.Dq.HasValue()) + { + jsonRoot["key"]["dq"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Dq.Value()); + } + + if (parameters.Key.Qi.HasValue()) + { + jsonRoot["key"]["qi"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Qi.Value()); + } + + if (parameters.Key.P.HasValue()) + { + jsonRoot["key"]["p"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.P.Value()); + } + + if (parameters.Key.Q.HasValue()) + { + jsonRoot["key"]["q"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Q.Value()); + } + + if (parameters.Key.K.HasValue()) + { + jsonRoot["key"]["k"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.K.Value()); + } + + if (parameters.Key.T.HasValue()) + { + jsonRoot["key"]["key_hsm"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.T.Value()); + } + + if (parameters.Key.Crv.HasValue()) + { + jsonRoot["key"]["crv"] = parameters.Key.Crv.Value().ToString(); + } + + if (parameters.Key.X.HasValue()) + { + jsonRoot["key"]["x"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.X.Value()); + } + + if (parameters.Key.Y.HasValue()) + { + jsonRoot["key"]["y"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Key.Y.Value()); + } + + if (parameters.KeyAttributes.HasValue()) + { + if (parameters.KeyAttributes.Value().Enabled.HasValue()) + { + jsonRoot["attributes"]["enabled"] = parameters.KeyAttributes.Value().Enabled.Value(); + } + + if (parameters.KeyAttributes.Value().NotBefore.HasValue()) + { + jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().NotBefore.Value()); + } + + if (parameters.KeyAttributes.Value().Expires.HasValue()) + { + jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Expires.Value()); + } + + if (parameters.KeyAttributes.Value().Created.HasValue()) + { + jsonRoot["attributes"]["created"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Created.Value()); + } + + if (parameters.KeyAttributes.Value().Updated.HasValue()) + { + jsonRoot["attributes"]["updated"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Updated.Value()); + } + + if (parameters.KeyAttributes.Value().RecoverableDays.HasValue()) + { + jsonRoot["attributes"]["recoverableDays"] + = parameters.KeyAttributes.Value().RecoverableDays.Value(); + } + + if (parameters.KeyAttributes.Value().RecoveryLevel.HasValue()) + { + jsonRoot["attributes"]["recoveryLevel"] + = parameters.KeyAttributes.Value().RecoveryLevel.Value().ToString(); + } + + if (parameters.KeyAttributes.Value().Exportable.HasValue()) + { + jsonRoot["attributes"]["exportable"] = parameters.KeyAttributes.Value().Exportable.Value(); + } + + if (parameters.KeyAttributes.Value().HsmPlatform.HasValue()) + { + jsonRoot["attributes"]["hsmPlatform"] + = parameters.KeyAttributes.Value().HsmPlatform.Value(); + } + + if (parameters.KeyAttributes.Value().Attestation.HasValue()) + { + if (parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.HasValue()) + { + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + = Core::_internal::Base64Url::Base64UrlEncode( + parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation.HasValue()) + { + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value() + .Attestation.Value() + .PrivateKeyAttestation.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation.HasValue()) + { + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value() + .Attestation.Value() + .PublicKeyAttestation.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().Version.HasValue()) + { + jsonRoot["attributes"]["attestation"]["version"] + = parameters.KeyAttributes.Value().Attestation.Value().Version.Value(); + } + } + } + + if (parameters.Tags.HasValue()) + { + jsonRoot["tags"] = Core::Json::_internal::json::object(); + + for (auto const& kv : parameters.Tags.Value()) + { + jsonRoot["tags"][kv.first] = kv.second; + } + } + + if (parameters.ReleasePolicy.HasValue()) + { + if (parameters.ReleasePolicy.Value().ContentType.HasValue()) + { + jsonRoot["release_policy"]["contentType"] + = parameters.ReleasePolicy.Value().ContentType.Value(); + } + + if (parameters.ReleasePolicy.Value().Immutable.HasValue()) + { + jsonRoot["release_policy"]["immutable"] + = parameters.ReleasePolicy.Value().Immutable.Value(); + } + + if (parameters.ReleasePolicy.Value().EncodedPolicy.HasValue()) + { + jsonRoot["release_policy"]["data"] = Core::_internal::Base64Url::Base64UrlEncode( + parameters.ReleasePolicy.Value().EncodedPolicy.Value()); + } + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Put, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::DeleteKey(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Delete, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::DeletedKeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + + if (jsonRoot.contains("recoveryId") && !jsonRoot["recoveryId"].is_null()) + { + response.RecoveryId = jsonRoot["recoveryId"].get(); + } + + if (jsonRoot.contains("scheduledPurgeDate") && !jsonRoot["scheduledPurgeDate"].is_null()) + { + response.ScheduledPurgeDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["scheduledPurgeDate"].is_string() + ? std::stoll(jsonRoot["scheduledPurgeDate"].get()) + : jsonRoot["scheduledPurgeDate"].get()); + } + + if (jsonRoot.contains("deletedDate") && !jsonRoot["deletedDate"].is_null()) + { + response.DeletedDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["deletedDate"].is_string() + ? std::stoll(jsonRoot["deletedDate"].get()) + : jsonRoot["deletedDate"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::UpdateKey( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyUpdateParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + if (parameters.KeyOps.HasValue()) + { + jsonRoot["key_ops"] = Core::Json::_internal::json::array(); + + const size_t size = parameters.KeyOps.Value().size(); + for (size_t i = 0; i < size; ++i) + { + jsonRoot["key_ops"][i] = parameters.KeyOps.Value()[i].ToString(); + } + } + + if (parameters.KeyAttributes.HasValue()) + { + if (parameters.KeyAttributes.Value().Enabled.HasValue()) + { + jsonRoot["attributes"]["enabled"] = parameters.KeyAttributes.Value().Enabled.Value(); + } + + if (parameters.KeyAttributes.Value().NotBefore.HasValue()) + { + jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().NotBefore.Value()); + } + + if (parameters.KeyAttributes.Value().Expires.HasValue()) + { + jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Expires.Value()); + } + + if (parameters.KeyAttributes.Value().Created.HasValue()) + { + jsonRoot["attributes"]["created"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Created.Value()); + } + + if (parameters.KeyAttributes.Value().Updated.HasValue()) + { + jsonRoot["attributes"]["updated"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.KeyAttributes.Value().Updated.Value()); + } + + if (parameters.KeyAttributes.Value().RecoverableDays.HasValue()) + { + jsonRoot["attributes"]["recoverableDays"] + = parameters.KeyAttributes.Value().RecoverableDays.Value(); + } + + if (parameters.KeyAttributes.Value().RecoveryLevel.HasValue()) + { + jsonRoot["attributes"]["recoveryLevel"] + = parameters.KeyAttributes.Value().RecoveryLevel.Value().ToString(); + } + + if (parameters.KeyAttributes.Value().Exportable.HasValue()) + { + jsonRoot["attributes"]["exportable"] = parameters.KeyAttributes.Value().Exportable.Value(); + } + + if (parameters.KeyAttributes.Value().HsmPlatform.HasValue()) + { + jsonRoot["attributes"]["hsmPlatform"] + = parameters.KeyAttributes.Value().HsmPlatform.Value(); + } + + if (parameters.KeyAttributes.Value().Attestation.HasValue()) + { + if (parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.HasValue()) + { + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + = Core::_internal::Base64Url::Base64UrlEncode( + parameters.KeyAttributes.Value().Attestation.Value().CertificatePemFile.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation.HasValue()) + { + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value() + .Attestation.Value() + .PrivateKeyAttestation.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation.HasValue()) + { + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyAttributes.Value() + .Attestation.Value() + .PublicKeyAttestation.Value()); + } + + if (parameters.KeyAttributes.Value().Attestation.Value().Version.HasValue()) + { + jsonRoot["attributes"]["attestation"]["version"] + = parameters.KeyAttributes.Value().Attestation.Value().Version.Value(); + } + } + } + + if (parameters.Tags.HasValue()) + { + jsonRoot["tags"] = Core::Json::_internal::json::object(); + + for (auto const& kv : parameters.Tags.Value()) + { + jsonRoot["tags"][kv.first] = kv.second; + } + } + + if (parameters.ReleasePolicy.HasValue()) + { + if (parameters.ReleasePolicy.Value().ContentType.HasValue()) + { + jsonRoot["release_policy"]["contentType"] + = parameters.ReleasePolicy.Value().ContentType.Value(); + } + + if (parameters.ReleasePolicy.Value().Immutable.HasValue()) + { + jsonRoot["release_policy"]["immutable"] + = parameters.ReleasePolicy.Value().Immutable.Value(); + } + + if (parameters.ReleasePolicy.Value().EncodedPolicy.HasValue()) + { + jsonRoot["release_policy"]["data"] = Core::_internal::Base64Url::Base64UrlEncode( + parameters.ReleasePolicy.Value().EncodedPolicy.Value()); + } + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Patch, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} +// codegen: replace KeyVaultClient::GetKey +Azure::Response KeyVaultClient::GetKey( + const std::string& keyName, + const std::string& keyVersion, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (!keyVersion.empty()) + { + url.AppendPath(Core::Url::Encode(keyVersion)); + } + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} +// codegen: end replace KeyVaultClient::GetKey +GetKeyVersionsPagedResponse KeyVaultClient::GetKeyVersions( + const std::string& keyName, + const KeyVaultClientGetKeyVersionsOptions& options, + const Core::Context& context) const +{ + Core::Url url; + if (options.NextPageToken.empty()) + { + url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("versions"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + if (options.Maxresults.HasValue()) + { + url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value())); + } + } + else + { + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost()) + { + url.SetPort(m_url.GetPort()); + } + } + else + { + url = Core::Url( + m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/' + + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) + : options.NextPageToken)); + } + + const auto qps = url.GetQueryParameters(); + if (qps.find("api-version") != qps.cend()) + { + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + } + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetKeyVersionsPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_keyName = keyName; + response.m_options = options; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["nextLink"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = std::vector{}; + + for (auto const& jsonItem : jsonRoot["value"]) + { + Models::KeyItem vectorItem{}; + + if (jsonItem.contains("kid") && !jsonItem["kid"].is_null()) + { + vectorItem.Kid = jsonItem["kid"].get(); + } + + if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null()) + { + vectorItem.Attributes = Models::KeyAttributes{}; + + if (jsonItem["attributes"].contains("enabled") + && !jsonItem["attributes"]["enabled"].is_null()) + { + vectorItem.Attributes.Value().Enabled + = jsonItem["attributes"]["enabled"].get(); + } + + if (jsonItem["attributes"].contains("nbf") + && !jsonItem["attributes"]["nbf"].is_null()) + { + vectorItem.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["nbf"].is_string() + ? std::stoll(jsonItem["attributes"]["nbf"].get()) + : jsonItem["attributes"]["nbf"].get()); + } + + if (jsonItem["attributes"].contains("exp") + && !jsonItem["attributes"]["exp"].is_null()) + { + vectorItem.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["exp"].is_string() + ? std::stoll(jsonItem["attributes"]["exp"].get()) + : jsonItem["attributes"]["exp"].get()); + } + + if (jsonItem["attributes"].contains("created") + && !jsonItem["attributes"]["created"].is_null()) + { + vectorItem.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["created"].is_string() + ? std::stoll(jsonItem["attributes"]["created"].get()) + : jsonItem["attributes"]["created"].get()); + } + + if (jsonItem["attributes"].contains("updated") + && !jsonItem["attributes"]["updated"].is_null()) + { + vectorItem.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["updated"].is_string() + ? std::stoll(jsonItem["attributes"]["updated"].get()) + : jsonItem["attributes"]["updated"].get()); + } + + if (jsonItem["attributes"].contains("recoverableDays") + && !jsonItem["attributes"]["recoverableDays"].is_null()) + { + vectorItem.Attributes.Value().RecoverableDays + = jsonItem["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonItem["attributes"]["recoverableDays"].get()) + : jsonItem["attributes"]["recoverableDays"].get(); + } + + if (jsonItem["attributes"].contains("recoveryLevel") + && !jsonItem["attributes"]["recoveryLevel"].is_null()) + { + vectorItem.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonItem["attributes"]["recoveryLevel"].get()); + } + + if (jsonItem["attributes"].contains("exportable") + && !jsonItem["attributes"]["exportable"].is_null()) + { + vectorItem.Attributes.Value().Exportable + = jsonItem["attributes"]["exportable"].get(); + } + + if (jsonItem["attributes"].contains("hsmPlatform") + && !jsonItem["attributes"]["hsmPlatform"].is_null()) + { + vectorItem.Attributes.Value().HsmPlatform + = jsonItem["attributes"]["hsmPlatform"].get(); + } + + if (jsonItem["attributes"].contains("attestation") + && !jsonItem["attributes"]["attestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonItem["attributes"]["attestation"].contains("certificatePemFile") + && !jsonItem["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonItem["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonItem["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("version") + && !jsonItem["attributes"]["attestation"]["version"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().Version + = jsonItem["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonItem.contains("tags") && !jsonItem["tags"].is_null()) + { + vectorItem.Tags = std::map{}; + + for (auto const& kv : jsonItem["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + vectorItem.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonItem.contains("managed") && !jsonItem["managed"].is_null()) + { + vectorItem.Managed = jsonItem["managed"].get(); + } + + response.Value.Value().emplace_back(std::move(vectorItem)); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + response.RawResponse = std::move(rawResponse); + + return response; +} + +GetKeysPagedResponse KeyVaultClient::GetKeys( + const KeyVaultClientGetKeysOptions& options, + const Core::Context& context) const +{ + Core::Url url; + if (options.NextPageToken.empty()) + { + url = m_url; + url.AppendPath("keys"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + if (options.Maxresults.HasValue()) + { + url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value())); + } + } + else + { + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost()) + { + url.SetPort(m_url.GetPort()); + } + } + else + { + url = Core::Url( + m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/' + + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) + : options.NextPageToken)); + } + + const auto qps = url.GetQueryParameters(); + if (qps.find("api-version") != qps.cend()) + { + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + } + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetKeysPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_options = options; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["nextLink"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = std::vector{}; + + for (auto const& jsonItem : jsonRoot["value"]) + { + Models::KeyItem vectorItem{}; + + if (jsonItem.contains("kid") && !jsonItem["kid"].is_null()) + { + vectorItem.Kid = jsonItem["kid"].get(); + } + + if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null()) + { + vectorItem.Attributes = Models::KeyAttributes{}; + + if (jsonItem["attributes"].contains("enabled") + && !jsonItem["attributes"]["enabled"].is_null()) + { + vectorItem.Attributes.Value().Enabled + = jsonItem["attributes"]["enabled"].get(); + } + + if (jsonItem["attributes"].contains("nbf") + && !jsonItem["attributes"]["nbf"].is_null()) + { + vectorItem.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["nbf"].is_string() + ? std::stoll(jsonItem["attributes"]["nbf"].get()) + : jsonItem["attributes"]["nbf"].get()); + } + + if (jsonItem["attributes"].contains("exp") + && !jsonItem["attributes"]["exp"].is_null()) + { + vectorItem.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["exp"].is_string() + ? std::stoll(jsonItem["attributes"]["exp"].get()) + : jsonItem["attributes"]["exp"].get()); + } + + if (jsonItem["attributes"].contains("created") + && !jsonItem["attributes"]["created"].is_null()) + { + vectorItem.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["created"].is_string() + ? std::stoll(jsonItem["attributes"]["created"].get()) + : jsonItem["attributes"]["created"].get()); + } + + if (jsonItem["attributes"].contains("updated") + && !jsonItem["attributes"]["updated"].is_null()) + { + vectorItem.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["updated"].is_string() + ? std::stoll(jsonItem["attributes"]["updated"].get()) + : jsonItem["attributes"]["updated"].get()); + } + + if (jsonItem["attributes"].contains("recoverableDays") + && !jsonItem["attributes"]["recoverableDays"].is_null()) + { + vectorItem.Attributes.Value().RecoverableDays + = jsonItem["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonItem["attributes"]["recoverableDays"].get()) + : jsonItem["attributes"]["recoverableDays"].get(); + } + + if (jsonItem["attributes"].contains("recoveryLevel") + && !jsonItem["attributes"]["recoveryLevel"].is_null()) + { + vectorItem.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonItem["attributes"]["recoveryLevel"].get()); + } + + if (jsonItem["attributes"].contains("exportable") + && !jsonItem["attributes"]["exportable"].is_null()) + { + vectorItem.Attributes.Value().Exportable + = jsonItem["attributes"]["exportable"].get(); + } + + if (jsonItem["attributes"].contains("hsmPlatform") + && !jsonItem["attributes"]["hsmPlatform"].is_null()) + { + vectorItem.Attributes.Value().HsmPlatform + = jsonItem["attributes"]["hsmPlatform"].get(); + } + + if (jsonItem["attributes"].contains("attestation") + && !jsonItem["attributes"]["attestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonItem["attributes"]["attestation"].contains("certificatePemFile") + && !jsonItem["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonItem["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonItem["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("version") + && !jsonItem["attributes"]["attestation"]["version"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().Version + = jsonItem["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonItem.contains("tags") && !jsonItem["tags"].is_null()) + { + vectorItem.Tags = std::map{}; + + for (auto const& kv : jsonItem["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + vectorItem.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonItem.contains("managed") && !jsonItem["managed"].is_null()) + { + vectorItem.Managed = jsonItem["managed"].get(); + } + + response.Value.Value().emplace_back(std::move(vectorItem)); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + response.RawResponse = std::move(rawResponse); + + return response; +} + +Azure::Response +KeyVaultClient::BackupKey(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("backup"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::BackupKeyResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response KeyVaultClient:: + RestoreKey(const Models::KeyRestoreParameters& parameters, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/restore"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.KeyBundleBackup); + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::Encrypt( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("encrypt"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["alg"] = parameters.Algorithm.ToString(); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value); + if (parameters.Iv.HasValue()) + { + jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value()); + } + + if (parameters.Aad.HasValue()) + { + jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value()); + } + + if (parameters.Tag.HasValue()) + { + jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.Value()); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyOperationResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Result + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + + if (jsonRoot.contains("iv") && !jsonRoot["iv"].is_null()) + { + response.Iv + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["iv"].get()); + } + + if (jsonRoot.contains("tag") && !jsonRoot["tag"].is_null()) + { + response.AuthenticationTag + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["tag"].get()); + } + + if (jsonRoot.contains("aad") && !jsonRoot["aad"].is_null()) + { + response.AdditionalAuthenticatedData + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["aad"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::Decrypt( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("decrypt"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["alg"] = parameters.Algorithm.ToString(); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value); + if (parameters.Iv.HasValue()) + { + jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value()); + } + + if (parameters.Aad.HasValue()) + { + jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value()); + } + + if (parameters.Tag.HasValue()) + { + jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.Value()); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyOperationResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Result + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + + if (jsonRoot.contains("iv") && !jsonRoot["iv"].is_null()) + { + response.Iv + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["iv"].get()); + } + + if (jsonRoot.contains("tag") && !jsonRoot["tag"].is_null()) + { + response.AuthenticationTag + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["tag"].get()); + } + + if (jsonRoot.contains("aad") && !jsonRoot["aad"].is_null()) + { + response.AdditionalAuthenticatedData + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["aad"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::Sign( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeySignParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("sign"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["alg"] = parameters.Algorithm.ToString(); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value); + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyOperationResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Result + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + + if (jsonRoot.contains("iv") && !jsonRoot["iv"].is_null()) + { + response.Iv + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["iv"].get()); + } + + if (jsonRoot.contains("tag") && !jsonRoot["tag"].is_null()) + { + response.AuthenticationTag + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["tag"].get()); + } + + if (jsonRoot.contains("aad") && !jsonRoot["aad"].is_null()) + { + response.AdditionalAuthenticatedData + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["aad"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::Verify( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyVerifyParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("verify"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["alg"] = parameters.Algorithm.ToString(); + jsonRoot["digest"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Digest); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Signature); + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyVerifyResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = jsonRoot["value"].get(); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::WrapKey( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("wrapkey"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["alg"] = parameters.Algorithm.ToString(); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value); + if (parameters.Iv.HasValue()) + { + jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value()); + } + + if (parameters.Aad.HasValue()) + { + jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value()); + } + + if (parameters.Tag.HasValue()) + { + jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.Value()); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyOperationResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Result + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + + if (jsonRoot.contains("iv") && !jsonRoot["iv"].is_null()) + { + response.Iv + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["iv"].get()); + } + + if (jsonRoot.contains("tag") && !jsonRoot["tag"].is_null()) + { + response.AuthenticationTag + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["tag"].get()); + } + + if (jsonRoot.contains("aad") && !jsonRoot["aad"].is_null()) + { + response.AdditionalAuthenticatedData + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["aad"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::UnwrapKey( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("unwrapkey"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["alg"] = parameters.Algorithm.ToString(); + jsonRoot["value"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Value); + if (parameters.Iv.HasValue()) + { + jsonRoot["iv"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Iv.Value()); + } + + if (parameters.Aad.HasValue()) + { + jsonRoot["aad"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Aad.Value()); + } + + if (parameters.Tag.HasValue()) + { + jsonRoot["tag"] = Core::_internal::Base64Url::Base64UrlEncode(parameters.Tag.Value()); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyOperationResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Result + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + + if (jsonRoot.contains("iv") && !jsonRoot["iv"].is_null()) + { + response.Iv + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["iv"].get()); + } + + if (jsonRoot.contains("tag") && !jsonRoot["tag"].is_null()) + { + response.AuthenticationTag + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["tag"].get()); + } + + if (jsonRoot.contains("aad") && !jsonRoot["aad"].is_null()) + { + response.AdditionalAuthenticatedData + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["aad"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::Release( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyReleaseParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("release"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["target"] = parameters.TargetAttestationToken; + if (parameters.Nonce.HasValue()) + { + jsonRoot["nonce"] = parameters.Nonce.Value(); + } + + if (parameters.Enc.HasValue()) + { + jsonRoot["enc"] = parameters.Enc.Value().ToString(); + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyReleaseResult response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = jsonRoot["value"].get(); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +GetDeletedKeysPagedResponse KeyVaultClient::GetDeletedKeys( + const KeyVaultClientGetDeletedKeysOptions& options, + const Core::Context& context) const +{ + Core::Url url; + if (options.NextPageToken.empty()) + { + url = m_url; + url.AppendPath("deletedkeys"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + if (options.Maxresults.HasValue()) + { + url.AppendQueryParameter("maxresults", std::to_string(options.Maxresults.Value())); + } + } + else + { + if (options.NextPageToken.find("https://") == 0 || options.NextPageToken.find("http://") == 0) + { + url = Core::Url(options.NextPageToken); + if (url.GetPort() == 0 && m_url.GetPort() != 0 && url.GetHost() == m_url.GetHost()) + { + url.SetPort(m_url.GetPort()); + } + } + else + { + url = Core::Url( + m_url.GetScheme() + "://" + m_url.GetHost() + ':' + std::to_string(m_url.GetPort()) + '/' + + (options.NextPageToken[0] == '/' ? options.NextPageToken.substr(1) + : options.NextPageToken)); + } + + const auto qps = url.GetQueryParameters(); + if (qps.find("api-version") != qps.cend()) + { + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + } + } + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + GetDeletedKeysPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_options = options; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + if (jsonRoot.contains("nextLink") && !jsonRoot["nextLink"].is_null()) + { + response.NextPageToken = jsonRoot["nextLink"].get(); + } + + if (jsonRoot.contains("value") && !jsonRoot["value"].is_null()) + { + response.Value = std::vector{}; + + for (auto const& jsonItem : jsonRoot["value"]) + { + Models::DeletedKeyItem vectorItem{}; + + if (jsonItem.contains("kid") && !jsonItem["kid"].is_null()) + { + vectorItem.Kid = jsonItem["kid"].get(); + } + + if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null()) + { + vectorItem.Attributes = Models::KeyAttributes{}; + + if (jsonItem["attributes"].contains("enabled") + && !jsonItem["attributes"]["enabled"].is_null()) + { + vectorItem.Attributes.Value().Enabled + = jsonItem["attributes"]["enabled"].get(); + } + + if (jsonItem["attributes"].contains("nbf") + && !jsonItem["attributes"]["nbf"].is_null()) + { + vectorItem.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["nbf"].is_string() + ? std::stoll(jsonItem["attributes"]["nbf"].get()) + : jsonItem["attributes"]["nbf"].get()); + } + + if (jsonItem["attributes"].contains("exp") + && !jsonItem["attributes"]["exp"].is_null()) + { + vectorItem.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["exp"].is_string() + ? std::stoll(jsonItem["attributes"]["exp"].get()) + : jsonItem["attributes"]["exp"].get()); + } + + if (jsonItem["attributes"].contains("created") + && !jsonItem["attributes"]["created"].is_null()) + { + vectorItem.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["created"].is_string() + ? std::stoll(jsonItem["attributes"]["created"].get()) + : jsonItem["attributes"]["created"].get()); + } + + if (jsonItem["attributes"].contains("updated") + && !jsonItem["attributes"]["updated"].is_null()) + { + vectorItem.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["attributes"]["updated"].is_string() + ? std::stoll(jsonItem["attributes"]["updated"].get()) + : jsonItem["attributes"]["updated"].get()); + } + + if (jsonItem["attributes"].contains("recoverableDays") + && !jsonItem["attributes"]["recoverableDays"].is_null()) + { + vectorItem.Attributes.Value().RecoverableDays + = jsonItem["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonItem["attributes"]["recoverableDays"].get()) + : jsonItem["attributes"]["recoverableDays"].get(); + } + + if (jsonItem["attributes"].contains("recoveryLevel") + && !jsonItem["attributes"]["recoveryLevel"].is_null()) + { + vectorItem.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonItem["attributes"]["recoveryLevel"].get()); + } + + if (jsonItem["attributes"].contains("exportable") + && !jsonItem["attributes"]["exportable"].is_null()) + { + vectorItem.Attributes.Value().Exportable + = jsonItem["attributes"]["exportable"].get(); + } + + if (jsonItem["attributes"].contains("hsmPlatform") + && !jsonItem["attributes"]["hsmPlatform"].is_null()) + { + vectorItem.Attributes.Value().HsmPlatform + = jsonItem["attributes"]["hsmPlatform"].get(); + } + + if (jsonItem["attributes"].contains("attestation") + && !jsonItem["attributes"]["attestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonItem["attributes"]["attestation"].contains("certificatePemFile") + && !jsonItem["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonItem["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonItem["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonItem["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonItem["attributes"]["attestation"].contains("version") + && !jsonItem["attributes"]["attestation"]["version"].is_null()) + { + vectorItem.Attributes.Value().Attestation.Value().Version + = jsonItem["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonItem.contains("tags") && !jsonItem["tags"].is_null()) + { + vectorItem.Tags = std::map{}; + + for (auto const& kv : jsonItem["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + vectorItem.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonItem.contains("managed") && !jsonItem["managed"].is_null()) + { + vectorItem.Managed = jsonItem["managed"].get(); + } + + if (jsonItem.contains("recoveryId") && !jsonItem["recoveryId"].is_null()) + { + vectorItem.RecoveryId = jsonItem["recoveryId"].get(); + } + + if (jsonItem.contains("scheduledPurgeDate") + && !jsonItem["scheduledPurgeDate"].is_null()) + { + vectorItem.ScheduledPurgeDate + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["scheduledPurgeDate"].is_string() + ? std::stoll(jsonItem["scheduledPurgeDate"].get()) + : jsonItem["scheduledPurgeDate"].get()); + } + + if (jsonItem.contains("deletedDate") && !jsonItem["deletedDate"].is_null()) + { + vectorItem.DeletedDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonItem["deletedDate"].is_string() + ? std::stoll(jsonItem["deletedDate"].get()) + : jsonItem["deletedDate"].get()); + } + + response.Value.Value().emplace_back(std::move(vectorItem)); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + response.RawResponse = std::move(rawResponse); + + return response; +} + +Azure::Response +KeyVaultClient::GetDeletedKey(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("deletedkeys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::DeletedKeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + + if (jsonRoot.contains("recoveryId") && !jsonRoot["recoveryId"].is_null()) + { + response.RecoveryId = jsonRoot["recoveryId"].get(); + } + + if (jsonRoot.contains("scheduledPurgeDate") && !jsonRoot["scheduledPurgeDate"].is_null()) + { + response.ScheduledPurgeDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["scheduledPurgeDate"].is_string() + ? std::stoll(jsonRoot["scheduledPurgeDate"].get()) + : jsonRoot["scheduledPurgeDate"].get()); + } + + if (jsonRoot.contains("deletedDate") && !jsonRoot["deletedDate"].is_null()) + { + response.DeletedDate = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["deletedDate"].is_string() + ? std::stoll(jsonRoot["deletedDate"].get()) + : jsonRoot["deletedDate"].get()); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::PurgeDeletedKey(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("deletedkeys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Delete, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::NoContent) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::PurgeDeletedKeyResult response{}; + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::RecoverDeletedKey(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("deletedkeys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("recover"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::GetKeyRotationPolicy(const std::string& keyName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("rotationpolicy"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyRotationPolicy response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("lifetimeActions") && !jsonRoot["lifetimeActions"].is_null()) + { + response.LifetimeActions = std::vector{}; + + for (auto const& jsonItem : jsonRoot["lifetimeActions"]) + { + Models::LifetimeActions vectorItem{}; + + if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null()) + { + vectorItem.Trigger = Models::LifetimeActionsTrigger{}; + + if (jsonItem["trigger"].contains("timeAfterCreate") + && !jsonItem["trigger"]["timeAfterCreate"].is_null()) + { + vectorItem.Trigger.Value().TimeAfterCreate + = jsonItem["trigger"]["timeAfterCreate"].get(); + } + + if (jsonItem["trigger"].contains("timeBeforeExpiry") + && !jsonItem["trigger"]["timeBeforeExpiry"].is_null()) + { + vectorItem.Trigger.Value().TimeBeforeExpiry + = jsonItem["trigger"]["timeBeforeExpiry"].get(); + } + } + + if (jsonItem.contains("action") && !jsonItem["action"].is_null()) + { + vectorItem.Action = Models::LifetimeActionsType{}; + + if (jsonItem["action"].contains("type") && !jsonItem["action"]["type"].is_null()) + { + vectorItem.Action.Value().Type = Models::KeyRotationPolicyAction( + jsonItem["action"]["type"].get()); + } + } + + response.LifetimeActions.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyRotationPolicyAttributes{}; + + if (jsonRoot["attributes"].contains("expiryTime") + && !jsonRoot["attributes"]["expiryTime"].is_null()) + { + response.Attributes.Value().ExpiryTime + = jsonRoot["attributes"]["expiryTime"].get(); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::UpdateKeyRotationPolicy( + const std::string& keyName, + const Models::KeyRotationPolicy& keyRotationPolicy, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + url.AppendPath("rotationpolicy"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + if (keyRotationPolicy.Id.HasValue()) + { + jsonRoot["id"] = keyRotationPolicy.Id.Value(); + } + + if (keyRotationPolicy.LifetimeActions.HasValue()) + { + jsonRoot["lifetimeActions"] = Core::Json::_internal::json::array(); + + const size_t size = keyRotationPolicy.LifetimeActions.Value().size(); + for (size_t i = 0; i < size; ++i) + { + if (keyRotationPolicy.LifetimeActions.Value()[i].Trigger.HasValue()) + { + if (keyRotationPolicy.LifetimeActions.Value()[i] + .Trigger.Value() + .TimeAfterCreate.HasValue()) + { + jsonRoot["lifetimeActions"][i]["trigger"]["timeAfterCreate"] + = keyRotationPolicy.LifetimeActions.Value()[i] + .Trigger.Value() + .TimeAfterCreate.Value(); + } + + if (keyRotationPolicy.LifetimeActions.Value()[i] + .Trigger.Value() + .TimeBeforeExpiry.HasValue()) + { + jsonRoot["lifetimeActions"][i]["trigger"]["timeBeforeExpiry"] + = keyRotationPolicy.LifetimeActions.Value()[i] + .Trigger.Value() + .TimeBeforeExpiry.Value(); + } + } + + if (keyRotationPolicy.LifetimeActions.Value()[i].Action.HasValue()) + { + if (keyRotationPolicy.LifetimeActions.Value()[i].Action.Value().Type.HasValue()) + { + jsonRoot["lifetimeActions"][i]["action"]["type"] + = keyRotationPolicy.LifetimeActions.Value()[i] + .Action.Value() + .Type.Value() + .ToString(); + } + } + } + } + + if (keyRotationPolicy.Attributes.HasValue()) + { + if (keyRotationPolicy.Attributes.Value().ExpiryTime.HasValue()) + { + jsonRoot["attributes"]["expiryTime"] + = keyRotationPolicy.Attributes.Value().ExpiryTime.Value(); + } + + if (keyRotationPolicy.Attributes.Value().Created.HasValue()) + { + jsonRoot["attributes"]["created"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + keyRotationPolicy.Attributes.Value().Created.Value()); + } + + if (keyRotationPolicy.Attributes.Value().Updated.HasValue()) + { + jsonRoot["attributes"]["updated"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + keyRotationPolicy.Attributes.Value().Updated.Value()); + } + } + + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Put, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyRotationPolicy response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("lifetimeActions") && !jsonRoot["lifetimeActions"].is_null()) + { + response.LifetimeActions = std::vector{}; + + for (auto const& jsonItem : jsonRoot["lifetimeActions"]) + { + Models::LifetimeActions vectorItem{}; + + if (jsonItem.contains("trigger") && !jsonItem["trigger"].is_null()) + { + vectorItem.Trigger = Models::LifetimeActionsTrigger{}; + + if (jsonItem["trigger"].contains("timeAfterCreate") + && !jsonItem["trigger"]["timeAfterCreate"].is_null()) + { + vectorItem.Trigger.Value().TimeAfterCreate + = jsonItem["trigger"]["timeAfterCreate"].get(); + } + + if (jsonItem["trigger"].contains("timeBeforeExpiry") + && !jsonItem["trigger"]["timeBeforeExpiry"].is_null()) + { + vectorItem.Trigger.Value().TimeBeforeExpiry + = jsonItem["trigger"]["timeBeforeExpiry"].get(); + } + } + + if (jsonItem.contains("action") && !jsonItem["action"].is_null()) + { + vectorItem.Action = Models::LifetimeActionsType{}; + + if (jsonItem["action"].contains("type") && !jsonItem["action"]["type"].is_null()) + { + vectorItem.Action.Value().Type = Models::KeyRotationPolicyAction( + jsonItem["action"]["type"].get()); + } + } + + response.LifetimeActions.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyRotationPolicyAttributes{}; + + if (jsonRoot["attributes"].contains("expiryTime") + && !jsonRoot["attributes"]["expiryTime"].is_null()) + { + response.Attributes.Value().ExpiryTime + = jsonRoot["attributes"]["expiryTime"].get(); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::GetRandomBytes( + const Models::GetRandomBytesRequest& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("rng"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["count"] = parameters.Count; + jsonBody = jsonRoot.dump(); + } + + Core::IO::MemoryBodyStream requestBody( + reinterpret_cast(jsonBody.data()), jsonBody.length()); + + Core::Http::Request request(Core::Http::HttpMethod::Post, url, &requestBody); + + request.SetHeader("Content-Type", "application/json"); + request.SetHeader("Accept", "application/json"); + + request.SetHeader("Content-Length", std::to_string(requestBody.Length())); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::RandomBytes response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + response.Value + = Core::_internal::Base64Url::Base64UrlDecode(jsonRoot["value"].get()); + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::GetKeyAttestation( + const std::string& keyName, + const std::string& keyVersion, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("keys/"); + if (keyName.empty()) + { + throw std::invalid_argument("Parameter 'keyName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyName)); + if (keyVersion.empty()) + { + throw std::invalid_argument("Parameter 'keyVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(keyVersion)); + url.AppendPath("attestation"); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + Core::Http::Request request(Core::Http::HttpMethod::Get, url); + + request.SetHeader("Accept", "application/json"); + + auto rawResponse = m_pipeline->Send(request, context); + const auto httpStatusCode = rawResponse->GetStatusCode(); + + if (httpStatusCode != Core::Http::HttpStatusCode::Ok) + { + throw Core::RequestFailedException(rawResponse); + } + + Models::KeyBundle response{}; + { + const auto& responseBody = rawResponse->GetBody(); + if (responseBody.size() > 0) + { + try + { + const auto jsonRoot + = Core::Json::_internal::json::parse(responseBody.begin(), responseBody.end()); + + if (jsonRoot.contains("key") && !jsonRoot["key"].is_null()) + { + response.Key = Models::JsonWebKey{}; + + if (jsonRoot["key"].contains("kid") && !jsonRoot["key"]["kid"].is_null()) + { + response.Key.Value().Kid = jsonRoot["key"]["kid"].get(); + } + + if (jsonRoot["key"].contains("kty") && !jsonRoot["key"]["kty"].is_null()) + { + response.Key.Value().Kty + = Models::JsonWebKeyType(jsonRoot["key"]["kty"].get()); + } + + if (jsonRoot["key"].contains("key_ops") && !jsonRoot["key"]["key_ops"].is_null()) + { + response.Key.Value().KeyOps = std::vector{}; + + for (auto const& jsonItem : jsonRoot["key"]["key_ops"]) + { + std::string vectorItem{}; + + vectorItem = jsonItem.get(); + + response.Key.Value().KeyOps.Value().emplace_back(std::move(vectorItem)); + } + } + + if (jsonRoot["key"].contains("n") && !jsonRoot["key"]["n"].is_null()) + { + response.Key.Value().N = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["n"].get()); + } + + if (jsonRoot["key"].contains("e") && !jsonRoot["key"]["e"].is_null()) + { + response.Key.Value().E = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["e"].get()); + } + + if (jsonRoot["key"].contains("d") && !jsonRoot["key"]["d"].is_null()) + { + response.Key.Value().D = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["d"].get()); + } + + if (jsonRoot["key"].contains("dp") && !jsonRoot["key"]["dp"].is_null()) + { + response.Key.Value().Dp = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dp"].get()); + } + + if (jsonRoot["key"].contains("dq") && !jsonRoot["key"]["dq"].is_null()) + { + response.Key.Value().Dq = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["dq"].get()); + } + + if (jsonRoot["key"].contains("qi") && !jsonRoot["key"]["qi"].is_null()) + { + response.Key.Value().Qi = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["qi"].get()); + } + + if (jsonRoot["key"].contains("p") && !jsonRoot["key"]["p"].is_null()) + { + response.Key.Value().P = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["p"].get()); + } + + if (jsonRoot["key"].contains("q") && !jsonRoot["key"]["q"].is_null()) + { + response.Key.Value().Q = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["q"].get()); + } + + if (jsonRoot["key"].contains("k") && !jsonRoot["key"]["k"].is_null()) + { + response.Key.Value().K = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["k"].get()); + } + + if (jsonRoot["key"].contains("key_hsm") && !jsonRoot["key"]["key_hsm"].is_null()) + { + response.Key.Value().T = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["key_hsm"].get()); + } + + if (jsonRoot["key"].contains("crv") && !jsonRoot["key"]["crv"].is_null()) + { + response.Key.Value().Crv + = Models::JsonWebKeyCurveName(jsonRoot["key"]["crv"].get()); + } + + if (jsonRoot["key"].contains("x") && !jsonRoot["key"]["x"].is_null()) + { + response.Key.Value().X = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["x"].get()); + } + + if (jsonRoot["key"].contains("y") && !jsonRoot["key"]["y"].is_null()) + { + response.Key.Value().Y = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["key"]["y"].get()); + } + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::KeyAttributes{}; + + if (jsonRoot["attributes"].contains("enabled") + && !jsonRoot["attributes"]["enabled"].is_null()) + { + response.Attributes.Value().Enabled = jsonRoot["attributes"]["enabled"].get(); + } + + if (jsonRoot["attributes"].contains("nbf") && !jsonRoot["attributes"]["nbf"].is_null()) + { + response.Attributes.Value().NotBefore + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["nbf"].is_string() + ? std::stoll(jsonRoot["attributes"]["nbf"].get()) + : jsonRoot["attributes"]["nbf"].get()); + } + + if (jsonRoot["attributes"].contains("exp") && !jsonRoot["attributes"]["exp"].is_null()) + { + response.Attributes.Value().Expires + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["exp"].is_string() + ? std::stoll(jsonRoot["attributes"]["exp"].get()) + : jsonRoot["attributes"]["exp"].get()); + } + + if (jsonRoot["attributes"].contains("created") + && !jsonRoot["attributes"]["created"].is_null()) + { + response.Attributes.Value().Created + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["created"].is_string() + ? std::stoll(jsonRoot["attributes"]["created"].get()) + : jsonRoot["attributes"]["created"].get()); + } + + if (jsonRoot["attributes"].contains("updated") + && !jsonRoot["attributes"]["updated"].is_null()) + { + response.Attributes.Value().Updated + = Core::_internal::PosixTimeConverter::PosixTimeToDateTime( + jsonRoot["attributes"]["updated"].is_string() + ? std::stoll(jsonRoot["attributes"]["updated"].get()) + : jsonRoot["attributes"]["updated"].get()); + } + + if (jsonRoot["attributes"].contains("recoverableDays") + && !jsonRoot["attributes"]["recoverableDays"].is_null()) + { + response.Attributes.Value().RecoverableDays + = jsonRoot["attributes"]["recoverableDays"].is_string() + ? std::stoi(jsonRoot["attributes"]["recoverableDays"].get()) + : jsonRoot["attributes"]["recoverableDays"].get(); + } + + if (jsonRoot["attributes"].contains("recoveryLevel") + && !jsonRoot["attributes"]["recoveryLevel"].is_null()) + { + response.Attributes.Value().RecoveryLevel = Models::DeletionRecoveryLevel( + jsonRoot["attributes"]["recoveryLevel"].get()); + } + + if (jsonRoot["attributes"].contains("exportable") + && !jsonRoot["attributes"]["exportable"].is_null()) + { + response.Attributes.Value().Exportable + = jsonRoot["attributes"]["exportable"].get(); + } + + if (jsonRoot["attributes"].contains("hsmPlatform") + && !jsonRoot["attributes"]["hsmPlatform"].is_null()) + { + response.Attributes.Value().HsmPlatform + = jsonRoot["attributes"]["hsmPlatform"].get(); + } + + if (jsonRoot["attributes"].contains("attestation") + && !jsonRoot["attributes"]["attestation"].is_null()) + { + response.Attributes.Value().Attestation = Models::KeyAttestation{}; + + if (jsonRoot["attributes"]["attestation"].contains("certificatePemFile") + && !jsonRoot["attributes"]["attestation"]["certificatePemFile"].is_null()) + { + response.Attributes.Value().Attestation.Value().CertificatePemFile + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["certificatePemFile"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("privateKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["privateKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PrivateKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["privateKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("publicKeyAttestation") + && !jsonRoot["attributes"]["attestation"]["publicKeyAttestation"].is_null()) + { + response.Attributes.Value().Attestation.Value().PublicKeyAttestation + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["attributes"]["attestation"]["publicKeyAttestation"] + .get()); + } + + if (jsonRoot["attributes"]["attestation"].contains("version") + && !jsonRoot["attributes"]["attestation"]["version"].is_null()) + { + response.Attributes.Value().Attestation.Value().Version + = jsonRoot["attributes"]["attestation"]["version"].get(); + } + } + } + + if (jsonRoot.contains("tags") && !jsonRoot["tags"].is_null()) + { + response.Tags = std::map{}; + + for (auto const& kv : jsonRoot["tags"].items()) + { + std::string value{}; + value = kv.value().get(); + response.Tags.Value().emplace(kv.key(), value); + } + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + + if (jsonRoot.contains("release_policy") && !jsonRoot["release_policy"].is_null()) + { + response.ReleasePolicy = Models::KeyReleasePolicy{}; + + if (jsonRoot["release_policy"].contains("contentType") + && !jsonRoot["release_policy"]["contentType"].is_null()) + { + response.ReleasePolicy.Value().ContentType + = jsonRoot["release_policy"]["contentType"].get(); + } + + if (jsonRoot["release_policy"].contains("immutable") + && !jsonRoot["release_policy"]["immutable"].is_null()) + { + response.ReleasePolicy.Value().Immutable + = jsonRoot["release_policy"]["immutable"].get(); + } + + if (jsonRoot["release_policy"].contains("data") + && !jsonRoot["release_policy"]["data"].is_null()) + { + response.ReleasePolicy.Value().EncodedPolicy + = Core::_internal::Base64Url::Base64UrlDecode( + jsonRoot["release_policy"]["data"].get()); + } + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.hpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.hpp new file mode 100644 index 000000000..96448aa87 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client.hpp @@ -0,0 +1,471 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "key_vault_client_options.hpp" +#include "key_vault_client_paged_responses.hpp" +#include "keys_models.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail { + /** + * @brief The key vault client performs cryptographic key operations and vault operations against + * the Key Vault service. + * + */ + class KeyVaultClient final { + public: + /** + * @brief Constructs the KeyVaultClient. + * @param url The URL address where the client will send the requests to. + * @param credential Credential to authenticate with the service. + * @param options Optional parameters. + * + */ + explicit KeyVaultClient( + const std::string& url, + const std::shared_ptr& credential, + const KeyVaultClientOptions& options = {}); + + /** + * @brief Gets the KeyVaultClient URL endpoint. + * @return The KeyVaultClient's URL endpoint. + * + */ + std::string GetUrl() const; + + /** + * @brief The create key operation can be used to create any key type in Azure Key Vault. If the + * named key already exists, Azure Key Vault creates a new version of the key. It requires the + * keys/create permission. + * @param keyName The name for the new key. The system will generate the version name for the + * new key. The value you provide may be copied globally for the purpose of running the service. + * The value provided should not include personally identifiable or sensitive information. + * @param parameters The parameters to create a key. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response CreateKey( + const std::string& keyName, + const Models::KeyCreateParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The operation will rotate the key based on the key policy. It requires the keys/rotate + * permission. + * @param keyName The name of key to be rotated. The system will generate a new version in the + * specified key. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response RotateKey( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief The import key operation may be used to import any key type into an Azure Key Vault. + * If the named key already exists, Azure Key Vault creates a new version of the key. This + * operation requires the keys/import permission. + * @param keyName Name for the imported key. The value you provide may be copied globally for + * the purpose of running the service. The value provided should not include personally + * identifiable or sensitive information. + * @param parameters The parameters to import a key. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response ImportKey( + const std::string& keyName, + const Models::KeyImportParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The delete key operation cannot be used to remove individual versions of a key. This + * operation removes the cryptographic material associated with the key, which means the key is + * not usable for Sign/Verify, Wrap/Unwrap or Encrypt/Decrypt operations. This operation + * requires the keys/delete permission. + * @param keyName The name of the key to delete. + * @param context The context for the operation can be used for request cancellation. + * @return A DeletedKeyBundle consisting of a WebKey plus its Attributes and deletion info + * + */ + Response DeleteKey( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief In order to perform this operation, the key must already exist in the Key Vault. Note: + * The cryptographic material of a key itself cannot be changed. This operation requires the + * keys/update permission. + * @param keyName The name of key to update. + * @param keyVersion The version of the key to update. + * @param parameters The parameters of the key to update. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response UpdateKey( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyUpdateParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The get key operation is applicable to all key types. If the requested key is + * symmetric, then no key material is released in the response. This operation requires the + * keys/get permission. + * @param keyName The name of the key to get. + * @param keyVersion Adding the version parameter retrieves a specific version of a key. This + * URI fragment is optional. If not specified, the latest version of the key is returned. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response GetKey( + const std::string& keyName, + const std::string& keyVersion, + const Core::Context& context = {}) const; + + /** + * @brief The full key identifier, attributes, and tags are provided in the response. This + * operation requires the keys/list permission. + * @param keyName The name of the key. + * @param options Optional parameters. + * @param context The context for the operation can be used for request cancellation. + * @return The key list result. + * + */ + GetKeyVersionsPagedResponse GetKeyVersions( + const std::string& keyName, + const KeyVaultClientGetKeyVersionsOptions& options = {}, + const Core::Context& context = {}) const; + + /** + * @brief Retrieves a list of the keys in the Key Vault as JSON Web Key structures that contain + * the public part of a stored key. The LIST operation is applicable to all key types, however + * only the base key identifier, attributes, and tags are provided in the response. Individual + * versions of a key are not listed in the response. This operation requires the keys/list + * permission. + * @param options Optional parameters. + * @param context The context for the operation can be used for request cancellation. + * @return The key list result. + * + */ + GetKeysPagedResponse GetKeys( + const KeyVaultClientGetKeysOptions& options = {}, + const Core::Context& context = {}) const; + + /** + * @brief The Key Backup operation exports a key from Azure Key Vault in a protected form. Note + * that this operation does NOT return key material in a form that can be used outside the Azure + * Key Vault system, the returned key material is either protected to a Azure Key Vault HSM or + * to Azure Key Vault itself. The intent of this operation is to allow a client to GENERATE a + * key in one Azure Key Vault instance, BACKUP the key, and then RESTORE it into another Azure + * Key Vault instance. The BACKUP operation may be used to export, in protected form, any key + * type from Azure Key Vault. Individual versions of a key cannot be backed up. BACKUP / RESTORE + * can be performed within geographical boundaries only; meaning that a BACKUP from one + * geographical area cannot be restored to another geographical area. For example, a backup from + * the US geographical area cannot be restored in an EU geographical area. This operation + * requires the key/backup permission. + * @param keyName The name of the key. + * @param context The context for the operation can be used for request cancellation. + * @return The backup key result, containing the backup blob. + * + */ + Response BackupKey( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief Imports a previously backed up key into Azure Key Vault, restoring the key, its key + * identifier, attributes and access control policies. The RESTORE operation may be used to + * import a previously backed up key. Individual versions of a key cannot be restored. The key + * is restored in its entirety with the same key name as it had when it was backed up. If the + * key name is not available in the target Key Vault, the RESTORE operation will be rejected. + * While the key name is retained during restore, the final key identifier will change if the + * key is restored to a different vault. Restore will restore all versions and preserve version + * identifiers. The RESTORE operation is subject to security constraints: The target Key Vault + * must be owned by the same Microsoft Azure Subscription as the source Key Vault The user must + * have RESTORE permission in the target Key Vault. This operation requires the keys/restore + * permission. + * @param parameters The parameters to restore the key. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response RestoreKey( + const Models::KeyRestoreParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The ENCRYPT operation encrypts an arbitrary sequence of bytes using an encryption key + * that is stored in Azure Key Vault. Note that the ENCRYPT operation only supports a single + * block of data, the size of which is dependent on the target key and the encryption algorithm + * to be used. The ENCRYPT operation is only strictly necessary for symmetric keys stored in + * Azure Key Vault since protection with an asymmetric key can be performed using public portion + * of the key. This operation is supported for asymmetric keys as a convenience for callers that + * have a key-reference but do not have access to the public key material. This operation + * requires the keys/encrypt permission. + * @param keyName The name of the key. + * @param keyVersion The version of the key. + * @param parameters The parameters for the encryption operation. + * @param context The context for the operation can be used for request cancellation. + * @return The key operation result. + * + */ + Response Encrypt( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The DECRYPT operation decrypts a well-formed block of ciphertext using the target + * encryption key and specified algorithm. This operation is the reverse of the ENCRYPT + * operation; only a single block of data may be decrypted, the size of this block is dependent + * on the target key and the algorithm to be used. The DECRYPT operation applies to asymmetric + * and symmetric keys stored in Azure Key Vault since it uses the private portion of the key. + * This operation requires the keys/decrypt permission. Microsoft recommends not to use CBC + * algorithms for decryption without first ensuring the integrity of the ciphertext using an + * HMAC, for example. See + * https://learn.microsoft.com/dotnet/standard/security/vulnerabilities-cbc-mode for more + * information. + * @param keyName The name of the key. + * @param keyVersion The version of the key. + * @param parameters The parameters for the decryption operation. + * @param context The context for the operation can be used for request cancellation. + * @return The key operation result. + * + */ + Response Decrypt( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The SIGN operation is applicable to asymmetric and symmetric keys stored in Azure Key + * Vault since this operation uses the private portion of the key. This operation requires the + * keys/sign permission. + * @param keyName The name of the key. + * @param keyVersion The version of the key. + * @param parameters The parameters for the signing operation. + * @param context The context for the operation can be used for request cancellation. + * @return The key operation result. + * + */ + Response Sign( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeySignParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The VERIFY operation is applicable to symmetric keys stored in Azure Key Vault. VERIFY + * is not strictly necessary for asymmetric keys stored in Azure Key Vault since signature + * verification can be performed using the public portion of the key but this operation is + * supported as a convenience for callers that only have a key-reference and not the public + * portion of the key. This operation requires the keys/verify permission. + * @param keyName The name of the key. + * @param keyVersion The version of the key. + * @param parameters The parameters for verify operations. + * @param context The context for the operation can be used for request cancellation. + * @return The key verify result. + * + */ + Response Verify( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyVerifyParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The WRAP operation supports encryption of a symmetric key using a key encryption key + * that has previously been stored in an Azure Key Vault. The WRAP operation is only strictly + * necessary for symmetric keys stored in Azure Key Vault since protection with an asymmetric + * key can be performed using the public portion of the key. This operation is supported for + * asymmetric keys as a convenience for callers that have a key-reference but do not have access + * to the public key material. This operation requires the keys/wrapKey permission. + * @param keyName The name of the key. + * @param keyVersion The version of the key. + * @param parameters The parameters for wrap operation. + * @param context The context for the operation can be used for request cancellation. + * @return The key operation result. + * + */ + Response WrapKey( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The UNWRAP operation supports decryption of a symmetric key using the target key + * encryption key. This operation is the reverse of the WRAP operation. The UNWRAP operation + * applies to asymmetric and symmetric keys stored in Azure Key Vault since it uses the private + * portion of the key. This operation requires the keys/unwrapKey permission. + * @param keyName The name of the key. + * @param keyVersion The version of the key. + * @param parameters The parameters for the key operation. + * @param context The context for the operation can be used for request cancellation. + * @return The key operation result. + * + */ + Response UnwrapKey( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyOperationsParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The release key operation is applicable to all key types. The target key must be + * marked exportable. This operation requires the keys/release permission. + * @param keyName The name of the key to get. + * @param keyVersion Adding the version parameter retrieves a specific version of a key. + * @param parameters The parameters for the key release operation. + * @param context The context for the operation can be used for request cancellation. + * @return The release result, containing the released key. + * + */ + Response Release( + const std::string& keyName, + const std::string& keyVersion, + const Models::KeyReleaseParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief Retrieves a list of the keys in the Key Vault as JSON Web Key structures that contain + * the public part of a deleted key. This operation includes deletion-specific information. The + * Get Deleted Keys operation is applicable for vaults enabled for soft-delete. While the + * operation can be invoked on any vault, it will return an error if invoked on a non + * soft-delete enabled vault. This operation requires the keys/list permission. + * @param options Optional parameters. + * @param context The context for the operation can be used for request cancellation. + * @return A list of keys that have been deleted in this vault. + * + */ + GetDeletedKeysPagedResponse GetDeletedKeys( + const KeyVaultClientGetDeletedKeysOptions& options = {}, + const Core::Context& context = {}) const; + + /** + * @brief The Get Deleted Key operation is applicable for soft-delete enabled vaults. While the + * operation can be invoked on any vault, it will return an error if invoked on a non + * soft-delete enabled vault. This operation requires the keys/get permission. + * @param keyName The name of the key. + * @param context The context for the operation can be used for request cancellation. + * @return A DeletedKeyBundle consisting of a WebKey plus its Attributes and deletion info + * + */ + Response GetDeletedKey( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief The Purge Deleted Key operation is applicable for soft-delete enabled vaults. While + * the operation can be invoked on any vault, it will return an error if invoked on a non + * soft-delete enabled vault. This operation requires the keys/purge permission. + * @param keyName The name of the key + * @param context The context for the operation can be used for request cancellation. + * @return Operation result. + * + */ + Response PurgeDeletedKey( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief The Recover Deleted Key operation is applicable for deleted keys in soft-delete + * enabled vaults. It recovers the deleted key back to its latest version under /keys. An + * attempt to recover an non-deleted key will return an error. Consider this the inverse of the + * delete operation on soft-delete enabled vaults. This operation requires the keys/recover + * permission. + * @param keyName The name of the deleted key. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response RecoverDeletedKey( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief The GetKeyRotationPolicy operation returns the specified key policy resources in the + * specified key vault. This operation requires the keys/get permission. + * @param keyName The name of the key in a given key vault. + * @param context The context for the operation can be used for request cancellation. + * @return Management policy for a key. + * + */ + Response GetKeyRotationPolicy( + const std::string& keyName, + const Core::Context& context = {}) const; + + /** + * @brief Set specified members in the key policy. Leave others as undefined. This operation + * requires the keys/update permission. + * @param keyName The name of the key in the given vault. + * @param keyRotationPolicy The policy for the key. + * @param context The context for the operation can be used for request cancellation. + * @return Management policy for a key. + * + */ + Response UpdateKeyRotationPolicy( + const std::string& keyName, + const Models::KeyRotationPolicy& keyRotationPolicy, + const Core::Context& context = {}) const; + + /** + * @brief Get the requested number of bytes containing random values from a managed HSM. + * @param parameters The request object to get random bytes. + * @param context The context for the operation can be used for request cancellation. + * @return The get random bytes response object containing the bytes. + * + */ + Response GetRandomBytes( + const Models::GetRandomBytesRequest& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The get key attestation operation returns the key along with its attestation blob. + * This operation requires the keys/get permission. + * @param keyName The name of the key to retrieve attestation for. + * @param keyVersion Adding the version parameter retrieves attestation blob for specific + * version of a key. This URI fragment is optional. If not specified, the latest version of the + * key attestation blob is returned. + * @param context The context for the operation can be used for request cancellation. + * @return A KeyBundle consisting of a WebKey plus its attributes. + * + */ + Response GetKeyAttestation( + const std::string& keyName, + const std::string& keyVersion, + const Core::Context& context = {}) const; + + private: + std::shared_ptr m_pipeline; + Core::Url m_url; + std::string m_apiVersion; + }; +}}}}} // namespace Azure::Security::KeyVault::Keys::_detail diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_options.hpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_options.hpp new file mode 100644 index 000000000..22b992dcd --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_options.hpp @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "keys_models.hpp" + +#include +#include + +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail { + /** + * @brief KeyVaultClient options. + * + */ + struct KeyVaultClientOptions final : public Core::_internal::ClientOptions + { + /// The API version to use for this operation. + std::string ApiVersion = "7.6-preview.2"; + }; + + /** + * @brief GetKeyVersions operation options. + * + */ + struct KeyVaultClientGetKeyVersionsOptions final + { + /// The URL to fetch the next page of results. + std::string NextPageToken; + + /// Maximum number of results to return in a page. If not specified the service will return up + /// to 25 results. + Nullable Maxresults; + }; + + /** + * @brief GetKeys operation options. + * + */ + struct KeyVaultClientGetKeysOptions final + { + /// The URL to fetch the next page of results. + std::string NextPageToken; + + /// Maximum number of results to return in a page. If not specified the service will return up + /// to 25 results. + Nullable Maxresults; + }; + + /** + * @brief GetDeletedKeys operation options. + * + */ + struct KeyVaultClientGetDeletedKeysOptions final + { + /// The URL to fetch the next page of results. + std::string NextPageToken; + + /// Maximum number of results to return in a page. If not specified the service will return up + /// to 25 results. + Nullable Maxresults; + }; +}}}}} // namespace Azure::Security::KeyVault::Keys::_detail diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_paged_responses.hpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_paged_responses.hpp new file mode 100644 index 000000000..24c7cff4c --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/key_vault_client_paged_responses.hpp @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "key_vault_client_options.hpp" +#include "keys_models.hpp" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail { + class KeyVaultClient; + + /** + * @brief The key list result. + * + */ + class GetKeyVersionsPagedResponse final + : public Core::PagedResponse { + friend class KeyVaultClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_keyName; + KeyVaultClientGetKeyVersionsOptions m_options; + + void OnNextPage(const Core::Context& context); + + public: + /// A response message containing a list of keys in the key vault along with a link to the next + /// page of keys. + Nullable> Value; + }; + + /** + * @brief The key list result. + * + */ + class GetKeysPagedResponse final : public Core::PagedResponse { + friend class KeyVaultClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + KeyVaultClientGetKeysOptions m_options; + + void OnNextPage(const Core::Context& context); + + public: + /// A response message containing a list of keys in the key vault along with a link to the next + /// page of keys. + Nullable> Value; + }; + + /** + * @brief A list of keys that have been deleted in this vault. + * + */ + class GetDeletedKeysPagedResponse final + : public Core::PagedResponse { + friend class KeyVaultClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + KeyVaultClientGetDeletedKeysOptions m_options; + + void OnNextPage(const Core::Context& context); + + public: + /// A response message containing a list of deleted keys in the key vault along with a link to + /// the next page of deleted keys. + Nullable> Value; + }; +}}}}} // namespace Azure::Security::KeyVault::Keys::_detail diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/keys.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/keys.cpp new file mode 100644 index 000000000..80eb97418 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/keys.cpp @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#include "keys_models.hpp" + +using namespace Azure::Security::KeyVault::Keys::_detail::Models; + +const JsonWebKeyType JsonWebKeyType::EC{"EC"}; +const JsonWebKeyType JsonWebKeyType::ECHsm{"EC-HSM"}; +const JsonWebKeyType JsonWebKeyType::Rsa{"RSA"}; +const JsonWebKeyType JsonWebKeyType::RsaHsm{"RSA-HSM"}; +const JsonWebKeyType JsonWebKeyType::Oct{"oct"}; +const JsonWebKeyType JsonWebKeyType::OctHsm{"oct-HSM"}; + +const JsonWebKeyCurveName JsonWebKeyCurveName::PTwoHundredFiftySix{"P-256"}; +const JsonWebKeyCurveName JsonWebKeyCurveName::PThreeHundredEightyFour{"P-384"}; +const JsonWebKeyCurveName JsonWebKeyCurveName::PFiveHundredTwentyOne{"P-521"}; +const JsonWebKeyCurveName JsonWebKeyCurveName::P256k{"P-256K"}; + +const DeletionRecoveryLevel DeletionRecoveryLevel::Purgeable{"Purgeable"}; +const DeletionRecoveryLevel DeletionRecoveryLevel::RecoverablePurgeable{"Recoverable+Purgeable"}; +const DeletionRecoveryLevel DeletionRecoveryLevel::Recoverable{"Recoverable"}; +const DeletionRecoveryLevel DeletionRecoveryLevel::RecoverableProtectedSubscription{ + "Recoverable+ProtectedSubscription"}; +const DeletionRecoveryLevel DeletionRecoveryLevel::CustomizedRecoverablePurgeable{ + "CustomizedRecoverable+Purgeable"}; +const DeletionRecoveryLevel DeletionRecoveryLevel::CustomizedRecoverable{"CustomizedRecoverable"}; +const DeletionRecoveryLevel DeletionRecoveryLevel::CustomizedRecoverableProtectedSubscription{ + "CustomizedRecoverable+ProtectedSubscription"}; + +const JsonWebKeyOperation JsonWebKeyOperation::Encrypt{"encrypt"}; +const JsonWebKeyOperation JsonWebKeyOperation::Decrypt{"decrypt"}; +const JsonWebKeyOperation JsonWebKeyOperation::Sign{"sign"}; +const JsonWebKeyOperation JsonWebKeyOperation::Verify{"verify"}; +const JsonWebKeyOperation JsonWebKeyOperation::WrapKey{"wrapKey"}; +const JsonWebKeyOperation JsonWebKeyOperation::UnwrapKey{"unwrapKey"}; +const JsonWebKeyOperation JsonWebKeyOperation::Import{"import"}; +const JsonWebKeyOperation JsonWebKeyOperation::Export{"export"}; + +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::RsaOaep{"RSA-OAEP"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::RsaOaepTwoHundredFiftySix{ + "RSA-OAEP-256"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::Rsa1Five{"RSA1_5"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A128gcm{"A128GCM"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A192gcm{"A192GCM"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A256gcm{"A256GCM"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A128kw{"A128KW"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A192kw{"A192KW"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A256kw{"A256KW"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A128cbc{"A128CBC"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A192cbc{"A192CBC"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A256cbc{"A256CBC"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A128cbcpad{"A128CBCPAD"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A192cbcpad{"A192CBCPAD"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::A256cbcpad{"A256CBCPAD"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::CkmAesKeyWrap{ + "CKM_AES_KEY_WRAP"}; +const JsonWebKeyEncryptionAlgorithm JsonWebKeyEncryptionAlgorithm::CkmAesKeyWrapPad{ + "CKM_AES_KEY_WRAP_PAD"}; + +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Ps256{"PS256"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Ps384{"PS384"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Ps512{"PS512"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Rs256{"RS256"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Rs384{"RS384"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Rs512{"RS512"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Hs256{"HS256"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Hs384{"HS384"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Hs512{"HS512"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Rsnull{"RSNULL"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Es256{"ES256"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Es384{"ES384"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Es512{"ES512"}; +const JsonWebKeySignatureAlgorithm JsonWebKeySignatureAlgorithm::Es256k{"ES256K"}; + +const KeyEncryptionAlgorithm KeyEncryptionAlgorithm::CkmRsaAesKeyWrap{"CKM_RSA_AES_KEY_WRAP"}; +const KeyEncryptionAlgorithm KeyEncryptionAlgorithm::RsaAesKeyWrapTwoHundredFiftySix{ + "RSA_AES_KEY_WRAP_256"}; +const KeyEncryptionAlgorithm KeyEncryptionAlgorithm::RsaAesKeyWrapThreeHundredEightyFour{ + "RSA_AES_KEY_WRAP_384"}; + +const KeyRotationPolicyAction KeyRotationPolicyAction::Rotate{"Rotate"}; +const KeyRotationPolicyAction KeyRotationPolicyAction::Notify{"Notify"}; diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/generated/keys_models.hpp b/sdk/keyvault/azure-security-keyvault-keys/src/generated/keys_models.hpp new file mode 100644 index 000000000..d989f5c9e --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/generated/keys_models.hpp @@ -0,0 +1,996 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. +// Code generated by Microsoft (R) TypeSpec Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +#pragma once + +#include "azure/keyvault/keys/dll_import_export.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail { + namespace Models { + /** + * @brief JsonWebKey Key Type (kty), as defined in + * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40. + * + */ + class JsonWebKeyType final : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new JsonWebKeyType instance. + * + **/ + JsonWebKeyType() = default; + + /** + * @brief Constructs a new JsonWebKeyType instance from a string. + * @param jsonWebKeyType String value to construct the new instance from. + * + **/ + explicit JsonWebKeyType(std::string jsonWebKeyType) + : ExtendableEnumeration(std::move(jsonWebKeyType)) + { + } + + /// Elliptic Curve. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyType EC; + + /// Elliptic Curve with a private key which is stored in the HSM. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyType ECHsm; + + /// RSA (https://tools.ietf.org/html/rfc3447) + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyType Rsa; + + /// RSA with a private key which is stored in the HSM. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyType RsaHsm; + + /// Octet sequence (used to represent symmetric keys) + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyType Oct; + + /// Octet sequence (used to represent symmetric keys) which is stored the HSM. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyType OctHsm; + }; + + /** + * @brief Elliptic curve name. For valid values, see JsonWebKeyCurveName. + * + */ + class JsonWebKeyCurveName final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new JsonWebKeyCurveName instance. + * + **/ + JsonWebKeyCurveName() = default; + + /** + * @brief Constructs a new JsonWebKeyCurveName instance from a string. + * @param jsonWebKeyCurveName String value to construct the new instance from. + * + **/ + explicit JsonWebKeyCurveName(std::string jsonWebKeyCurveName) + : ExtendableEnumeration(std::move(jsonWebKeyCurveName)) + { + } + + /// The NIST P-256 elliptic curve, AKA SECG curve SECP256R1. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyCurveName PTwoHundredFiftySix; + + /// The NIST P-384 elliptic curve, AKA SECG curve SECP384R1. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyCurveName PThreeHundredEightyFour; + + /// The NIST P-521 elliptic curve, AKA SECG curve SECP521R1. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyCurveName PFiveHundredTwentyOne; + + /// The SECG SECP256K1 elliptic curve. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyCurveName P256k; + }; + + /** + * @brief Reflects the deletion recovery level currently in effect for certificates in the + * current vault. If it contains 'Purgeable', the certificate can be permanently deleted by a + * privileged user; otherwise, only the system can purge the certificate, at the end of the + * retention interval. + * + */ + class DeletionRecoveryLevel final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new DeletionRecoveryLevel instance. + * + **/ + DeletionRecoveryLevel() = default; + + /** + * @brief Constructs a new DeletionRecoveryLevel instance from a string. + * @param deletionRecoveryLevel String value to construct the new instance from. + * + **/ + explicit DeletionRecoveryLevel(std::string deletionRecoveryLevel) + : ExtendableEnumeration(std::move(deletionRecoveryLevel)) + { + } + + /// Denotes a vault state in which deletion is an irreversible operation, without the + /// possibility for recovery. This level corresponds to no protection being available against + /// a Delete operation; the data is irretrievably lost upon accepting a Delete operation at + /// the entity level or higher (vault, resource group, subscription etc.) + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel Purgeable; + + /// Denotes a vault state in which deletion is recoverable, and which also permits immediate + /// and permanent deletion (i.e. purge). This level guarantees the recoverability of the + /// deleted entity during the retention interval (90 days), unless a Purge operation is + /// requested, or the subscription is cancelled. System wil permanently delete it after 90 + /// days, if not recovered + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel RecoverablePurgeable; + + /// Denotes a vault state in which deletion is recoverable without the possibility for + /// immediate and permanent deletion (i.e. purge). This level guarantees the recoverability of + /// the deleted entity during the retention interval(90 days) and while the subscription is + /// still available. System wil permanently delete it after 90 days, if not recovered + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel Recoverable; + + /// Denotes a vault and subscription state in which deletion is recoverable within retention + /// interval (90 days), immediate and permanent deletion (i.e. purge) is not permitted, and in + /// which the subscription itself cannot be permanently canceled. System wil permanently + /// delete it after 90 days, if not recovered + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel + RecoverableProtectedSubscription; + + /// Denotes a vault state in which deletion is recoverable, and which also permits immediate + /// and permanent deletion (i.e. purge when 7 <= SoftDeleteRetentionInDays < 90). This level + /// guarantees the recoverability of the deleted entity during the retention interval, unless + /// a Purge operation is requested, or the subscription is cancelled. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel + CustomizedRecoverablePurgeable; + + /// Denotes a vault state in which deletion is recoverable without the possibility for + /// immediate and permanent deletion (i.e. purge when 7 <= SoftDeleteRetentionInDays < + /// 90).This level guarantees the recoverability of the deleted entity during the retention + /// interval and while the subscription is still available. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel CustomizedRecoverable; + + /// Denotes a vault and subscription state in which deletion is recoverable, immediate and + /// permanent deletion (i.e. purge) is not permitted, and in which the subscription itself + /// cannot be permanently canceled when 7 <= SoftDeleteRetentionInDays < 90. This level + /// guarantees the recoverability of the deleted entity during the retention interval, and + /// also reflects the fact that the subscription itself cannot be cancelled. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const DeletionRecoveryLevel + CustomizedRecoverableProtectedSubscription; + }; + + /** + * @brief JSON web key operations. For more information, see JsonWebKeyOperation. + * + */ + class JsonWebKeyOperation final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new JsonWebKeyOperation instance. + * + **/ + JsonWebKeyOperation() = default; + + /** + * @brief Constructs a new JsonWebKeyOperation instance from a string. + * @param jsonWebKeyOperation String value to construct the new instance from. + * + **/ + explicit JsonWebKeyOperation(std::string jsonWebKeyOperation) + : ExtendableEnumeration(std::move(jsonWebKeyOperation)) + { + } + + /// Indicates that the key can be used to encrypt. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation Encrypt; + + /// Indicates that the key can be used to decrypt. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation Decrypt; + + /// Indicates that the key can be used to sign. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation Sign; + + /// Indicates that the key can be used to verify. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation Verify; + + /// Indicates that the key can be used to wrap another key. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation WrapKey; + + /// Indicates that the key can be used to unwrap another key. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation UnwrapKey; + + /// Indicates that the key can be imported during creation. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation Import; + + /// Indicates that the private component of the key can be exported. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyOperation Export; + }; + + /** + * @brief An algorithm used for encryption and decryption. + * + */ + class JsonWebKeyEncryptionAlgorithm final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new JsonWebKeyEncryptionAlgorithm instance. + * + **/ + JsonWebKeyEncryptionAlgorithm() = default; + + /** + * @brief Constructs a new JsonWebKeyEncryptionAlgorithm instance from a string. + * @param jsonWebKeyEncryptionAlgorithm String value to construct the new instance from. + * + **/ + explicit JsonWebKeyEncryptionAlgorithm(std::string jsonWebKeyEncryptionAlgorithm) + : ExtendableEnumeration(std::move(jsonWebKeyEncryptionAlgorithm)) + { + } + + /// [Not recommended] RSAES using Optimal Asymmetric Encryption Padding (OAEP), as described + /// in https://tools.ietf.org/html/rfc3447, with the default parameters specified by RFC 3447 + /// in Section A.2.1. Those default parameters are using a hash function of SHA-1 and a mask + /// generation function of MGF1 with SHA-1. Microsoft recommends using RSA_OAEP_256 or + /// stronger algorithms for enhanced security. Microsoft does *not* recommend RSA_OAEP, which + /// is included solely for backwards compatibility. RSA_OAEP utilizes SHA1, which has known + /// collision problems. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm RsaOaep; + + /// RSAES using Optimal Asymmetric Encryption Padding with a hash function of SHA-256 and a + /// mask generation function of MGF1 with SHA-256. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm + RsaOaepTwoHundredFiftySix; + + /// [Not recommended] RSAES-PKCS1-V1_5 key encryption, as described in + /// https://tools.ietf.org/html/rfc3447. Microsoft recommends using RSA_OAEP_256 or stronger + /// algorithms for enhanced security. Microsoft does *not* recommend RSA_1_5, which is + /// included solely for backwards compatibility. Cryptographic standards no longer consider + /// RSA with the PKCS#1 v1.5 padding scheme secure for encryption. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm Rsa1Five; + + /// 128-bit AES-GCM. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A128gcm; + + /// 192-bit AES-GCM. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A192gcm; + + /// 256-bit AES-GCM. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A256gcm; + + /// 128-bit AES key wrap. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A128kw; + + /// 192-bit AES key wrap. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A192kw; + + /// 256-bit AES key wrap. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A256kw; + + /// 128-bit AES-CBC. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A128cbc; + + /// 192-bit AES-CBC. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A192cbc; + + /// 256-bit AES-CBC. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A256cbc; + + /// 128-bit AES-CBC with PKCS padding. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A128cbcpad; + + /// 192-bit AES-CBC with PKCS padding. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A192cbcpad; + + /// 256-bit AES-CBC with PKCS padding. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm A256cbcpad; + + /// CKM AES key wrap. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm CkmAesKeyWrap; + + /// CKM AES key wrap with padding. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeyEncryptionAlgorithm + CkmAesKeyWrapPad; + }; + + /** + * @brief The signing/verification algorithm identifier. For more information on possible + * algorithm types, see JsonWebKeySignatureAlgorithm. + * + */ + class JsonWebKeySignatureAlgorithm final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new JsonWebKeySignatureAlgorithm instance. + * + **/ + JsonWebKeySignatureAlgorithm() = default; + + /** + * @brief Constructs a new JsonWebKeySignatureAlgorithm instance from a string. + * @param jsonWebKeySignatureAlgorithm String value to construct the new instance from. + * + **/ + explicit JsonWebKeySignatureAlgorithm(std::string jsonWebKeySignatureAlgorithm) + : ExtendableEnumeration(std::move(jsonWebKeySignatureAlgorithm)) + { + } + + /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256, as described in + /// https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Ps256; + + /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384, as described in + /// https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Ps384; + + /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512, as described in + /// https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Ps512; + + /// RSASSA-PKCS1-v1_5 using SHA-256, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Rs256; + + /// RSASSA-PKCS1-v1_5 using SHA-384, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Rs384; + + /// RSASSA-PKCS1-v1_5 using SHA-512, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Rs512; + + /// HMAC using SHA-256, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Hs256; + + /// HMAC using SHA-384, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Hs384; + + /// HMAC using SHA-512, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Hs512; + + /// Reserved + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Rsnull; + + /// ECDSA using P-256 and SHA-256, as described in https://tools.ietf.org/html/rfc7518. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Es256; + + /// ECDSA using P-384 and SHA-384, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Es384; + + /// ECDSA using P-521 and SHA-512, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Es512; + + /// ECDSA using P-256K and SHA-256, as described in https://tools.ietf.org/html/rfc7518 + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const JsonWebKeySignatureAlgorithm Es256k; + }; + + /** + * @brief The encryption algorithm to use to protected the exported key material + * + */ + class KeyEncryptionAlgorithm final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new KeyEncryptionAlgorithm instance. + * + **/ + KeyEncryptionAlgorithm() = default; + + /** + * @brief Constructs a new KeyEncryptionAlgorithm instance from a string. + * @param keyEncryptionAlgorithm String value to construct the new instance from. + * + **/ + explicit KeyEncryptionAlgorithm(std::string keyEncryptionAlgorithm) + : ExtendableEnumeration(std::move(keyEncryptionAlgorithm)) + { + } + + /// The CKM_RSA_AES_KEY_WRAP key wrap mechanism. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyEncryptionAlgorithm CkmRsaAesKeyWrap; + + /// The RSA_AES_KEY_WRAP_256 key wrap mechanism. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyEncryptionAlgorithm + RsaAesKeyWrapTwoHundredFiftySix; + + /// The RSA_AES_KEY_WRAP_384 key wrap mechanism. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyEncryptionAlgorithm + RsaAesKeyWrapThreeHundredEightyFour; + }; + + /** + * @brief The type of the action. The value should be compared case-insensitively. + * + */ + class KeyRotationPolicyAction final + : public Core::_internal::ExtendableEnumeration { + public: + /** + * @brief Constructs a new KeyRotationPolicyAction instance. + * + **/ + KeyRotationPolicyAction() = default; + + /** + * @brief Constructs a new KeyRotationPolicyAction instance from a string. + * @param keyRotationPolicyAction String value to construct the new instance from. + * + **/ + explicit KeyRotationPolicyAction(std::string keyRotationPolicyAction) + : ExtendableEnumeration(std::move(keyRotationPolicyAction)) + { + } + + /// Rotate the key based on the key policy. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyRotationPolicyAction Rotate; + + /// Trigger Event Grid events. Defaults to 30 days before expiry. Key Vault only. + AZ_SECURITY_KEYVAULT_KEYS_DLLEXPORT static const KeyRotationPolicyAction Notify; + }; + + /** + * @brief As of http://tools.ietf.org/html/draft-ietf-jose-json-web-key-18 + * + */ + struct JsonWebKey final + { + /// Key identifier. + Nullable Kid; + + /// JsonWebKey Key Type (kty), as defined in + /// https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40. + Nullable Kty; + + /// Json web key operations. For more information on possible key operations, see + /// JsonWebKeyOperation. + Nullable> KeyOps; + + /// RSA modulus. + Nullable> N; + + /// RSA public exponent. + Nullable> E; + + /// RSA private exponent, or the D component of an EC private key. + Nullable> D; + + /// RSA private key parameter. + Nullable> Dp; + + /// RSA private key parameter. + Nullable> Dq; + + /// RSA private key parameter. + Nullable> Qi; + + /// RSA secret prime. + Nullable> P; + + /// RSA secret prime, with p < q. + Nullable> Q; + + /// Symmetric key. + Nullable> K; + + /// Protected Key, used with 'Bring Your Own Key'. + Nullable> T; + + /// Elliptic curve name. For valid values, see JsonWebKeyCurveName. + Nullable Crv; + + /// X component of an EC public key. + Nullable> X; + + /// Y component of an EC public key. + Nullable> Y; + }; + + /** + * @brief The key attestation information. + * + */ + struct KeyAttestation final + { + /// A base64url-encoded string containing certificates in PEM format, used for attestation + /// validation. + Nullable> CertificatePemFile; + + /// The attestation blob bytes encoded as base64url string corresponding to a private key. + Nullable> PrivateKeyAttestation; + + /// The attestation blob bytes encoded as base64url string corresponding to a public key in + /// case of asymmetric key. + Nullable> PublicKeyAttestation; + + /// The version of the attestation. + Nullable Version; + }; + + /** + * @brief The attributes of a key managed by the key vault service. + * + */ + struct KeyAttributes final + { + /// Determines whether the object is enabled. + Nullable Enabled; + + /// Not before date in UTC. + Nullable NotBefore; + + /// Expiry date in UTC. + Nullable Expires; + + /// [out] Creation time in UTC. + Nullable Created; + + /// [out] Last updated time in UTC. + Nullable Updated; + + /// [out] softDelete data retention days. Value should be >=7 and <=90 when softDelete + /// enabled, otherwise 0. + Nullable RecoverableDays; + + /// [out] Reflects the deletion recovery level currently in effect for keys in the current + /// vault. If it contains 'Purgeable' the key can be permanently deleted by a privileged user; + /// otherwise, only the system can purge the key, at the end of the retention interval. + Nullable RecoveryLevel; + + /// Indicates if the private key can be exported. Release policy must be provided when + /// creating the first version of an exportable key. + Nullable Exportable; + + /// [out] The underlying HSM Platform. + Nullable HsmPlatform; + + /// The key or key version attestation information. + Nullable Attestation; + }; + + /** + * @brief The policy rules under which the key can be exported. + * + */ + struct KeyReleasePolicy final + { + /// Content type and version of key release policy + Nullable ContentType; + + /// Defines the mutability state of the policy. Once marked immutable, this flag cannot be + /// reset and the policy cannot be changed under any circumstances. + Nullable Immutable; + + /// Blob encoding the policy rules under which the key can be released. Blob must be base64 + /// URL encoded. + Nullable> EncodedPolicy; + }; + + /** + * @brief A KeyBundle consisting of a WebKey plus its attributes. + * + */ + struct KeyBundle final + { + /// The Json web key. + Nullable Key; + + /// The key management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// [out] True if the key's lifetime is managed by key vault. If this is a key backing a + /// certificate, then managed will be true. + Nullable Managed; + + /// The policy rules under which the key can be exported. + Nullable ReleasePolicy; + }; + + /** + * @brief The key create parameters. + * + */ + struct KeyCreateParameters final + { + /// The type of key to create. For valid values, see JsonWebKeyType. + JsonWebKeyType Kty; + + /// The key size in bits. For example: 2048, 3072, or 4096 for RSA. + Nullable KeySize; + + /// The public exponent for a RSA key. + Nullable PublicExponent; + + /// Json web key operations. For more information on possible key operations, see + /// JsonWebKeyOperation. + Nullable> KeyOps; + + /// The attributes of a key managed by the key vault service. + Nullable KeyAttributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// Elliptic curve name. For valid values, see JsonWebKeyCurveName. + Nullable Curve; + + /// The policy rules under which the key can be exported. + Nullable ReleasePolicy; + }; + + /** + * @brief The key import parameters. + * + */ + struct KeyImportParameters final + { + /// Whether to import as a hardware key (HSM) or software key. + Nullable Hsm; + + /// The Json web key + JsonWebKey Key; + + /// The key management attributes. + Nullable KeyAttributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// The policy rules under which the key can be exported. + Nullable ReleasePolicy; + }; + + /** + * @brief A DeletedKeyBundle consisting of a WebKey plus its Attributes and deletion info + * + */ + struct DeletedKeyBundle final + { + /// The Json web key. + Nullable Key; + + /// The key management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// [out] True if the key's lifetime is managed by key vault. If this is a key backing a + /// certificate, then managed will be true. + Nullable Managed; + + /// The policy rules under which the key can be exported. + Nullable ReleasePolicy; + + /// The url of the recovery object, used to identify and recover the deleted key. + Nullable RecoveryId; + + /// [out] The time when the key is scheduled to be purged, in UTC + Nullable ScheduledPurgeDate; + + /// [out] The time when the key was deleted, in UTC + Nullable DeletedDate; + }; + + /** + * @brief The key update parameters. + * + */ + struct KeyUpdateParameters final + { + /// Json web key operations. For more information on possible key operations, see + /// JsonWebKeyOperation. + Nullable> KeyOps; + + /// The attributes of a key managed by the key vault service. + Nullable KeyAttributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// The policy rules under which the key can be exported. + Nullable ReleasePolicy; + }; + + /** + * @brief The key item containing key metadata. + * + */ + struct KeyItem final + { + /// Key identifier. + Nullable Kid; + + /// The key management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// [out] True if the key's lifetime is managed by key vault. If this is a key backing a + /// certificate, then managed will be true. + Nullable Managed; + }; + + /** + * @brief The backup key result, containing the backup blob. + * + */ + struct BackupKeyResult final + { + /// [out] The backup blob containing the backed up key. + Nullable> Value; + }; + + /** + * @brief The key restore parameters. + * + */ + struct KeyRestoreParameters final + { + /// The backup blob associated with a key bundle. + std::vector KeyBundleBackup; + }; + + /** + * @brief The key operation result. + * + */ + struct KeyOperationResult final + { + /// [out] Key identifier + Nullable Kid; + + /// [out] The result of the operation. + Nullable> Result; + + /// [out] Cryptographically random, non-repeating initialization vector for symmetric + /// algorithms. + Nullable> Iv; + + /// [out] The tag to authenticate when performing decryption with an authenticated algorithm. + Nullable> AuthenticationTag; + + /// [out] Additional data to authenticate but not encrypt/decrypt when using authenticated + /// crypto algorithms. + Nullable> AdditionalAuthenticatedData; + }; + + /** + * @brief The key operations parameters. + * + */ + struct KeyOperationsParameters final + { + /// algorithm identifier + JsonWebKeyEncryptionAlgorithm Algorithm; + + /// The value to operate on. + std::vector Value; + + /// Cryptographically random, non-repeating initialization vector for symmetric algorithms. + Nullable> Iv; + + /// Additional data to authenticate but not encrypt/decrypt when using authenticated crypto + /// algorithms. + Nullable> Aad; + + /// The tag to authenticate when performing decryption with an authenticated algorithm. + Nullable> Tag; + }; + + /** + * @brief The key operations parameters. + * + */ + struct KeySignParameters final + { + /// The signing/verification algorithm identifier. For more information on possible algorithm + /// types, see JsonWebKeySignatureAlgorithm. + JsonWebKeySignatureAlgorithm Algorithm; + + /// The value to operate on. + std::vector Value; + }; + + /** + * @brief The key verify result. + * + */ + struct KeyVerifyResult final + { + /// [out] True if the signature is verified, otherwise false. + Nullable Value; + }; + + /** + * @brief The key verify parameters. + * + */ + struct KeyVerifyParameters final + { + /// The signing/verification algorithm. For more information on possible algorithm types, see + /// JsonWebKeySignatureAlgorithm. + JsonWebKeySignatureAlgorithm Algorithm; + + /// The digest used for signing. + std::vector Digest; + + /// The signature to be verified. + std::vector Signature; + }; + + /** + * @brief The release result, containing the released key. + * + */ + struct KeyReleaseResult final + { + /// [out] A signed object containing the released key. + Nullable Value; + }; + + /** + * @brief The release key parameters. + * + */ + struct KeyReleaseParameters final + { + /// The attestation assertion for the target of the key release. + std::string TargetAttestationToken; + + /// A client provided nonce for freshness. + Nullable Nonce; + + /// The encryption algorithm to use to protected the exported key material + Nullable Enc; + }; + + /** + * @brief The deleted key item containing the deleted key metadata and information about + * deletion. + * + */ + struct DeletedKeyItem final + { + /// Key identifier. + Nullable Kid; + + /// The key management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// [out] True if the key's lifetime is managed by key vault. If this is a key backing a + /// certificate, then managed will be true. + Nullable Managed; + + /// The url of the recovery object, used to identify and recover the deleted key. + Nullable RecoveryId; + + /// [out] The time when the key is scheduled to be purged, in UTC + Nullable ScheduledPurgeDate; + + /// [out] The time when the key was deleted, in UTC + Nullable DeletedDate; + }; + + /** + * @brief PurgeDeletedKey operation result. + * + */ + struct PurgeDeletedKeyResult final + { + }; + + /** + * @brief A condition to be satisfied for an action to be executed. + * + */ + struct LifetimeActionsTrigger final + { + /// Time after creation to attempt to rotate. It only applies to rotate. It will be in ISO + /// 8601 duration format. Example: 90 days : "P90D" + Nullable TimeAfterCreate; + + /// Time before expiry to attempt to rotate or notify. It will be in ISO 8601 duration format. + /// Example: 90 days : "P90D" + Nullable TimeBeforeExpiry; + }; + + /** + * @brief The action that will be executed. + * + */ + struct LifetimeActionsType final + { + /// The type of the action. The value should be compared case-insensitively. + Nullable Type; + }; + + /** + * @brief Action and its trigger that will be performed by Key Vault over the lifetime of a key. + * + */ + struct LifetimeActions final + { + /// The condition that will execute the action. + Nullable Trigger; + + /// The action that will be executed. + Nullable Action; + }; + + /** + * @brief The key rotation policy attributes. + * + */ + struct KeyRotationPolicyAttributes final + { + /// The expiryTime will be applied on the new key version. It should be at least 28 days. It + /// will be in ISO 8601 Format. Examples: 90 days: P90D, 3 months: P3M, 48 hours: PT48H, 1 + /// year and 10 days: P1Y10D + Nullable ExpiryTime; + + /// [out] The key rotation policy created time in UTC. + Nullable Created; + + /// [out] The key rotation policy's last updated time in UTC. + Nullable Updated; + }; + + /** + * @brief Management policy for a key. + * + */ + struct KeyRotationPolicy final + { + /// [out] The key policy id. + Nullable Id; + + /// Actions that will be performed by Key Vault over the lifetime of a key. For preview, + /// lifetimeActions can only have two items at maximum: one for rotate, one for notify. + /// Notification time would be default to 30 days before expiry and it is not configurable. + Nullable> LifetimeActions; + + /// The key rotation policy attributes. + Nullable Attributes; + }; + + /** + * @brief The get random bytes response object containing the bytes. + * + */ + struct RandomBytes final + { + /// The bytes encoded as a base64url string. + std::vector Value; + }; + + /** + * @brief The get random bytes request object. + * + */ + struct GetRandomBytesRequest final + { + /// The requested number of random bytes. + std::int32_t Count = 0; + }; +}}}}}} // namespace Azure::Security::KeyVault::Keys::_detail::Models 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 f827d1b8b..2f5faacd4 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/src/key_client.cpp @@ -3,6 +3,7 @@ #include "azure/keyvault/keys/key_client.hpp" +#include "./generated/key_vault_client.hpp" #include "private/cryptography_internal_access.hpp" #include "private/key_backup.hpp" #include "private/key_constants.hpp" @@ -30,47 +31,20 @@ using namespace Azure::Core::Http::Policies; using namespace Azure::Core::Http::Policies::_internal; using namespace Azure::Core::Http::_internal; -namespace { -constexpr const char CreateValue[] = "create"; -} // namespace - -std::unique_ptr KeyClient::SendRequest( - Azure::Core::Http::Request& request, - Azure::Core::Context const& context) const -{ - return Azure::Security::KeyVault::_detail::KeyVaultKeysCommonRequest::SendRequest( - *m_pipeline, request, context); -} - -Request KeyClient::CreateRequest( - HttpMethod method, - std::vector const& path, - Azure::Core::IO::BodyStream* content) const -{ - return Azure::Security::KeyVault::_detail::KeyVaultKeysCommonRequest::CreateRequest( - m_vaultUrl, m_apiVersion, std::move(method), path, content); -} - -Request KeyClient::ContinuationTokenRequest( - std::vector const& path, - const Azure::Nullable& NextPageToken) const -{ - if (NextPageToken) - { - // Using a continuation token requires to send the request to the continuation token URL instead - // of the default URL which is used only for the first page. - Azure::Core::Url nextPageUrl(NextPageToken.Value()); - return Request(HttpMethod::Get, nextPageUrl); - } - return CreateRequest(HttpMethod::Get, path); -} - KeyClient::KeyClient( std::string const& vaultUrl, std::shared_ptr credential, KeyClientOptions const& options) : m_vaultUrl(vaultUrl), m_apiVersion(options.ApiVersion) { + _detail::KeyVaultClientOptions generatedClientOptions; + static_cast(generatedClientOptions) + = static_cast(options); + generatedClientOptions.ApiVersion = options.ApiVersion; + m_client = std::make_shared<_detail::KeyVaultClient>( + _detail::KeyVaultClient(vaultUrl, credential, generatedClientOptions)); + + // pipeline needed for crypto client std::vector> perRetryPolicies; { Azure::Core::Credentials::TokenRequestContext tokenContext; @@ -95,13 +69,10 @@ Azure::Response KeyClient::GetKey( GetKeyOptions const& options, Azure::Core::Context const& context) const { - // Request with no payload - auto request = CreateRequest(HttpMethod::Get, {_detail::KeysPath, name, options.Version}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto result = m_client->GetKey(name, options.Version, context); + KeyVaultKey keyResult(result.Value); + keyResult.Properties.VaultUrl = m_vaultUrl.GetAbsoluteUrl(); + return Azure::Response(std::move(keyResult), std::move(result.RawResponse)); } Azure::Response KeyClient::CreateKey( @@ -110,99 +81,78 @@ Azure::Response KeyClient::CreateKey( CreateKeyOptions const& options, Azure::Core::Context const& context) const { - // Payload for the request - _detail::KeyRequestParameters const params(std::move(keyType), options); - auto payload = params.Serialize(); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request - = CreateRequest(HttpMethod::Post, {_detail::KeysPath, name, CreateValue}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + Models::KeyCreateParameters keyCreateParameters = options.ToKeyCreateParameters(); + keyCreateParameters.Kty = Models::JsonWebKeyType(keyType.ToString()); + auto result = m_client->CreateKey(name, keyCreateParameters, context); + KeyVaultKey keyResult(result.Value); + return Azure::Response(keyResult, std::move(result.RawResponse)); } Azure::Response KeyClient::CreateEcKey( CreateEcKeyOptions const& ecKeyOptions, Azure::Core::Context const& context) const { - // Payload for the request - std::string const& keyName = ecKeyOptions.GetName(); - auto payload = _detail::KeyRequestParameters(ecKeyOptions).Serialize(); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request - = CreateRequest(HttpMethod::Post, {_detail::KeysPath, keyName, CreateValue}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + Models::KeyCreateParameters keyCreateParameters + = static_cast(ecKeyOptions).ToKeyCreateParameters(); + keyCreateParameters.Kty = Models::JsonWebKeyType(ecKeyOptions.GetKeyType().ToString()); + if (ecKeyOptions.CurveName.HasValue()) + { + keyCreateParameters.Curve + = Models::JsonWebKeyCurveName(ecKeyOptions.CurveName.Value().ToString()); + } + auto result = m_client->CreateKey(ecKeyOptions.GetName(), keyCreateParameters, context); + KeyVaultKey keyResult(result.Value); + return Azure::Response(keyResult, std::move(result.RawResponse)); } Azure::Response KeyClient::CreateRsaKey( CreateRsaKeyOptions const& rsaKeyOptions, Azure::Core::Context const& context) const { - // Payload for the request - std::string const& keyName = rsaKeyOptions.GetName(); - auto payload = _detail::KeyRequestParameters(rsaKeyOptions).Serialize(); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request - = CreateRequest(HttpMethod::Post, {_detail::KeysPath, keyName, CreateValue}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + Models::KeyCreateParameters keyCreateParameters + = static_cast(rsaKeyOptions).ToKeyCreateParameters(); + keyCreateParameters.Kty = Models::JsonWebKeyType(rsaKeyOptions.GetKeyType().ToString()); + if (rsaKeyOptions.KeySize.HasValue()) + { + keyCreateParameters.KeySize = static_cast(rsaKeyOptions.KeySize.Value()); + } + if (rsaKeyOptions.PublicExponent.HasValue()) + { + keyCreateParameters.PublicExponent = static_cast(rsaKeyOptions.PublicExponent.Value()); + } + auto result = m_client->CreateKey(rsaKeyOptions.GetName(), keyCreateParameters, context); + KeyVaultKey keyResult(result.Value); + return Azure::Response(keyResult, std::move(result.RawResponse)); } Azure::Response KeyClient::CreateOctKey( CreateOctKeyOptions const& octKeyOptions, Azure::Core::Context const& context) const { - // Payload for the request. - std::string const& keyName = octKeyOptions.GetName(); - auto payload = _detail::KeyRequestParameters(octKeyOptions).Serialize(); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request - = CreateRequest(HttpMethod::Post, {_detail::KeysPath, keyName, CreateValue}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + Models::KeyCreateParameters keyCreateParameters + = static_cast(octKeyOptions).ToKeyCreateParameters(); + keyCreateParameters.Kty = Models::JsonWebKeyType(octKeyOptions.GetKeyType().ToString()); + if (octKeyOptions.KeySize.HasValue()) + { + keyCreateParameters.KeySize = static_cast(octKeyOptions.KeySize.Value()); + } + auto result = m_client->CreateKey(octKeyOptions.GetName(), keyCreateParameters, context); + KeyVaultKey keyResult(result.Value); + return Azure::Response(keyResult, std::move(result.RawResponse)); } KeyPropertiesPagedResponse KeyClient::GetPropertiesOfKeys( GetPropertiesOfKeysOptions const& options, Azure::Core::Context const& context) const { - // Request and settings - auto request = ContinuationTokenRequest({_detail::KeysPath}, options.NextPageToken); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyPropertiesPagedResultSerializer::KeyPropertiesPagedResultDeserialize( - *rawResponse); + _detail::KeyVaultClientGetKeysOptions getOptions; + if (options.NextPageToken.HasValue()) + { + getOptions.NextPageToken = options.NextPageToken.Value(); + } + auto result = m_client->GetKeys(getOptions, context); return KeyPropertiesPagedResponse( - std::move(value), std::move(rawResponse), std::make_unique(*this)); + std::move(result), std::move(result.RawResponse), std::make_unique(*this)); } KeyPropertiesPagedResponse KeyClient::GetPropertiesOfKeyVersions( @@ -210,29 +160,24 @@ KeyPropertiesPagedResponse KeyClient::GetPropertiesOfKeyVersions( GetPropertiesOfKeyVersionsOptions const& options, Azure::Core::Context const& context) const { - // Request and settings - auto request - = ContinuationTokenRequest({_detail::KeysPath, name, "versions"}, options.NextPageToken); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyPropertiesPagedResultSerializer::KeyPropertiesPagedResultDeserialize( - *rawResponse); + _detail::KeyVaultClientGetKeyVersionsOptions getOptions; + if (options.NextPageToken.HasValue()) + { + getOptions.NextPageToken = options.NextPageToken.Value(); + } + auto result = m_client->GetKeyVersions(name, getOptions, context); return KeyPropertiesPagedResponse( - std::move(value), std::move(rawResponse), std::make_unique(*this)); + std::move(result), std::move(result.RawResponse), std::make_unique(*this)); } Azure::Security::KeyVault::Keys::DeleteKeyOperation KeyClient::StartDeleteKey( std::string const& name, Azure::Core::Context const& context) const { + auto response = m_client->DeleteKey(name, context); // Request with no payload - auto request = CreateRequest(HttpMethod::Delete, {_detail::KeysPath, name}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::DeletedKeySerializer::DeletedKeyDeserialize(name, *rawResponse); - auto responseT = Azure::Response(std::move(value), std::move(rawResponse)); + DeletedKey value(response.Value); + auto responseT = Azure::Response(std::move(value), std::move(response.RawResponse)); return Azure::Security::KeyVault::Keys::DeleteKeyOperation( std::make_shared(*this), std::move(responseT)); } @@ -242,34 +187,19 @@ Azure::Response KeyClient::ReleaseKey( KeyReleaseOptions const& options, Azure::Core::Context const& context) const { - auto payload = _detail::KeyReleaseOptionsSerializer::KeyReleaseOptionsSerialize(options); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request = CreateRequest( - HttpMethod::Post, - {_detail::KeysPath, name, options.Version.ValueOr(""), _detail::ReleaseValue}, - &payloadStream); - - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyReleaseOptionsSerializer::KeyReleaseOptionsDeserialize(*rawResponse); - return Azure::Response(value, std::move(rawResponse)); + _detail::Models::KeyReleaseParameters keyReleaseParameters = options.ToKeyReleaseParameters(); + auto result = m_client->Release(name, options.Version.ValueOr(""), keyReleaseParameters, context); + ReleaseKeyResult value{result.Value.Value.ValueOr("")}; + return Azure::Response(value, std::move(result.RawResponse)); } Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation KeyClient::StartRecoverDeletedKey( std::string const& name, Azure::Core::Context const& context) const { - // Request with no payload - auto request = CreateRequest(HttpMethod::Post, {_detail::DeletedKeysPath, name, "recover"}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, *rawResponse); - auto responseT = Azure::Response(std::move(value), std::move(rawResponse)); + auto result = m_client->RecoverDeletedKey(name, context); + KeyVaultKey value(result.Value); + auto responseT = Azure::Response(std::move(value), std::move(result.RawResponse)); return Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation( std::make_shared(*this), std::move(responseT)); } @@ -278,41 +208,32 @@ Azure::Response KeyClient::GetDeletedKey( std::string const& name, Azure::Core::Context const& context) const { - // Request with no payload - auto request = CreateRequest(HttpMethod::Get, {_detail::DeletedKeysPath, name}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::DeletedKeySerializer::DeletedKeyDeserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->GetDeletedKey(name, context); + DeletedKey value(response.Value); + return Azure::Response(std::move(value), std::move(response.RawResponse)); } DeletedKeyPagedResponse KeyClient::GetDeletedKeys( GetDeletedKeysOptions const& options, Azure::Core::Context const& context) const { - // Request and settings - auto request = ContinuationTokenRequest({_detail::DeletedKeysPath}, options.NextPageToken); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value - = _detail::KeyPropertiesPagedResultSerializer::DeletedKeyPagedResultDeserialize(*rawResponse); + _detail::KeyVaultClientGetDeletedKeysOptions getOptions; + if (options.NextPageToken.HasValue()) + { + getOptions.NextPageToken = options.NextPageToken.Value(); + } + auto result = m_client->GetDeletedKeys(getOptions, context); return DeletedKeyPagedResponse( - std::move(value), std::move(rawResponse), std::make_unique(*this)); + std::move(result), std::move(result.RawResponse), std::make_unique(*this)); } Azure::Response KeyClient::PurgeDeletedKey( std::string const& name, Azure::Core::Context const& context) const { - // Request with no payload - auto request = CreateRequest(HttpMethod::Delete, {_detail::DeletedKeysPath, name}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); + auto result = m_client->PurgeDeletedKey(name, context); auto value = PurgedKey(); - return Azure::Response(std::move(value), std::move(rawResponse)); + return Azure::Response(std::move(value), std::move(result.RawResponse)); } Azure::Response KeyClient::UpdateKeyProperties( @@ -320,58 +241,35 @@ Azure::Response KeyClient::UpdateKeyProperties( Azure::Nullable> const& keyOperations, Azure::Core::Context const& context) const { - // Payload for the request - _detail::KeyRequestParameters const params(properties, keyOperations); - auto payload = params.Serialize(); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); + auto result = m_client->UpdateKey( + properties.Name, + properties.Version, + properties.ToKeyUpdateParameters(keyOperations), + context); - // Request and settings - auto request = CreateRequest( - HttpMethod::Patch, {_detail::KeysPath, properties.Name, properties.Version}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); + KeyVaultKey value(result.Value); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value - = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(properties.Name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + return Azure::Response(std::move(value), std::move(result.RawResponse)); } Azure::Response KeyClient::BackupKey( std::string const& name, Azure::Core::Context const& context) const { - // Request with no payload - auto request = CreateRequest(HttpMethod::Post, {_detail::KeysPath, name, "backup"}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - // the internal backupKey model provides the Deserialize implementation - auto internalValue = _detail::KeyBackup::Deserialize(*rawResponse); - auto value = BackupKeyResult{internalValue.Value}; - return Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->BackupKey(name, context); + auto internalValue = response.Value.Value.Value(); + auto value = BackupKeyResult{internalValue}; + return Azure::Response(std::move(value), std::move(response.RawResponse)); } Azure::Response KeyClient::RestoreKeyBackup( std::vector const& backup, Azure::Core::Context const& context) const { - // Payload for the request - _detail::KeyBackup backupModel; - backupModel.Value = backup; - auto payload = backupModel.Serialize(); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request = CreateRequest(HttpMethod::Post, {_detail::KeysPath, "restore"}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(*rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + _detail::Models::KeyRestoreParameters restoreParameters{backup}; + auto response = m_client->RestoreKey(restoreParameters, context); + KeyVaultKey value(response.Value); + return Azure::Response(std::move(value), std::move(response.RawResponse)); } Azure::Response KeyClient::ImportKey( @@ -387,49 +285,29 @@ Azure::Response KeyClient::ImportKey( ImportKeyOptions const& importKeyOptions, Azure::Core::Context const& context) const { - // Payload for the request - auto payload = _detail::ImportKeyOptionsSerializer::ImportKeyOptionsSerialize(importKeyOptions); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request = CreateRequest( - HttpMethod::Put, {_detail::KeysPath, importKeyOptions.Name()}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize( - importKeyOptions.Name(), *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + _detail::Models::KeyImportParameters keyImportParameters + = importKeyOptions.ToKeyImportParameters(); + auto result = m_client->ImportKey(importKeyOptions.Name(), keyImportParameters, context); + KeyVaultKey value(result.Value); + return Azure::Response(std::move(value), std::move(result.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 response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto result = m_client->RotateKey(name, context); + KeyVaultKey value(result.Value); + return Azure::Response(std::move(value), std::move(result.RawResponse)); } Azure::Response KeyClient::GetKeyRotationPolicy( std::string const& name, Azure::Core::Context const& context) const { - // Request with no payload - auto request - = CreateRequest(HttpMethod::Get, {_detail::KeysPath, name, _detail::RotationPolicyPath}); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyRotationPolicySerializer::KeyRotationPolicyDeserialize(*rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto result = m_client->GetKeyRotationPolicy(name, context); + KeyRotationPolicy value(result.Value); + return Azure::Response(std::move(value), std::move(result.RawResponse)); } Azure::Response KeyClient::UpdateKeyRotationPolicy( @@ -437,39 +315,21 @@ Azure::Response KeyClient::UpdateKeyRotationPolicy( KeyRotationPolicy const& rotationPolicy, Azure::Core::Context const& context) const { - // Payload for the request - auto payload = _detail::KeyRotationPolicySerializer::KeyRotationPolicySerialize(rotationPolicy); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request = CreateRequest( - HttpMethod::Put, {_detail::KeysPath, name, _detail::RotationPolicyPath}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::KeyRotationPolicySerializer::KeyRotationPolicyDeserialize(*rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + _detail::Models::KeyRotationPolicy keyRotationPolicy = rotationPolicy.ToKeyRotationPolicy(); + auto result = m_client->UpdateKeyRotationPolicy(name, keyRotationPolicy, context); + KeyRotationPolicy value(result.Value); + return Azure::Response(std::move(value), std::move(result.RawResponse)); } Azure::Response KeyClient::GetRandomBytes( GetRandomBytesOptions const& options, Azure::Core::Context const& context) const { - auto payload = _detail::GetRandomBytesSerializer::GetRandomBytesOptionsSerialize(options); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - // Request and settings - auto request = CreateRequest(HttpMethod::Post, {"rng"}, &payloadStream); - request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto response = GetRandomBytesResult{ - _detail::GetRandomBytesSerializer::GetRandomBytesResponseDeserialize(*rawResponse)}; - return Azure::Response(std::move(response), std::move(rawResponse)); + _detail::Models::GetRandomBytesRequest getRandomBytesRequest; + getRandomBytesRequest.Count = options.Count; + auto result = m_client->GetRandomBytes(getRandomBytesRequest, context); + auto value = GetRandomBytesResult{result.Value.Value}; + return Azure::Response(std::move(value), std::move(result.RawResponse)); } Cryptography::CryptographyClient KeyClient::GetCryptographyClient( diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/key_client_models.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/key_client_models.cpp new file mode 100644 index 000000000..25fce23da --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/key_client_models.cpp @@ -0,0 +1,573 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "./generated/keys_models.hpp" +#include "./private/key_serializers.hpp" + +#include + +using namespace Azure::Security::KeyVault::Keys; +using namespace Azure::Security::KeyVault::Keys::_detail; + +KeyVaultKey::KeyVaultKey(_detail::Models::KeyBundle const& response) +{ + if (response.Key.HasValue()) + { + if (response.Key.Value().Crv.HasValue()) + { + Key.CurveName = KeyCurveName(response.Key.Value().Crv.Value().ToString()); + } + if (response.Key.Value().Kty.HasValue()) + { + Key.KeyType = KeyVaultKeyType(response.Key.Value().Kty.Value().ToString()); + } + if (response.Key.Value().D.HasValue()) + { + Key.D = response.Key.Value().D.Value(); + } + if (response.Key.Value().Dp.HasValue()) + { + Key.DP = response.Key.Value().Dp.Value(); + } + if (response.Key.Value().Dq.HasValue()) + { + Key.DQ = response.Key.Value().Dq.Value(); + } + if (response.Key.Value().E.HasValue()) + { + Key.E = response.Key.Value().E.Value(); + } + if (response.Key.Value().N.HasValue()) + { + Key.N = response.Key.Value().N.Value(); + } + if (response.Key.Value().P.HasValue()) + { + Key.P = response.Key.Value().P.Value(); + } + if (response.Key.Value().Q.HasValue()) + { + Key.Q = response.Key.Value().Q.Value(); + } + if (response.Key.Value().Qi.HasValue()) + { + Key.QI = response.Key.Value().Qi.Value(); + } + if (response.Key.Value().T.HasValue()) + { + Key.T = response.Key.Value().T.Value(); + } + if (response.Key.Value().K.HasValue()) + { + Key.K = response.Key.Value().K.Value(); + } + if (response.Key.Value().KeyOps.HasValue()) + { + std::vector keyOperations; + for (auto keyOp : response.Key.Value().KeyOps.Value()) + { + keyOperations.emplace_back(KeyOperation(keyOp)); + } + Key.SetKeyOperations(keyOperations); + } + if (response.Key.Value().Kid.HasValue()) + { + Key.Id = response.Key.Value().Kid.Value(); + Properties.Id = Key.Id; + KeyVaultKeySerializer::ParseKeyUrl(Properties, Key.Id); + } + if (response.Key.Value().X.HasValue()) + { + Key.X = response.Key.Value().X.Value(); + } + if (response.Key.Value().K.HasValue()) + { + Key.Y = response.Key.Value().Y.Value(); + } + } + + if (response.Attributes.HasValue()) + { + Properties.ExpiresOn = response.Attributes.Value().Expires; + Properties.CreatedOn = response.Attributes.Value().Created; + Properties.Enabled = response.Attributes.Value().Enabled; + Properties.NotBefore = response.Attributes.Value().NotBefore; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Properties.Exportable = response.Attributes.Value().Exportable; + Properties.HsmPlatform = response.Attributes.Value().HsmPlatform; + Properties.RecoverableDays = response.Attributes.Value().RecoverableDays; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Properties.UpdatedOn = response.Attributes.Value().Updated; + Properties.HsmPlatform = response.Attributes.Value().HsmPlatform; + if (response.Attributes.Value().Attestation.HasValue()) + { + Azure::Security::KeyVault::Keys::KeyAttestation attestation; + attestation.CertificatePemFile + = response.Attributes.Value().Attestation.Value().CertificatePemFile; + attestation.PrivateKeyAttestation + = response.Attributes.Value().Attestation.Value().PrivateKeyAttestation; + attestation.PublicKeyAttestation + = response.Attributes.Value().Attestation.Value().PublicKeyAttestation; + attestation.Version = response.Attributes.Value().Attestation.Value().Version; + Properties.Attestation = attestation; + } + } + + if (response.Managed.HasValue()) + { + Properties.Managed = (response.Managed.ValueOr(false) == true); + } + + if (response.Tags.HasValue()) + { + for (auto const& tag : response.Tags.Value()) + { + Properties.Tags.emplace(tag.first, tag.second); + } + } + + if (response.ReleasePolicy.HasValue()) + { + KeyReleasePolicy policy; + if (response.ReleasePolicy.Value().ContentType.HasValue()) + { + policy.ContentType = response.ReleasePolicy.Value().ContentType.Value(); + } + if (response.ReleasePolicy.Value().Immutable.HasValue()) + { + policy.Immutable = response.ReleasePolicy.Value().Immutable.Value(); + } + if (response.ReleasePolicy.Value().EncodedPolicy.HasValue()) + { + auto encodedPolicy = response.ReleasePolicy.Value().EncodedPolicy.Value(); + policy.EncodedPolicy = std::string{encodedPolicy.begin(), encodedPolicy.end()}; + } + Properties.ReleasePolicy = policy; + } +} + +DeletedKey::DeletedKey(_detail::Models::DeletedKeyBundle const& response) +{ + if (response.Key.HasValue()) + { + if (response.Key.Value().Crv.HasValue()) + { + Key.CurveName = KeyCurveName(response.Key.Value().Crv.Value().ToString()); + } + if (response.Key.Value().Kty.HasValue()) + { + Key.KeyType = KeyVaultKeyType(response.Key.Value().Kty.Value().ToString()); + } + if (response.Key.Value().D.HasValue()) + { + Key.D = response.Key.Value().D.Value(); + } + if (response.Key.Value().Dp.HasValue()) + { + Key.DP = response.Key.Value().Dp.Value(); + } + if (response.Key.Value().Dq.HasValue()) + { + Key.DQ = response.Key.Value().Dq.Value(); + } + if (response.Key.Value().E.HasValue()) + { + Key.E = response.Key.Value().E.Value(); + } + if (response.Key.Value().N.HasValue()) + { + Key.N = response.Key.Value().N.Value(); + } + if (response.Key.Value().P.HasValue()) + { + Key.P = response.Key.Value().P.Value(); + } + if (response.Key.Value().Q.HasValue()) + { + Key.Q = response.Key.Value().Q.Value(); + } + if (response.Key.Value().Qi.HasValue()) + { + Key.QI = response.Key.Value().Qi.Value(); + } + if (response.Key.Value().T.HasValue()) + { + Key.T = response.Key.Value().T.Value(); + } + if (response.Key.Value().K.HasValue()) + { + Key.K = response.Key.Value().K.Value(); + } + if (response.Key.Value().KeyOps.HasValue()) + { + std::vector keyOperations; + for (auto keyOp : response.Key.Value().KeyOps.Value()) + { + keyOperations.emplace_back(KeyOperation(keyOp)); + } + Key.SetKeyOperations(keyOperations); + } + if (response.Key.Value().Kid.HasValue()) + { + Key.Id = response.Key.Value().Kid.Value(); + Properties.Id = Key.Id; + KeyVaultKeySerializer::ParseKeyUrl(Properties, Key.Id); + } + if (response.Key.Value().X.HasValue()) + { + Key.X = response.Key.Value().X.Value(); + } + if (response.Key.Value().K.HasValue()) + { + Key.Y = response.Key.Value().Y.Value(); + } + } + + if (response.Attributes.HasValue()) + { + Properties.ExpiresOn = response.Attributes.Value().Expires; + Properties.CreatedOn = response.Attributes.Value().Created; + Properties.Enabled = response.Attributes.Value().Enabled; + Properties.NotBefore = response.Attributes.Value().NotBefore; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Properties.Exportable = response.Attributes.Value().Exportable; + Properties.HsmPlatform = response.Attributes.Value().HsmPlatform; + Properties.RecoverableDays = response.Attributes.Value().RecoverableDays; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Properties.UpdatedOn = response.Attributes.Value().Updated; + if (response.Attributes.Value().Attestation.HasValue()) + { + Azure::Security::KeyVault::Keys::KeyAttestation attestation; + attestation.CertificatePemFile + = response.Attributes.Value().Attestation.Value().CertificatePemFile; + attestation.PrivateKeyAttestation + = response.Attributes.Value().Attestation.Value().PrivateKeyAttestation; + attestation.PublicKeyAttestation + = response.Attributes.Value().Attestation.Value().PublicKeyAttestation; + attestation.Version = response.Attributes.Value().Attestation.Value().Version; + Properties.Attestation = attestation; + } + } + + if (response.Managed.HasValue()) + { + Properties.Managed = (response.Managed.ValueOr(false) == true); + } + + if (response.Tags.HasValue()) + { + for (auto const& tag : response.Tags.Value()) + { + Properties.Tags.emplace(tag.first, tag.second); + } + } + + if (response.ReleasePolicy.HasValue()) + { + KeyReleasePolicy policy; + if (response.ReleasePolicy.Value().ContentType.HasValue()) + { + policy.ContentType = response.ReleasePolicy.Value().ContentType.Value(); + } + if (response.ReleasePolicy.Value().Immutable.HasValue()) + { + policy.Immutable = response.ReleasePolicy.Value().Immutable.Value(); + } + if (response.ReleasePolicy.Value().EncodedPolicy.HasValue()) + { + auto encodedPolicy = response.ReleasePolicy.Value().EncodedPolicy.Value(); + policy.EncodedPolicy = std::string{encodedPolicy.begin(), encodedPolicy.end()}; + } + Properties.ReleasePolicy = policy; + } + if (response.RecoveryId.HasValue()) + { + RecoveryId = response.RecoveryId.Value(); + } + if (response.DeletedDate.HasValue()) + { + DeletedDate = response.DeletedDate.Value(); + } + if (response.ScheduledPurgeDate.HasValue()) + { + ScheduledPurgeDate = response.ScheduledPurgeDate.Value(); + } +} + +_detail::Models::KeyUpdateParameters KeyProperties::ToKeyUpdateParameters( + Azure::Nullable> const& keyOperations) const +{ + _detail::Models::KeyUpdateParameters kUP; + if (Tags.size() > 0) + { + std::map tags; + for (auto const& tag : Tags) + { + tags.insert({tag.first, tag.second}); + } + kUP.Tags = tags; + } + if (ReleasePolicy.HasValue()) + { + _detail::Models::KeyReleasePolicy releasePolicy; + if (ReleasePolicy.Value().ContentType.HasValue()) + { + releasePolicy.ContentType = ReleasePolicy.Value().ContentType.Value(); + } + if (ReleasePolicy.Value().EncodedPolicy.size() > 0) + { + releasePolicy.EncodedPolicy = std::vector( + ReleasePolicy.Value().EncodedPolicy.begin(), ReleasePolicy.Value().EncodedPolicy.end()); + } + releasePolicy.Immutable = ReleasePolicy.Value().Immutable; + kUP.ReleasePolicy = releasePolicy; + } + if (keyOperations.HasValue()) + { + kUP.KeyOps = std::vector<_detail::Models::JsonWebKeyOperation>(); + for (auto const& operation : keyOperations.Value()) + { + kUP.KeyOps.Value().push_back(_detail::Models::JsonWebKeyOperation(operation.ToString())); + } + } + + kUP.KeyAttributes = _detail::Models::KeyAttributes(); + if (Attestation.HasValue()) + { + kUP.KeyAttributes.Value().Attestation = _detail::Models::KeyAttestation(); + kUP.KeyAttributes.Value().Attestation.Value().CertificatePemFile + = Attestation.Value().CertificatePemFile; + kUP.KeyAttributes.Value().Attestation.Value().PrivateKeyAttestation + = Attestation.Value().PrivateKeyAttestation; + kUP.KeyAttributes.Value().Attestation.Value().PublicKeyAttestation + = Attestation.Value().PublicKeyAttestation; + kUP.KeyAttributes.Value().Attestation.Value().Version = Attestation.Value().Version; + } + kUP.KeyAttributes.Value().Created = CreatedOn; + kUP.KeyAttributes.Value().Enabled = Enabled; + kUP.KeyAttributes.Value().Expires = ExpiresOn; + kUP.KeyAttributes.Value().Exportable = Exportable; + kUP.KeyAttributes.Value().HsmPlatform = HsmPlatform; + kUP.KeyAttributes.Value().NotBefore = NotBefore; + kUP.KeyAttributes.Value().RecoverableDays = RecoverableDays; + if (RecoveryLevel.size() > 0) + { + kUP.KeyAttributes.Value().RecoveryLevel = _detail::Models::DeletionRecoveryLevel(RecoveryLevel); + } + kUP.KeyAttributes.Value().Updated = UpdatedOn; + return kUP; +} + +KeyRotationPolicy::KeyRotationPolicy(_detail::Models::KeyRotationPolicy const& krp) +{ + if (krp.Id.HasValue()) + { + Id = krp.Id.Value(); + } + + if (krp.LifetimeActions.HasValue()) + { + for (auto const& action : krp.LifetimeActions.Value()) + { + LifetimeActionsType la; + if (action.Action.Value().Type.Value() == _detail::Models::KeyRotationPolicyAction::Rotate) + { + la.Action = LifetimeActionType::Rotate; + } + else if ( + action.Action.Value().Type.Value() == _detail::Models::KeyRotationPolicyAction::Notify) + { + la.Action = LifetimeActionType::Notify; + } + if (action.Trigger.HasValue()) + { + la.Trigger.TimeAfterCreate = action.Trigger.Value().TimeAfterCreate; + la.Trigger.TimeBeforeExpiry = action.Trigger.Value().TimeBeforeExpiry; + } + LifetimeActions.emplace_back(la); + } + } + if (krp.Attributes.HasValue()) + { + Attributes.ExpiryTime = krp.Attributes.Value().ExpiryTime; + Attributes.Created = krp.Attributes.Value().Created; + Attributes.Updated = krp.Attributes.Value().Updated; + } +} + +_detail::Models::KeyRotationPolicy KeyRotationPolicy::ToKeyRotationPolicy() const +{ + _detail::Models::KeyRotationPolicy krp; + if (Id.size() > 0) + { + krp.Id = Id; + } + if (LifetimeActions.size() > 0) + { + krp.LifetimeActions = std::vector<_detail::Models::LifetimeActions>(); + for (auto const& action : LifetimeActions) + { + _detail::Models::LifetimeActions la; + _detail::Models::LifetimeActionsType laType; + if (action.Action == LifetimeActionType::Rotate) + { + laType.Type = _detail::Models::KeyRotationPolicyAction::Rotate; + } + else if (action.Action == LifetimeActionType::Notify) + { + laType.Type = _detail::Models::KeyRotationPolicyAction::Notify; + } + la.Action = laType; + la.Trigger = _detail::Models::LifetimeActionsTrigger(); + if (action.Trigger.TimeAfterCreate.HasValue()) + { + la.Trigger.Value().TimeAfterCreate = action.Trigger.TimeAfterCreate.Value(); + } + if (action.Trigger.TimeBeforeExpiry.HasValue()) + { + la.Trigger.Value().TimeBeforeExpiry = action.Trigger.TimeBeforeExpiry.Value(); + } + krp.LifetimeActions.Value().emplace_back(la); + } + } + + krp.Attributes = _detail::Models::KeyRotationPolicyAttributes(); + krp.Attributes.Value().Created = Attributes.Created; + krp.Attributes.Value().Updated = Attributes.Updated; + krp.Attributes.Value().ExpiryTime = Attributes.ExpiryTime; + return krp; +} + +KeyProperties::KeyProperties(_detail::Models::KeyItem const& response) +{ + if (response.Attributes.HasValue()) + { + ExpiresOn = response.Attributes.Value().Expires; + CreatedOn = response.Attributes.Value().Created; + Enabled = response.Attributes.Value().Enabled; + NotBefore = response.Attributes.Value().NotBefore; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Exportable = response.Attributes.Value().Exportable; + HsmPlatform = response.Attributes.Value().HsmPlatform; + RecoverableDays = response.Attributes.Value().RecoverableDays; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + UpdatedOn = response.Attributes.Value().Updated; + HsmPlatform = response.Attributes.Value().HsmPlatform; + if (response.Attributes.Value().Attestation.HasValue()) + { + Azure::Security::KeyVault::Keys::KeyAttestation attestation; + attestation.CertificatePemFile + = response.Attributes.Value().Attestation.Value().CertificatePemFile; + attestation.PrivateKeyAttestation + = response.Attributes.Value().Attestation.Value().PrivateKeyAttestation; + attestation.PublicKeyAttestation + = response.Attributes.Value().Attestation.Value().PublicKeyAttestation; + attestation.Version = response.Attributes.Value().Attestation.Value().Version; + Attestation = attestation; + } + } + + if (response.Managed.HasValue()) + { + Managed = (response.Managed.ValueOr(false) == true); + } + + if (response.Tags.HasValue()) + { + for (auto const& tag : response.Tags.Value()) + { + Tags.emplace(tag.first, tag.second); + } + } + if (response.Kid.HasValue()) + { + Id = response.Kid.Value(); + KeyVaultKeySerializer::ParseKeyUrl(*this, Id); + } +} + +DeletedKey::DeletedKey(_detail::Models::DeletedKeyItem const& response) +{ + if (response.Attributes.HasValue()) + { + Properties.ExpiresOn = response.Attributes.Value().Expires; + Properties.CreatedOn = response.Attributes.Value().Created; + Properties.Enabled = response.Attributes.Value().Enabled; + Properties.NotBefore = response.Attributes.Value().NotBefore; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Properties.Exportable = response.Attributes.Value().Exportable; + Properties.HsmPlatform = response.Attributes.Value().HsmPlatform; + Properties.RecoverableDays = response.Attributes.Value().RecoverableDays; + if (response.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = response.Attributes.Value().RecoveryLevel.Value().ToString(); + } + Properties.UpdatedOn = response.Attributes.Value().Updated; + if (response.Attributes.Value().Attestation.HasValue()) + { + Azure::Security::KeyVault::Keys::KeyAttestation attestation; + attestation.CertificatePemFile + = response.Attributes.Value().Attestation.Value().CertificatePemFile; + attestation.PrivateKeyAttestation + = response.Attributes.Value().Attestation.Value().PrivateKeyAttestation; + attestation.PublicKeyAttestation + = response.Attributes.Value().Attestation.Value().PublicKeyAttestation; + attestation.Version = response.Attributes.Value().Attestation.Value().Version; + Properties.Attestation = attestation; + } + } + if (response.Managed.HasValue()) + { + Properties.Managed = (response.Managed.ValueOr(false) == true); + } + if (response.Tags.HasValue()) + { + for (auto const& tag : response.Tags.Value()) + { + Properties.Tags.emplace(tag.first, tag.second); + } + } + if (response.RecoveryId.HasValue()) + { + RecoveryId = response.RecoveryId.Value(); + } + if (response.DeletedDate.HasValue()) + { + DeletedDate = response.DeletedDate.Value(); + } + if (response.ScheduledPurgeDate.HasValue()) + { + ScheduledPurgeDate = response.ScheduledPurgeDate.Value(); + } + if (response.DeletedDate.HasValue()) + { + DeletedDate = response.DeletedDate.Value(); + } + if (response.Kid.HasValue()) + { + Key.Id = response.Kid.Value(); + Properties.Id = Key.Id; + KeyVaultKeySerializer::ParseKeyUrl(Properties, Key.Id); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/key_client_options.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/key_client_options.cpp new file mode 100644 index 000000000..2d500b754 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/key_client_options.cpp @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +#include "./generated/keys_models.hpp" + +#include +using namespace Azure::Security::KeyVault::Keys; +using namespace Azure::Security::KeyVault::Keys::_detail; +_detail::Models::KeyCreateParameters CreateKeyOptions::ToKeyCreateParameters() const +{ + Models::KeyCreateParameters keyCreateParameters; + Models::KeyAttributes attributes; + std::vector operations; + for (auto operation : KeyOperations) + { + operations.push_back(Models::JsonWebKeyOperation(operation.ToString())); + } + keyCreateParameters.KeyOps = operations; + std::map tags; + for (auto const& tag : Tags) + { + tags.insert({tag.first, tag.second}); + } + keyCreateParameters.Tags = tags; + attributes.NotBefore = NotBefore; + attributes.Expires = ExpiresOn; + attributes.Enabled = Enabled; + attributes.Exportable = Exportable; + if (ReleasePolicy.HasValue()) + { + Models::KeyReleasePolicy releasePolicy; + if (ReleasePolicy.Value().ContentType.HasValue()) + { + releasePolicy.ContentType = ReleasePolicy.Value().ContentType.Value(); + } + + releasePolicy.EncodedPolicy = std::vector( + ReleasePolicy.Value().EncodedPolicy.begin(), ReleasePolicy.Value().EncodedPolicy.end()); + releasePolicy.Immutable = ReleasePolicy.Value().Immutable; + keyCreateParameters.ReleasePolicy = releasePolicy; + } + keyCreateParameters.KeyAttributes = attributes; + return keyCreateParameters; +} + +_detail::Models::KeyImportParameters ImportKeyOptions::ToKeyImportParameters() const +{ + _detail::Models::KeyImportParameters kIP; + kIP.Hsm = HardwareProtected; + kIP.Key = _detail::Models::JsonWebKey(); + if (Key.CurveName.HasValue()) + { + kIP.Key.Crv = _detail::Models::JsonWebKeyCurveName(Key.CurveName.Value().ToString()); + } + kIP.Key.D = Key.D; + kIP.Key.Dp = Key.DP; + kIP.Key.Dq = Key.DQ; + kIP.Key.E = Key.E; + kIP.Key.K = Key.K; + auto operations = Key.KeyOperations(); + if (operations.size() > 0) + { + kIP.Key.KeyOps = std::vector(); + for (auto op : Key.KeyOperations()) + { + kIP.Key.KeyOps.Value().push_back(op.ToString()); + } + } + kIP.Key.Kid = Key.Id; + kIP.Key.Kty = _detail::Models::JsonWebKeyType(Key.KeyType.ToString()); + kIP.Key.N = Key.N; + kIP.Key.P = Key.P; + kIP.Key.Q = Key.Q; + kIP.Key.Qi = Key.QI; + kIP.Key.T = Key.T; + kIP.Key.X = Key.X; + kIP.Key.Y = Key.Y; + auto attributes = _detail::Models::KeyAttributes(); + + if (Properties.Attestation.HasValue()) + { + attributes.Attestation.Value().CertificatePemFile + = Properties.Attestation.Value().CertificatePemFile; + attributes.Attestation.Value().PrivateKeyAttestation + = Properties.Attestation.Value().PrivateKeyAttestation; + attributes.Attestation.Value().PublicKeyAttestation + = Properties.Attestation.Value().PublicKeyAttestation; + attributes.Attestation.Value().Version = Properties.Attestation.Value().Version; + }; + attributes.Expires = Properties.ExpiresOn; + attributes.Enabled = Properties.Enabled; + attributes.Created = Properties.CreatedOn; + attributes.Exportable = Properties.Exportable; + attributes.HsmPlatform = Properties.HsmPlatform; + attributes.NotBefore = Properties.NotBefore; + attributes.RecoverableDays = Properties.RecoverableDays; + attributes.Updated = Properties.UpdatedOn; + attributes.RecoveryLevel = _detail::Models::DeletionRecoveryLevel(Properties.RecoveryLevel); + kIP.KeyAttributes = attributes; + + return kIP; +} + +_detail::Models::KeyReleaseParameters KeyReleaseOptions::ToKeyReleaseParameters() const +{ + _detail::Models::KeyReleaseParameters krp = _detail::Models::KeyReleaseParameters(); + if (Encryption.HasValue()) + { + if (Encryption.Value() == KeyEncryptionAlgorithm::CkmRsaAesKeyWrap) + { + krp.Enc = _detail::Models::KeyEncryptionAlgorithm::KeyEncryptionAlgorithm::CkmRsaAesKeyWrap; + } + else if (Encryption.Value() == KeyEncryptionAlgorithm::RsaAesKeyWrap256) + { + krp.Enc = _detail::Models::KeyEncryptionAlgorithm::KeyEncryptionAlgorithm:: + RsaAesKeyWrapTwoHundredFiftySix; + } + if (Encryption.Value() == KeyEncryptionAlgorithm::RsaAesKeyWrap384) + { + krp.Enc = _detail::Models::KeyEncryptionAlgorithm::KeyEncryptionAlgorithm:: + RsaAesKeyWrapThreeHundredEightyFour; + } + } + + krp.Nonce = Nonce; + krp.TargetAttestationToken = Target; + return krp; +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/key_client_paged_responses.cpp b/sdk/keyvault/azure-security-keyvault-keys/src/key_client_paged_responses.cpp index 2ce014d88..911013351 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/key_client_paged_responses.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/src/key_client_paged_responses.cpp @@ -3,6 +3,7 @@ #include "azure/keyvault/keys/key_client.hpp" #include "azure/keyvault/keys/key_client_models.hpp" +#include "generated/key_vault_client_paged_responses.hpp" #include "private/key_constants.hpp" #include "private/key_serializers.hpp" @@ -164,3 +165,59 @@ void KeyPropertiesPagedResponse::OnNextPage(const Azure::Core::Context& context) CurrentPageToken = options.NextPageToken.Value(); } } + +KeyPropertiesPagedResponse::KeyPropertiesPagedResponse( + _detail::GetKeysPagedResponse const& pagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr keyClient, + std::string const& keyName) + : m_keyName(keyName), m_keyClient(std::move(keyClient)) +{ + CurrentPageToken = pagedResponse.CurrentPageToken; + NextPageToken = pagedResponse.NextPageToken; + RawResponse = std::move(rawResponse); + if (pagedResponse.Value.HasValue()) + { + for (auto item : pagedResponse.Value.Value()) + { + Items.emplace_back(KeyProperties(item)); + } + } +} + +KeyPropertiesPagedResponse::KeyPropertiesPagedResponse( + _detail::GetKeyVersionsPagedResponse const& pagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr keyClient, + std::string const& keyName) + : m_keyName(keyName), m_keyClient(std::move(keyClient)) +{ + CurrentPageToken = pagedResponse.CurrentPageToken; + NextPageToken = pagedResponse.NextPageToken; + RawResponse = std::move(rawResponse); + if (pagedResponse.Value.HasValue()) + { + for (auto item : pagedResponse.Value.Value()) + { + Items.emplace_back(KeyProperties(item)); + } + } +} + +DeletedKeyPagedResponse::DeletedKeyPagedResponse( + _detail::GetDeletedKeysPagedResponse&& pagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr keyClient) + : m_keyClient(std::move(keyClient)) +{ + CurrentPageToken = pagedResponse.CurrentPageToken; + NextPageToken = pagedResponse.NextPageToken; + RawResponse = std::move(rawResponse); + if (pagedResponse.Value.HasValue()) + { + for (auto item : pagedResponse.Value.Value()) + { + Items.emplace_back(DeletedKey(item)); + } + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/CMakeLists.txt b/sdk/keyvault/azure-security-keyvault-keys/test/ut/CMakeLists.txt index 8efd2e4a4..b8af06645 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/CMakeLists.txt +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/CMakeLists.txt @@ -28,8 +28,6 @@ add_executable ( key_cryptographic_client_test_live.cpp key_rotation_policy_test_live.cpp macro_guard.cpp - mocked_client_test.cpp - mocked_transport_adapter_test.hpp ) target_compile_definitions(azure-security-keyvault-keys-test PRIVATE _azure_BUILDING_TESTS) diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_create_test_live.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_create_test_live.cpp index 8117006a9..40067e92b 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_create_test_live.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_create_test_live.cpp @@ -218,8 +218,7 @@ TEST_F(KeyVaultKeyClient, CreateKeyWithReleasePolicyOptions) })JSON"; auto jsonParser = json::parse(dataStr); auto parsedJson = jsonParser.dump(); - options.ReleasePolicy.Value().EncodedPolicy - = Base64Url::Base64UrlEncode(std::vector(parsedJson.begin(), parsedJson.end())); + options.ReleasePolicy.Value().EncodedPolicy = parsedJson; options.Exportable = true; { auto keyResponse = client.CreateKey( @@ -258,8 +257,7 @@ TEST_F(KeyVaultKeyClient, CreateKeyWithReleasePolicyOptions) EXPECT_FALSE(policy.Immutable); EXPECT_EQ( - json::parse(Base64Url::Base64UrlDecode(options.ReleasePolicy.Value().EncodedPolicy)) - .dump(1, ' ', true), - json::parse(Base64Url::Base64UrlDecode(policy.EncodedPolicy)).dump(1, ' ', true)); + json::parse(options.ReleasePolicy.Value().EncodedPolicy).dump(1, ' ', true), + json::parse(policy.EncodedPolicy).dump(1, ' ', true)); } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_test.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_test.cpp index b5a814025..66009a67c 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_test.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_client_test.cpp @@ -32,10 +32,10 @@ TEST(KeyVaultKeyClientUnitTest, ServiceVersion) { auto credential = std::make_shared("tenantID", "AppId", "SecretId"); - // Default - 7.5 + // Default - 7.6-preview.2 EXPECT_NO_THROW(auto options = KeyClientOptions(); KeyClient keyClient("http://account.vault.azure.net", credential, options); - EXPECT_EQ(options.ApiVersion, "7.5");); + EXPECT_EQ(options.ApiVersion, "7.6-preview.2");); // 7.4 EXPECT_NO_THROW(auto options = KeyClientOptions(); options.ApiVersion = "7.4"; diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_cryptographic_client_test_live.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_cryptographic_client_test_live.cpp index 3484e59ff..27bfaa71f 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_cryptographic_client_test_live.cpp +++ b/sdk/keyvault/azure-security-keyvault-keys/test/ut/key_cryptographic_client_test_live.cpp @@ -356,5 +356,6 @@ static std::string GetSuffix(const testing::TestParamInfo& info) INSTANTIATE_TEST_SUITE_P( Crypto, KeyVaultKeyClientWithParam, - ::testing::Values(-215, -100, 0, 13, 55, 233, 987, 1597, 2048, 3072, 4096), + // supported values are only 2048, 3072, 4096 + ::testing::Values(2048, 3072, 4096), GetSuffix); diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_client_test.cpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_client_test.cpp deleted file mode 100644 index a1cd27cf4..000000000 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_client_test.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "gtest/gtest.h" -#include "mocked_transport_adapter_test.hpp" - -#include -#include - -#include -using namespace Azure::Security::KeyVault::Keys; -using namespace Azure::Security::KeyVault::Keys::Test; - -TEST_F(KeyVaultKeyClientMocked, keyvaultTelemetryId) -{ - std::string applicationId("ourApplicationId"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->GetKey("name"); - - // The response is an echo of the sent headers. Let's find the telemetry ID - auto foundHeader = false; - for (auto& header : response.RawResponse->GetHeaders()) - { - if (Azure::Core::_internal::StringExtensions::LocaleInvariantCaseInsensitiveEqual( - header.first, "User-Agent")) - { - foundHeader = true; - EXPECT_PRED2( - [](std::string const& received, std::string const& sent) { - auto telemetryInfoWithNoOSAndDate = received.substr(0, sent.size()); - return Azure::Core::_internal::StringExtensions::LocaleInvariantCaseInsensitiveEqual( - telemetryInfoWithNoOSAndDate, sent); - }, - header.second, - applicationId); - break; - } - } - EXPECT_TRUE(foundHeader); -} - -TEST_F(KeyVaultKeyClientMocked, keyvaultTelemetryIdVersion) -{ - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "url", m_clientOptions); - - std::string const expectedTelemetryVersionString( - Azure::Security::KeyVault::Keys::_detail::PackageVersion::ToString()); - std::string telemetryStart("azsdk-cpp-keyvault-keys/"); - - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->GetKey("name"); - - // The response is an echo of the sent headers. Let's find the telemetry ID - auto foundHeader = false; - for (auto& header : response.RawResponse->GetHeaders()) - { - if (Azure::Core::_internal::StringExtensions::LocaleInvariantCaseInsensitiveEqual( - header.first, "User-Agent")) - { - foundHeader = true; - EXPECT_PRED2( - [](std::string const& received, std::string const& sent) { - return Azure::Core::_internal::StringExtensions::LocaleInvariantCaseInsensitiveEqual( - received, sent); - }, - header.second.substr(telemetryStart.size(), expectedTelemetryVersionString.size()), - expectedTelemetryVersionString); - break; - } - } - EXPECT_TRUE(foundHeader); -} - -TEST_F(KeyVaultKeyClientMocked, CreateKeyRSA) -{ - std::string applicationId("CreateKeyRSA"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateKey("name", KeyVaultKeyType::Rsa); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::Rsa); -} - -TEST_F(KeyVaultKeyClientMocked, CreateKeyRSA2) -{ - std::string applicationId("CreateKeyRSA"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = CreateRsaKeyOptions("name"); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateRsaKey(options); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::Rsa); -} - -// cspell: disable-next-line -TEST_F(KeyVaultKeyClientMocked, CreateKeyRSAHSM) -{ - // cspell: disable-next-line - std::string applicationId("CreateKeyRSAHSM"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = CreateRsaKeyOptions("name", true); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateRsaKey(options); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::RsaHsm); -} - -TEST_F(KeyVaultKeyClientMocked, CreateKeyEC) -{ - std::string applicationId("CreateKeyEC"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = CreateEcKeyOptions("name"); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateEcKey(options); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::Ec); -} - -// cspell: disable-next-line -TEST_F(KeyVaultKeyClientMocked, CreateKeyECHSM) -{ - // cspell: disable-next-line - std::string applicationId("CreateKeyECHSM"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = CreateEcKeyOptions("name", true); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateEcKey(options); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::EcHsm); -} - -TEST_F(KeyVaultKeyClientMocked, CreateKeyOCT) -{ - std::string applicationId("CreateKeyOCT"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = CreateOctKeyOptions("name"); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateOctKey(options); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::Oct); -} - -// cspell: disable-next-line -TEST_F(KeyVaultKeyClientMocked, CreateKeyOCTHSM) -{ - // cspell: disable-next-line - std::string applicationId("CreateKeyOCTHSM"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = CreateOctKeyOptions("name", true); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->CreateOctKey(options); - - EXPECT_EQ(response.Value.GetKeyType(), KeyVaultKeyType::OctHsm); -} - -TEST_F(KeyVaultKeyClientMocked, GetPropertiesOfKeys) -{ - std::string applicationId("CreateKey"); - m_clientOptions.Telemetry.ApplicationId = applicationId; - m_client = std::make_unique< - Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>( - "http://account.vault.azure.net", m_clientOptions); - - auto options = GetPropertiesOfKeysOptions(); - // The fake response from the mocked transport adapter is good for parsing a Key back - auto response = m_client->GetPropertiesOfKeys(); - EXPECT_NE(response.RawResponse, nullptr); -} diff --git a/sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_transport_adapter_test.hpp b/sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_transport_adapter_test.hpp deleted file mode 100644 index 276904f02..000000000 --- a/sdk/keyvault/azure-security-keyvault-keys/test/ut/mocked_transport_adapter_test.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** - * @file - * @brief The base class to construct and init a Key Vault client. - * - */ - -#include "./../../src/private/key_serializers.hpp" -#include "./../../src/private/keyvault_protocol.hpp" -#include "./../../src/private/package_version.hpp" - -#include -#include -#include - -#include -#include - -#include - -namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace Test { - - namespace _detail { - // Return a simple key as response so keyvault can parse it to create the T response - // Fake key from https://learn.microsoft.com/rest/api/keyvault/GetKey/GetKey#examples - static const char FakeKey[] - = "{ \"key\": { \"kid\": " - "\"https://myvault.vault.azure.net/keys/CreateSoftKeyTest/" - "78deebed173b48e48f55abf87ed4cf71\", \"kty\": \"%s\", \"key_ops\": [ " - "\"encrypt\", \"decrypt\", \"sign\", \"verify\", \"wrapKey\", " - "\"unwrapKey\" ]}, \"attributes\": { \"enabled\": true, " - "\"created\": 1493942451, \"updated\": 1493942451, \"recoveryLevel\": " - "\"Recoverable+Purgeable\" }, \"tags\": { \"purpose\" " - ": " - "\"unit test\", \"test name \" : \"CreateGetDeleteKeyTest\"}}"; - } // namespace _detail - - // A transport adapter which only echo a request headers back as a response. - class MockedTransportAdapter final : public Azure::Core::Http::HttpTransport { - std::unique_ptr Send( - Azure::Core::Http::Request& request, - Azure::Core::Context const& context) override - { - (void)context; - auto response = std::make_unique( - 1, 1, Azure::Core::Http::HttpStatusCode::Ok, "Ok"); - - // Copy headers - for (auto header : request.GetHeaders()) - { - response->SetHeader(header.first, header.second); - } - auto updatedFakeKey = UpdateFakeKey(_detail::FakeKey, request.GetHeaders()["user-agent"]); - std::string bodyCount(updatedFakeKey); - response->SetBodyStream(std::make_unique( - reinterpret_cast(updatedFakeKey), bodyCount.size())); - return response; - } - - const char* UpdateFakeKey(const char fakeKey[], std::string header) - { - char* result; - std::string keyType = "RSA"; - // cspell: disable-next-line - if (header.find("CreateKeyRSAHSM") != std::string::npos) - { - keyType = "RSA-HSM"; - } - // cspell: disable-next-line - else if (header.find("CreateKeyECHSM") != std::string::npos) - { - keyType = "EC-HSM"; - } - // cspell: disable-next-line - else if (header.find("CreateKeyOCTHSM") != std::string::npos) - { - keyType = "oct-HSM"; - } - else if (header.find("CreateKeyRSA") != std::string::npos) - { - keyType = "RSA"; - } - else if (header.find("CreateKeyEC") != std::string::npos) - { - keyType = "EC"; - } - else if (header.find("CreateKeyOCT") != std::string::npos) - { - keyType = "oct"; - } - size_t bufferSize = std::string(fakeKey).size() + keyType.size(); - result = new char[bufferSize]; - - std::snprintf(result, bufferSize, fakeKey, keyType.c_str()); - - return result; - } - }; - - // A derived class with no credential and authentication - class KeyClientWithNoAuthenticationPolicy final - : public Azure::Security::KeyVault::Keys::KeyClient { - public: - explicit KeyClientWithNoAuthenticationPolicy( - std::string const& vaultUrl, - KeyClientOptions const& options = KeyClientOptions()) - : KeyClient(vaultUrl, nullptr, options) - { - std::vector> perCallPolicies; - std::vector> perRetryPolicies; - m_pipeline = std::make_unique( - options, - "keyvault-keys", - Azure::Security::KeyVault::Keys::_detail::PackageVersion::ToString(), - std::move(perRetryPolicies), - std::move(perCallPolicies)); - } - }; - - class KeyVaultKeyClientMocked : public ::testing::Test { - protected: - std::unique_ptr m_client; - Azure::Security::KeyVault::Keys::KeyClientOptions m_clientOptions; - - // Create - virtual void SetUp() override - { - m_clientOptions.Transport.Transport = std::make_shared(); - } - }; -}}}}} // namespace Azure::Security::KeyVault::Keys::Test diff --git a/sdk/keyvault/azure-security-keyvault-keys/tsp-location.yaml b/sdk/keyvault/azure-security-keyvault-keys/tsp-location.yaml new file mode 100644 index 000000000..dad9f0292 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/tsp-location.yaml @@ -0,0 +1,5 @@ +directory: specification/keyvault/Security.KeyVault.Keys +commit: bc18a6a035dbab575177a5548c936621e47d1124 +repo: Azure/azure-rest-api-specs +additionalDirectories: +- specification/keyvault/Security.KeyVault.Common/ diff --git a/sdk/keyvault/azure-security-keyvault-keys/tspconfig.yaml b/sdk/keyvault/azure-security-keyvault-keys/tspconfig.yaml new file mode 100644 index 000000000..c3b534e0f --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/tspconfig.yaml @@ -0,0 +1,23 @@ +parameters: + "service-dir": + default: "sdk/keyvault" + +emit: + - "@azure-tools/typespec-autorest" + +linter: + extends: + - "@azure-tools/typespec-azure-core/all" + +options: + "@azure-tools/typespec-autorest": + azure-resource-provider-folder: "data-plane" + emitter-output-dir: "{project-root}/.." + examples-directory: "{project-root}/examples" + output-file: "{azure-resource-provider-folder}/{service-name}/{version-status}/{version}/openapi.json" + "@azure-tools/typespec-cpp": + flavor: azure + package-dir: "azure-security-keyvault-keys" + namespace: "Azure::Security::KeyVault::Keys::_detail" + headersOutputPath: "azure/keyvault/keys" + noPublicHeaders: true diff --git a/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt b/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt index ad3f3d429..3d5e18b74 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt +++ b/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt @@ -102,7 +102,6 @@ set( src/keyvault_secret_paged_response.cpp src/keyvault_secret_properties.cpp src/secret_client.cpp - src/secret_serializers.cpp ) add_library(azure-security-keyvault-secrets ${AZURE_SECURITY_KEYVAULT_SECRETS_HEADER} ${AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE} "src/keyvault_secret.cpp") diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/secret_client.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/secret_client.hpp index 8967fd39b..ed91763e5 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/secret_client.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/secret_client.hpp @@ -17,7 +17,6 @@ #include "dll_import_export.hpp" #include -#include #include #include @@ -51,7 +50,6 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { // Using a shared pipeline for a client to share it with LRO (like delete key) Azure::Core::Url m_vaultUrl; std::string m_apiVersion; - std::shared_ptr m_pipeline; public: /** diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp deleted file mode 100644 index 8c248ac61..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** - * @file - * @brief Keyvault Secret serializers - */ - -#include "private/secret_serializers.hpp" - -#include "private/secret_constants.hpp" - -#include -#include -#include -#include - -using namespace Azure::Core::_internal; -using namespace Azure::Core::Json::_internal; -using Azure::Core::_internal::PosixTimeConverter; -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Security::KeyVault::Secrets::_detail; diff --git a/sdk/keyvault/ci.yml b/sdk/keyvault/ci.yml index 5c8070fb6..af3dc432a 100644 --- a/sdk/keyvault/ci.yml +++ b/sdk/keyvault/ci.yml @@ -30,8 +30,8 @@ extends: CtestRegex: "azure-security-keyvault.*" LiveTestCtestRegex: "azure-security-keyvault.*" LiveTestTimeoutInMinutes: 120 - LineCoverageTarget: 77 - BranchCoverageTarget: 48 + LineCoverageTarget: 61 + BranchCoverageTarget: 33 Artifacts: - Name: azure-security-keyvault-keys Path: azure-security-keyvault-keys diff --git a/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp b/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp index c0f7ea500..95ca7c63d 100644 --- a/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp +++ b/sdk/tables/azure-data-tables/test/ut/table_client_test.cpp @@ -156,7 +156,6 @@ namespace Azure { namespace Data { namespace Test { EXPECT_EQ(response.Value.Logging.Delete, false); EXPECT_EQ(response.Value.HourMetrics.RetentionPolicyDefinition.IsEnabled, true); EXPECT_EQ(response.Value.HourMetrics.Version, "1.0"); - EXPECT_EQ(response.Value.HourMetrics.IsEnabled, true); EXPECT_EQ(response.Value.HourMetrics.IncludeApis.Value(), true); EXPECT_EQ(response.Value.MinuteMetrics.RetentionPolicyDefinition.IsEnabled, false); EXPECT_EQ(response.Value.MinuteMetrics.Version, "1.0");