diff --git a/cmake-modules/TSPCompile.cmake b/cmake-modules/TSPCompile.cmake index 3669be3aa..e60b9173b 100644 --- a/cmake-modules/TSPCompile.cmake +++ b/cmake-modules/TSPCompile.cmake @@ -3,62 +3,52 @@ find_package(Git) -macro(GenerateCodeFromTypeSpec TSP_SHA TSP_REPO_PATH TSP_DESTINATION CODEGEN_SHA CODEGEN_DESTINATION ) +macro(GenerateCodeFromTypeSpec TSP_DESTINATION TSP_SERVICE_PATH CODEGEN_SHA CODEGEN_DESTINATION GEN_FILES_DESTINATION COPY_CLIENT_TSP) - message("Generating code using the following params TSP_SHA=${TSP_SHA} TSP_REPO_PATH=${TSP_REPO_PATH} TSP_DESTINATION=${TSP_DESTINATION} CODEGEN_SHA=${CODEGEN_SHA} CODEGEN_DESTINATION=${CODEGEN_DESTINATION}") + message("\ + GenerateCodeFromTypeSpec using the following params \n\ + TSP_DESTINATION=${TSP_DESTINATION} \n\ + TSP_SERVICE_PATH=${TSP_SERVICE_PATH} \n\ + CODEGEN_SHA=${CODEGEN_SHA} \n\ + CODEGEN_DESTINATION=${CODEGEN_DESTINATION} \n\ + GEN_FILES_DESTINATION=${GEN_FILES_DESTINATION}") set(CODEGEN_PATH packages/typespec-cpp) - DownloadTSPFiles(${TSP_SHA} ${TSP_REPO_PATH} ${TSP_DESTINATION}) + DownloadTSPFiles(${TSP_DESTINATION}) DownloadCodeGenerator(${CODEGEN_SHA} ${CODEGEN_DESTINATION}) - GenerateCodeFromTSP(${TSP_DESTINATION} ${TSP_REPO_PATH} ${CODEGEN_DESTINATION} ${CODEGEN_PATH}) + GenerateCodeFromTSP(${TSP_DESTINATION} ${TSP_SERVICE_PATH} ${CODEGEN_DESTINATION} ${CODEGEN_PATH} ${GEN_FILES_DESTINATION} ${COPY_CLIENT_TSP}) endmacro() -macro(DownloadTSPFiles TSP_SHA TSP_REPO_PATH TSP_DESTINATION) - message ("Downloading TSP files using the following params TSP_REPO=${TSP_REPO} TSP_SHA=${TSP_SHA} TSP_REPO_PATH=${TSP_REPO_PATH} TSP_DESTINATION=${TSP_DESTINATION}") - - if(Git_FOUND) - message("Git found: ${GIT_EXECUTABLE}") - else() - message(FATAL_ERROR "Git not found") - endif() - +macro(DownloadTSPFiles TSP_DESTINATION) set(TSP_REPO "https://github.com/Azure/azure-rest-api-specs.git") - set(DOWNLOAD_TSP_FOLDER ${CMAKE_SOURCE_DIR}/build/${TSP_DESTINATION}) - # if we have the git folder, we don't need to download it again - # this also saves times on incremental builds - if(NOT EXISTS ${DOWNLOAD_TSP_FOLDER}/.git) - message("First time setting up the ${TSP_DESTINATION} repo.") - #make folder - make_directory(${DOWNLOAD_TSP_FOLDER}) + message ("\ + DownloadTSPFiles using the following params \n\ + TSP_REPO = ${TSP_REPO} \n\ + TSP_DESTINATION=${TSP_DESTINATION}") + + set(DOWNLOAD_TSP_FOLDER ${CMAKE_SOURCE_DIR}/build/${TSP_DESTINATION}) + + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/tsp-location.yaml + DESTINATION ${DOWNLOAD_TSP_FOLDER}) + + set(SCRIPTS_FOLDER ${CMAKE_SOURCE_DIR}/eng/scripts/typespec/) + + file(COPY ${SCRIPTS_FOLDER}/Run-Tsp-Update.ps1 + DESTINATION ${DOWNLOAD_TSP_FOLDER}) + + execute_process(COMMAND pwsh Run-Tsp-Update.ps1 + WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - #init git in folder - execute_process(COMMAND ${GIT_EXECUTABLE} init - WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - #add remote - execute_process(COMMAND ${GIT_EXECUTABLE} remote add origin ${TSP_REPO} - WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - #set sparse-checkout - execute_process(COMMAND ${GIT_EXECUTABLE} sparse-checkout init --cone - WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - #set sparse-checkout folder - execute_process(COMMAND ${GIT_EXECUTABLE} sparse-checkout set ${TSP_REPO_PATH} - WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - else() - message("Repo detected at ${TSP_DESTINATION}. Jumping ahead to checkout.") - endif() - #fetch - execute_process(COMMAND ${GIT_EXECUTABLE} fetch - WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - #switch branch - execute_process(COMMAND ${GIT_EXECUTABLE} checkout ${TSP_SHA} - WORKING_DIRECTORY ${DOWNLOAD_TSP_FOLDER}) - if(NOT ${STATUS_CODE} EQUAL 0) message(FATAL_ERROR "TSP download failed.") endif() endmacro() macro (DownloadCodeGenerator CODEGEN_SHA CODEGEN_DESTINATION) - message("Downloading CODEGEN files using the following params CODEGEN_REPO=${CODEGEN_REPO} CODEGEN_SHA=${CODEGEN_SHA} CODEGEN_DESTINATION=${CODEGEN_DESTINATION}") + message("\ + DownloadCodeGenerator using the following params \n\ + CODEGEN_REPO=${CODEGEN_REPO} \n\ + CODEGEN_SHA=${CODEGEN_SHA} \n\ + CODEGEN_DESTINATION=${CODEGEN_DESTINATION}") if(Git_FOUND) message("Git found: ${GIT_EXECUTABLE}") @@ -90,47 +80,82 @@ macro (DownloadCodeGenerator CODEGEN_SHA CODEGEN_DESTINATION) endif() endmacro() -macro(GenerateCodeFromTSP TSP_DESTINATION TSP_REPO_PATH CODEGEN_DESTINATION CODEGEN_PATH) - message("Generating code using the following params TSP_DESTINATION=${TSP_DESTINATION} TSP_REPO_PATH=${TSP_REPO_PATH} CODEGEN_DESTINATION=${CODEGEN_DESTINATION}") +macro(GenerateCodeFromTSP TSP_DESTINATION TSP_SERVICE_PATH CODEGEN_DESTINATION CODEGEN_PATH GEN_FILES_DESTINATION COPY_CLIENT_TSP ) + message("\ + GenerateCodeFromTSP using the following params \n\ + TSP_DESTINATION=${TSP_DESTINATION}\n\ + TSP_SERVICE_PATH=${TSP_SERVICE_PATH}\n\ + CODEGEN_DESTINATION=${CODEGEN_DESTINATION}\n\ + CODEGEN_PATH=${CODEGEN_PATH}\n\ + GEN_FILES_DESTINATION$=${GEN_FILES_DESTINATION}") message("Remember to Download the typspec-cpp emitter from npmjs.org") #TODO : https://github.com/Azure/azure-sdk-for-cpp/issues/6071 - set(DOWNLOAD_CODEGEN_FOLDER ${CMAKE_SOURCE_DIR}/build/${CODEGEN_DESTINATION}/${CODEGEN_PATH}/specs/) - set(DOWNLOAD_TSP_FOLDER ${CMAKE_SOURCE_DIR}/build/${TSP_DESTINATION}/${TSP_REPO_PATH}) + set(DOWNLOAD_CODEGEN_FOLDER ${CMAKE_SOURCE_DIR}/build/${CODEGEN_DESTINATION}/${CODEGEN_PATH}/specs/${TSP_SERVICE_PATH}) + set(DOWNLOAD_TSP_FOLDER ${CMAKE_SOURCE_DIR}/build/${TSP_DESTINATION}/TempTypeSpecFiles) + set(TSP_FINAL_LOCATION ${DOWNLOAD_CODEGEN_FOLDER}/${TSP_SERVICE_PATH}) set(SCRIPTS_FOLDER ${CMAKE_SOURCE_DIR}/eng/scripts/typespec/) - message("Will copy tsp files from ${DOWNLOAD_TSP_FOLDER} to ${DOWNLOAD_CODEGEN_FOLDER}") + message("\ + Will copy tsp files from \n\ + ${DOWNLOAD_TSP_FOLDER} to \n\ + ${DOWNLOAD_CODEGEN_FOLDER}") #copy tsp files to the codegen folder - file(COPY ${DOWNLOAD_TSP_FOLDER} + file(COPY ${DOWNLOAD_TSP_FOLDER}/ DESTINATION ${DOWNLOAD_CODEGEN_FOLDER}) - message("Will copy tsp generation scripts from ${SCRIPTS_FOLDER} to ${DOWNLOAD_CODEGEN_FOLDER}") + message("\ + Will copy tsp generation scripts from \n\ + ${SCRIPTS_FOLDER} to \n\ + ${TSP_FINAL_LOCATION}") file(COPY ${SCRIPTS_FOLDER} - DESTINATION ${DOWNLOAD_CODEGEN_FOLDER}) - message("Will copy ${CMAKE_CURRENT_SOURCE_DIR}/client.tsp to ${DOWNLOAD_CODEGEN_FOLDER}") - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/client.tsp - DESTINATION ${DOWNLOAD_CODEGEN_FOLDER}) - message("Will copy ${CMAKE_CURRENT_SOURCE_DIR}/tspconfig.yaml to ${DOWNLOAD_CODEGEN_FOLDER}") + DESTINATION ${TSP_FINAL_LOCATION}) + if(${COPY_CLIENT_TSP}) + message("\ + Will copy \n\ + ${CMAKE_CURRENT_SOURCE_DIR}/client.tsp to \n\ + ${TSP_FINAL_LOCATION}") + # file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/client.tsp + # DESTINATION ${TSP_FINAL_LOCATION}) + endif() + message("\ + Will copy \n\ + ${CMAKE_CURRENT_SOURCE_DIR}/tspconfig.yaml to \n\ + ${TSP_FINAL_LOCATION}") file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/tspconfig.yaml - DESTINATION ${DOWNLOAD_CODEGEN_FOLDER}) + DESTINATION ${TSP_FINAL_LOCATION}) #build codegen - message("Building codegen in folder ${DOWNLOAD_CODEGEN_FOLDER}") + message("Building codegen in folder \n\ + ${TSP_FINAL_LOCATION}") execute_process(COMMAND pwsh Build-Codegen.ps1 - WORKING_DIRECTORY ${DOWNLOAD_CODEGEN_FOLDER}) + WORKING_DIRECTORY ${TSP_FINAL_LOCATION}) #generate code - message("Use codegen in folder ${DOWNLOAD_CODEGEN_FOLDER}") - execute_process(COMMAND pwsh Generate-Code.ps1 - WORKING_DIRECTORY ${DOWNLOAD_CODEGEN_FOLDER}) + message("\ + Use codegen in folder \n\ + ${TSP_FINAL_LOCATION}") + execute_process(COMMAND pwsh Generate-Code.ps1 -outputPath ${GEN_FILES_DESTINATION} + WORKING_DIRECTORY ${TSP_FINAL_LOCATION}) endmacro() -macro(UpdateCodeFilesFromGenerated CODEGEN_DESTINATION INCLUDE_DESTINATION SOURCE_DESTINATION) - message("Updating code files using the following params CODEGEN_DESTINATION=${CODEGEN_DESTINATION} INCLUDE_DESTINATION=${INCLUDE_DESTINATION} SOURCE_DESTINATION=${SOURCE_DESTINATION}") - set(CODEGEN_PATH packages/typespec-cpp/specs) +macro(UpdateCodeFilesFromGenerated CODEGEN_DESTINATION TSP_SERVICE_PATH INCLUDE_DESTINATION SOURCE_DESTINATION) + message("\ + Updating code files using the following params \n\ + CODEGEN_DESTINATION=${CODEGEN_DESTINATION} \n\ + TSP_SERVICE_PATH=${TSP_SERVICE_PATH} \n\ + INCLUDE_DESTINATION=${INCLUDE_DESTINATION} \n\ + SOURCE_DESTINATION=${SOURCE_DESTINATION}") + set(CODEGEN_PATH packages/typespec-cpp/specs/${TSP_SERVICE_PATH}/${TSP_SERVICE_PATH}) set(INCLUDE_SRC ${CMAKE_SOURCE_DIR}/build/${CODEGEN_DESTINATION}/${CODEGEN_PATH}/generated/inc/) set(SOURCE_SRC ${CMAKE_SOURCE_DIR}/build/${CODEGEN_DESTINATION}/${CODEGEN_PATH}/generated/src/) - message("Copying files from ${INCLUDE_SRC} to ${INCLUDE_DESTINATION}") + message("\ + Copying files from \n\ + ${INCLUDE_SRC} to \n\ + ${INCLUDE_DESTINATION}") file(COPY ${INCLUDE_SRC} DESTINATION ${INCLUDE_DESTINATION}) - message("Copying files from ${SOURCE_SRC} to ${SOURCE_DESTINATION}") + message("\ + Copying files from \n\ + ${SOURCE_SRC} to \n\ + ${SOURCE_DESTINATION}") file(COPY ${SOURCE_SRC} DESTINATION ${SOURCE_DESTINATION}) message("CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}") endmacro() diff --git a/eng/scripts/typespec/Build-Codegen.ps1 b/eng/scripts/typespec/Build-Codegen.ps1 index b3bbd2caa..8f8e2b9f3 100644 --- a/eng/scripts/typespec/Build-Codegen.ps1 +++ b/eng/scripts/typespec/Build-Codegen.ps1 @@ -11,7 +11,7 @@ param( npm install -g @microsoft/rush typescript autorest @typespec/compiler @azure-tools/typespec-client-generator-cli @azure-tools/typespec-azure-rulesets pushd -cd ..\..\ +cd ..\..\..\..\ cd codegen.cpp if ($Reinstall) { diff --git a/eng/scripts/typespec/Generate-Code.ps1 b/eng/scripts/typespec/Generate-Code.ps1 index 18c7d94d2..efd7e9f5f 100644 --- a/eng/scripts/typespec/Generate-Code.ps1 +++ b/eng/scripts/typespec/Generate-Code.ps1 @@ -4,7 +4,10 @@ [CmdletBinding()] param( [Parameter(Mandatory=$false)] - [string] $ClangFormatPath = "clang-format" + [string] $ClangFormatPath = "clang-format", + + [Parameter(Mandatory=$false)] + [string] $outputPath = ".\generated" ) $ErrorActionPreference = "Stop" @@ -12,13 +15,13 @@ $PSNativeCommandUseErrorActionPreference = $true pushd cd $PSScriptRoot -cd ../ +cd ../../../ $typespecCppDir = Get-Location popd pushd Write-Host "Invoking: tsp compile ." -tsp compile --emit $typespecCppDir client.tsp +tsp compile --emit $typespecCppDir client.tsp --output-dir $outputPath if (-not (Test-Path ".clang-format")) { $oldProgressPreference = $ProgressPreference @@ -36,7 +39,7 @@ try { } Write-Host "Formatting generated code with clang-format" -Get-ChildItem generated -Include *.cpp, *.hpp -Recurse | ForEach-Object -Process{ +Get-ChildItem $outputPath -Include *.cpp, *.hpp -Recurse | ForEach-Object -Process{ " Processing: $_" & "$ClangFormatPath" -i $_ } diff --git a/eng/scripts/typespec/Run-Tsp-Update.ps1 b/eng/scripts/typespec/Run-Tsp-Update.ps1 new file mode 100644 index 000000000..5f1047b40 --- /dev/null +++ b/eng/scripts/typespec/Run-Tsp-Update.ps1 @@ -0,0 +1,3 @@ +npm install -g @microsoft/rush typescript autorest @typespec/compiler @azure-tools/typespec-client-generator-cli @azure-tools/typespec-azure-rulesets + +tsp-client update --save-inputs diff --git a/sdk/keyvault/assets.json b/sdk/keyvault/assets.json index 8391afdb4..204aaabe8 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_ae1c1474ad" + "Tag": "cpp/keyvault_682056eb2b" } diff --git a/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt b/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt index 37b0aa740..d399f9e7e 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt +++ b/sdk/keyvault/azure-security-keyvault-secrets/CMakeLists.txt @@ -32,29 +32,23 @@ include(AzureBuildTargetForCI) # Add create_map_file function include(CreateMapFile) -option(AZURE_TSP_KV_SECRETS_GEN "Generate KeyVault Secrets from TypeSpec" OFF) +option(AZURE_TSP_KV_SECRETS_GEN3 "Generate KeyVault Secrets from TypeSpec" ON) message("KeyVault Secrets TSP Generation ${AZURE_TSP_KV_SECRETS_GEN}") if(AZURE_TSP_KV_SECRETS_GEN) include(TSPCompile) #typespec related repo information - set(TSP_REPO_PATH "specification/keyvault/data-plane/Security.KeyVault.Secrets/") - set(TSP_SHA "1da5a85c4dc4f4f1caa47fff691e85960ef4bf20") + set(TSP_SERVICE_PATH "Security.KeyVault.Secrets") set(TSP_DESTINATION "keyvault_secrets") #codegen related repo information - set(CODEGEN_SHA "1a9e3b7a337d5553603b8326dd3be5024d53b28a") + set(CODEGEN_SHA "deff0a603a9001da24b8751709075a4a3d40d39a") set(CODEGEN_DESTINATION "typespec-cpp") #destination folders - set(INCLUDE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/inc/azure/keyvault/secrets") - set(SOURCE_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/src") - + set(GEN_FILES_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}") #generate code from typespec - GenerateCodeFromTypeSpec(${TSP_SHA} ${TSP_REPO_PATH} ${TSP_DESTINATION} ${CODEGEN_SHA} ${CODEGEN_DESTINATION}) - #update code files left this as a separate step as generating and moving result around - #conceptually are two different steps - UpdateCodeFilesFromGenerated(${CODEGEN_DESTINATION} ${INCLUDE_DESTINATION} ${SOURCE_DESTINATION}) + GenerateCodeFromTypeSpec(${TSP_DESTINATION} ${TSP_SERVICE_PATH} ${CODEGEN_SHA} ${CODEGEN_DESTINATION} ${GEN_FILES_DESTINATION} OFF) endif() if(FETCH_SOURCE_DEPS) @@ -83,17 +77,30 @@ set( inc/azure/keyvault/secrets/keyvault_secret_properties.hpp inc/azure/keyvault/secrets/rtti.hpp inc/azure/keyvault/secrets/secret_client.hpp + inc/azure/keyvault/secrets/generated.hpp + inc/azure/keyvault/secrets/generated/dll_import_export.hpp + inc/azure/keyvault/secrets/generated/key_vault_client.hpp + inc/azure/keyvault/secrets/generated/key_vault_client_options.hpp + inc/azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp + inc/azure/keyvault/secrets/generated/models/generated_models.hpp ) set( AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE + src/private/generated_package_version.hpp + src/private/package_version.hpp + src/generated.cpp + src/get_deleted_secrets_paged_response.cpp + src/get_secrets_paged_response.cpp + src/get_secret_versions_paged_response.cpp + src/keyvault_deleted_secret.cpp + src/key_vault_client.cpp src/keyvault_operations.cpp src/keyvault_protocol.cpp + src/keyvault_secret.cpp src/keyvault_secret_paged_response.cpp src/keyvault_secret_properties.cpp - src/keyvault_secrets_common_request.cpp src/private/keyvault_protocol.hpp - src/private/keyvault_secrets_common_request.hpp src/private/package_version.hpp src/private/secret_constants.hpp src/private/secret_serializers.hpp @@ -101,7 +108,7 @@ set( src/secret_serializers.cpp ) -add_library(azure-security-keyvault-secrets ${AZURE_SECURITY_KEYVAULT_SECRETS_HEADER} ${AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE}) +add_library(azure-security-keyvault-secrets ${AZURE_SECURITY_KEYVAULT_SECRETS_HEADER} ${AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE} "src/keyvault_secret.cpp") add_library(Azure::azure-security-keyvault-secrets ALIAS azure-security-keyvault-secrets) create_per_service_target_build(keyvault azure-security-keyvault-secrets) @@ -152,13 +159,13 @@ endif() az_vcpkg_export( azure-security-keyvault-secrets SECURITY_KEYVAULT_SECRETS - "azure/keyvault/secrets/dll_import_export.hpp" + azure/keyvault/secrets/dll_import_export.hpp ) az_rtti_setup( azure-security-keyvault-secrets SECURITY_KEYVAULT_SECRETS - "azure/keyvault/secrets/rtti.hpp" + azure/keyvault/secrets/rtti.hpp ) unset(FETCH_SOURCE_DEPS CACHE) diff --git a/sdk/keyvault/azure-security-keyvault-secrets/README.md b/sdk/keyvault/azure-security-keyvault-secrets/README.md index ada7c2222..6206e9615 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/README.md +++ b/sdk/keyvault/azure-security-keyvault-secrets/README.md @@ -80,7 +80,6 @@ For detailed samples please review the samples provided. First step is to create a SecretClient. - ```cpp auto const keyVaultUrl = std::getenv("AZURE_KEYVAULT_URL"); auto credential = std::make_shared(); @@ -93,7 +92,6 @@ SecretClient secretClient(keyVaultUrl, credential); We call the secret client to create a secret. - ```cpp std::string secretName("MySampleSecret"); std::string secretValue("my secret value"); @@ -105,7 +103,6 @@ secretClient.SetSecret(secretName, secretValue); We retrieve a secret by name. - ```cpp // get secret KeyVaultSecret secret = secretClient.GetSecret(secretName).Value; @@ -119,14 +116,12 @@ std::cout << "Secret is returned with name " << secret.Name << " and value " << Updating an existing secret - -```cpp +```cpp // change one of the properties secret.Properties.ContentType = "my content"; // update the secret KeyVaultSecret updatedSecret = secretClient.UpdateSecretProperties(secret.Properties).Value; -std::string updatedValueString - = updatedSecret.Value.HasValue() ? updatedSecret.Value.Value() : "NONE RETURNED"; +std::string updatedValueString = updatedSecret.Properties.ContentType.ValueOr("NONE RETURNED"); std::cout << "Secret's content type is now " << updatedValueString << std::endl; ``` @@ -134,7 +129,6 @@ std::cout << "Secret's content type is now " << updatedValueString << std::endl; Delete an existing secret. - ```cpp // start deleting the secret DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name); @@ -152,7 +146,6 @@ secretClient.PurgeDeletedSecret(secret.Name); Delete and Purge a secret. - ```cpp // start deleting the secret DeleteSecretOperation operation = secretClient.StartDeleteSecret(secret.Name); @@ -170,7 +163,6 @@ secretClient.PurgeDeletedSecret(secret.Name); List all the secrets in keyvault. - ```cpp // get all the versions of a secret for (auto secretsVersion = secretClient.GetPropertiesOfSecretsVersions(secret1.Name); diff --git a/sdk/keyvault/azure-security-keyvault-secrets/client.tsp b/sdk/keyvault/azure-security-keyvault-secrets/client.tsp deleted file mode 100644 index edd2ce7a0..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/client.tsp +++ /dev/null @@ -1,7 +0,0 @@ -// client.tsp -import "./main.tsp"; -import "@azure-tools/typespec-client-generator-core"; - -using Azure.ClientGenerator.Core; - -@@clientName(KeyVault, "SecretClient"); // This is the name of the client diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated.hpp new file mode 100644 index 000000000..15593df2a --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated.hpp @@ -0,0 +1,13 @@ +// 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 +#include +#include +#include +#include +#include diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/dll_import_export.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/dll_import_export.hpp new file mode 100644 index 000000000..154784243 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/dll_import_export.hpp @@ -0,0 +1,29 @@ +// 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 + +#if defined(AZ_SECURITY_KEYVAULT_SECRETS_DLL) \ + || (0 /*@AZ_SECURITY_KEYVAULT_SECRETS_DLL_INSTALLED_AS_PACKAGE@*/) +#define AZ_SECURITY_KEYVAULT_SECRETS_BUILT_AS_DLL 1 +#else +#define AZ_SECURITY_KEYVAULT_SECRETS_BUILT_AS_DLL 0 +#endif + +#if AZ_SECURITY_KEYVAULT_SECRETS_BUILT_AS_DLL +#if defined(_MSC_VER) +#if defined(AZ_SECURITY_KEYVAULT_SECRETS_BEING_BUILT) +#define AZ_SECURITY_KEYVAULT_SECRETS_DLLEXPORT __declspec(dllexport) +#else // !defined(AZ_SECURITY_KEYVAULT_SECRETS_BEING_BUILT) +#define AZ_SECURITY_KEYVAULT_SECRETS_DLLEXPORT __declspec(dllimport) +#endif // AZ_SECURITY_KEYVAULT_SECRETS_BEING_BUILT +#else // !defined(_MSC_VER) +#define AZ_SECURITY_KEYVAULT_SECRETS_DLLEXPORT +#endif // _MSC_VER +#else // !AZ_SECURITY_KEYVAULT_SECRETS_BUILT_AS_DLL +#define AZ_SECURITY_KEYVAULT_SECRETS_DLLEXPORT +#endif // AZ_SECURITY_KEYVAULT_SECRETS_BUILT_AS_DLL + +#undef AZ_SECURITY_KEYVAULT_SECRETS_BUILT_AS_DLL diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client.hpp new file mode 100644 index 000000000..dee1f0a77 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client.hpp @@ -0,0 +1,227 @@ +// 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/secrets/generated/key_vault_client_options.hpp" +#include "azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp" +#include "azure/keyvault/secrets/generated/models/generated_models.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { 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 SET operation adds a secret to the Azure Key Vault. If the named secret already + * exists, Azure Key Vault creates a new version of that secret. This operation requires the + * secrets/set permission. + * @param secretName The name of the secret. 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 for setting the secret. + * @param context The context for the operation can be used for request cancellation. + * @return A secret consisting of a value, id and its attributes. + * + */ + Response SetSecret( + const std::string& secretName, + const Models::SecretSetParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The DELETE operation applies to any secret stored in Azure Key Vault. DELETE cannot be + * applied to an individual version of a secret. This operation requires the secrets/delete + * permission. + * @param secretName The name of the secret. + * @param context The context for the operation can be used for request cancellation. + * @return A Deleted Secret consisting of its previous id, attributes and its tags, as well as + * information on when it will be purged. + * + */ + Response DeleteSecret( + const std::string& secretName, + const Core::Context& context = {}) const; + + /** + * @brief The UPDATE operation changes specified attributes of an existing stored secret. + * Attributes that are not specified in the request are left unchanged. The value of a secret + * itself cannot be changed. This operation requires the secrets/set permission. + * @param secretName The name of the secret. + * @param secretVersion The version of the secret. + * @param parameters The parameters for update secret operation. + * @param context The context for the operation can be used for request cancellation. + * @return A secret consisting of a value, id and its attributes. + * + */ + Response UpdateSecret( + const std::string& secretName, + const std::string& secretVersion, + const Models::SecretUpdateParameters& parameters, + const Core::Context& context = {}) const; + + /** + * @brief The GET operation is applicable to any secret stored in Azure Key Vault. This + * operation requires the secrets/get permission. + * @param secretName The name of the secret. + * @param secretVersion The version of the secret. This URI fragment is optional. If not + * specified, the latest version of the secret is returned. + * @param context The context for the operation can be used for request cancellation. + * @return A secret consisting of a value, id and its attributes. + * + */ + Response GetSecret( + const std::string& secretName, + const std::string& secretVersion, + const Core::Context& context = {}) const; + + /** + * @brief The Get Secrets operation is applicable to the entire vault. However, only the base + * secret identifier and its attributes are provided in the response. Individual secret versions + * are not listed in the response. This operation requires the secrets/list permission. + * @param options Optional parameters. + * @param context The context for the operation can be used for request cancellation. + * @return The secret list result. + * + */ + GetSecretsPagedResponse GetSecrets( + const KeyVaultClientGetSecretsOptions& options = {}, + const Core::Context& context = {}) const; + + /** + * @brief The full secret identifier and attributes are provided in the response. No values are + * returned for the secrets. This operations requires the secrets/list permission. + * @param secretName The name of the secret. + * @param options Optional parameters. + * @param context The context for the operation can be used for request cancellation. + * @return The secret list result. + * + */ + GetSecretVersionsPagedResponse GetSecretVersions( + const std::string& secretName, + const KeyVaultClientGetSecretVersionsOptions& options = {}, + const Core::Context& context = {}) const; + + /** + * @brief The Get Deleted Secrets operation returns the secrets that have been deleted for a + * vault enabled for soft-delete. This operation requires the secrets/list permission. + * @param options Optional parameters. + * @param context The context for the operation can be used for request cancellation. + * @return The deleted secret list result + * + */ + GetDeletedSecretsPagedResponse GetDeletedSecrets( + const KeyVaultClientGetDeletedSecretsOptions& options = {}, + const Core::Context& context = {}) const; + + /** + * @brief The Get Deleted Secret operation returns the specified deleted secret along with its + * attributes. This operation requires the secrets/get permission. + * @param secretName The name of the secret. + * @param context The context for the operation can be used for request cancellation. + * @return A Deleted Secret consisting of its previous id, attributes and its tags, as well as + * information on when it will be purged. + * + */ + Response GetDeletedSecret( + const std::string& secretName, + const Core::Context& context = {}) const; + + /** + * @brief The purge deleted secret operation removes the secret permanently, without the + * possibility of recovery. This operation can only be enabled on a soft-delete enabled vault. + * This operation requires the secrets/purge permission. + * @param secretName The name of the secret. + * @param context The context for the operation can be used for request cancellation. + * @return Operation result. + * + */ + Response PurgeDeletedSecret( + const std::string& secretName, + const Core::Context& context = {}) const; + + /** + * @brief Recovers the deleted secret in the specified vault. This operation can only be + * performed on a soft-delete enabled vault. This operation requires the secrets/recover + * permission. + * @param secretName The name of the deleted secret. + * @param context The context for the operation can be used for request cancellation. + * @return A secret consisting of a value, id and its attributes. + * + */ + Response RecoverDeletedSecret( + const std::string& secretName, + const Core::Context& context = {}) const; + + /** + * @brief Requests that a backup of the specified secret be downloaded to the client. All + * versions of the secret will be downloaded. This operation requires the secrets/backup + * permission. + * @param secretName The name of the secret. + * @param context The context for the operation can be used for request cancellation. + * @return The backup secret result, containing the backup blob. + * + */ + Response BackupSecret( + const std::string& secretName, + const Core::Context& context = {}) const; + + /** + * @brief Restores a backed up secret, and all its versions, to a vault. This operation requires + * the secrets/restore permission. + * @param parameters The parameters to restore the secret. + * @param context The context for the operation can be used for request cancellation. + * @return A secret consisting of a value, id and its attributes. + * + */ + Response RestoreSecret( + const Models::SecretRestoreParameters& parameters, + const Core::Context& context = {}) const; + + private: + std::shared_ptr m_pipeline; + Core::Url m_url; + std::string m_apiVersion; + }; +}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client_options.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client_options.hpp new file mode 100644 index 000000000..dce9ec0e8 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/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 "azure/keyvault/secrets/generated/models/generated_models.hpp" + +#include +#include + +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { 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 GetSecrets operation options. + * + */ + struct KeyVaultClientGetSecretsOptions 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 GetSecretVersions operation options. + * + */ + struct KeyVaultClientGetSecretVersionsOptions 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 GetDeletedSecrets operation options. + * + */ + struct KeyVaultClientGetDeletedSecretsOptions 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::Secrets::_detail diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp new file mode 100644 index 000000000..400da47c5 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/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 "azure/keyvault/secrets/generated/key_vault_client_options.hpp" +#include "azure/keyvault/secrets/generated/models/generated_models.hpp" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail { + class KeyVaultClient; + + /** + * @brief The secret list result. + * + */ + class GetSecretsPagedResponse final : public Core::PagedResponse { + friend class KeyVaultClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + KeyVaultClientGetSecretsOptions m_options; + + void OnNextPage(const Core::Context& context); + + public: + /// A response message containing a list of secrets in the key vault along with a link to the + /// next page of secrets. + Nullable> Value; + }; + + /** + * @brief The secret list result. + * + */ + class GetSecretVersionsPagedResponse final + : public Core::PagedResponse { + friend class KeyVaultClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + std::string m_secretName; + KeyVaultClientGetSecretVersionsOptions m_options; + + void OnNextPage(const Core::Context& context); + + public: + /// A response message containing a list of secrets in the key vault along with a link to the + /// next page of secrets. + Nullable> Value; + }; + + /** + * @brief The deleted secret list result + * + */ + class GetDeletedSecretsPagedResponse final + : public Core::PagedResponse { + friend class KeyVaultClient; + friend class Core::PagedResponse; + + private: + std::shared_ptr m_client; + KeyVaultClientGetDeletedSecretsOptions m_options; + + void OnNextPage(const Core::Context& context); + + public: + /// A response message containing a list of deleted secrets in the key vault along with a link + /// to the next page of deleted secrets. + Nullable> Value; + }; +}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/models/generated_models.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/models/generated_models.hpp new file mode 100644 index 000000000..4c34da3e9 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/models/generated_models.hpp @@ -0,0 +1,316 @@ +// 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/secrets/generated/dll_import_export.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail { + namespace Models { + /** + * @brief Reflects the deletion recovery level currently in effect for secrets in the current + * vault. If it contains 'Purgeable', the secret can be permanently deleted by a privileged + * user; otherwise, only the system can purge the secret, 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_SECRETS_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_SECRETS_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_SECRETS_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_SECRETS_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_SECRETS_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_SECRETS_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_SECRETS_DLLEXPORT static const DeletionRecoveryLevel + CustomizedRecoverableProtectedSubscription; + }; + + /** + * @brief The secret management attributes. + * + */ + struct SecretAttributes 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 secrets in the current + /// vault. If it contains 'Purgeable', the secret can be permanently deleted by a privileged + /// user; otherwise, only the system can purge the secret, at the end of the retention + /// interval. + Nullable RecoveryLevel; + }; + + /** + * @brief A secret consisting of a value, id and its attributes. + * + */ + struct SecretBundle final + { + /// The secret value. + Nullable Value; + + /// The secret id. + Nullable Id; + + /// The content type of the secret. + Nullable ContentType; + + /// The secret management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// [out] If this is a secret backing a KV certificate, then this field specifies the + /// corresponding key backing the KV certificate. + Nullable Kid; + + /// [out] True if the secret's lifetime is managed by key vault. If this is a secret backing a + /// certificate, then managed will be true. + Nullable Managed; + }; + + /** + * @brief The secret set parameters. + * + */ + struct SecretSetParameters final + { + /// The value of the secret. + std::string Value; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// Type of the secret value such as a password. + Nullable ContentType; + + /// The secret management attributes. + Nullable SecretAttributes; + }; + + /** + * @brief A Deleted Secret consisting of its previous id, attributes and its tags, as well as + * information on when it will be purged. + * + */ + struct DeletedSecretBundle final + { + /// The secret value. + Nullable Value; + + /// The secret id. + Nullable Id; + + /// The content type of the secret. + Nullable ContentType; + + /// The secret management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// [out] If this is a secret backing a KV certificate, then this field specifies the + /// corresponding key backing the KV certificate. + Nullable Kid; + + /// [out] True if the secret's lifetime is managed by key vault. If this is a secret backing a + /// certificate, then managed will be true. + Nullable Managed; + + /// The url of the recovery object, used to identify and recover the deleted secret. + Nullable RecoveryId; + + /// [out] The time when the secret is scheduled to be purged, in UTC + Nullable ScheduledPurgeDate; + + /// [out] The time when the secret was deleted, in UTC + Nullable DeletedDate; + }; + + /** + * @brief The secret update parameters. + * + */ + struct SecretUpdateParameters final + { + /// Type of the secret value such as a password. + Nullable ContentType; + + /// The secret management attributes. + Nullable SecretAttributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + }; + + /** + * @brief The secret item containing secret metadata. + * + */ + struct SecretItem final + { + /// Secret identifier. + Nullable Id; + + /// The secret management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// Type of the secret value such as a password. + Nullable ContentType; + + /// [out] True if the secret's lifetime is managed by key vault. If this is a key backing a + /// certificate, then managed will be true. + Nullable Managed; + }; + + /** + * @brief The deleted secret item containing metadata about the deleted secret. + * + */ + struct DeletedSecretItem final + { + /// Secret identifier. + Nullable Id; + + /// The secret management attributes. + Nullable Attributes; + + /// Application specific metadata in the form of key-value pairs. + Nullable> Tags; + + /// Type of the secret value such as a password. + Nullable ContentType; + + /// [out] True if the secret'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 secret. + Nullable RecoveryId; + + /// [out] The time when the secret is scheduled to be purged, in UTC + Nullable ScheduledPurgeDate; + + /// [out] The time when the secret was deleted, in UTC + Nullable DeletedDate; + }; + + /** + * @brief PurgeDeletedSecret operation result. + * + */ + struct PurgeDeletedSecretResult final + { + }; + + /** + * @brief The backup secret result, containing the backup blob. + * + */ + struct BackupSecretResult final + { + /// [out] The backup blob containing the backed up secret. + Nullable> Value; + }; + + /** + * @brief The secret restore parameters. + * + */ + struct SecretRestoreParameters final + { + /// The backup blob associated with a secret bundle. + std::vector SecretBundleBackup; + }; +}}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail::Models diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/rtti.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/rtti.hpp new file mode 100644 index 000000000..8a71b9e2d --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/generated/rtti.hpp @@ -0,0 +1,10 @@ +// 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 + +#if defined(AZURE_RTTI) || (0 /*@AZ_SECURITY_KEYVAULT_SECRETS_RTTI@*/) +#define AZ_SECURITY_KEYVAULT_SECRETS_RTTI +#endif diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_deleted_secret.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_deleted_secret.hpp index ee320002f..5a4dedc12 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_deleted_secret.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_deleted_secret.hpp @@ -11,6 +11,12 @@ #include namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { + class SecretClient; + class DeletedSecretPagedResponse; + namespace _detail { namespace Models { + struct DeletedSecretBundle; + struct DeletedSecretItem; + }} // namespace _detail::Models /** * @brief A Deleted Secret consisting of its previous id, attributes and its tags, * as well as information on when it will be purged. @@ -44,5 +50,12 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { * @param name Name of the deleted secret. */ DeletedSecret(std::string name) : KeyVaultSecret(std::move(name)) {} + + private: + DeletedSecret(_detail::Models::DeletedSecretBundle const& deletedSecret); + DeletedSecret(_detail::Models::DeletedSecretItem const& deletedSecret); + friend class SecretClient; + friend class DeletedSecretOperation; + friend class DeletedSecretPagedResponse; }; }}}} // namespace Azure::Security::KeyVault::Secrets diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_operations.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_operations.hpp index 33b7a324e..85c08d47b 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_operations.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_operations.hpp @@ -16,8 +16,8 @@ #include #include - namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { + class SecretClient; /** * @brief Represents a long running operation to restore a deleted secret. diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_options.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_options.hpp index 44f938d9b..3f2b367ec 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_options.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_options.hpp @@ -6,10 +6,10 @@ * @brief Keyvault Secret actions options */ #pragma once +#include "azure/keyvault/secrets/generated/key_vault_client_options.hpp" #include "dll_import_export.hpp" #include - namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { /** @@ -22,7 +22,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { * @brief Service Version used. * */ - std::string ApiVersion{"7.5"}; + std::string ApiVersion{_detail::KeyVaultClientOptions().ApiVersion}; }; /** diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret.hpp index fb00b4e0e..914d320e6 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret.hpp @@ -10,7 +10,13 @@ #include "azure/keyvault/secrets/keyvault_secret_properties.hpp" namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { - + class SecretClient; + class SecretPropertiesPagedResponse; + namespace _detail { namespace Models { + struct SecretBundle; + struct SecretItem; + struct SecretSetParameters; + }} // namespace _detail::Models /** * @brief Secret is the resource consisting of name, value and its attributes specified in * SecretProperties. It is managed by Secret Service. @@ -54,30 +60,17 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { * @param name The name of the secret. * @param value The name of the secret. */ - KeyVaultSecret(std::string const& name, std::string const& value) - : Name(name), Value(value), Properties(name) - { - if (Name.empty()) - { - throw std::invalid_argument("Name cannot be empty"); - } - - if (Value.HasValue() == false || Value.Value().empty()) - { - throw std::invalid_argument("Value cannot be empty"); - } - } + KeyVaultSecret(std::string const& name, std::string const& value); private: - KeyVaultSecret(std::string name) : Name(std::move(name)) - { - if (Name.empty()) - { - throw std::invalid_argument("Name cannot be empty"); - } - } + KeyVaultSecret(std::string name); + KeyVaultSecret(_detail::Models::SecretBundle const& secret); + KeyVaultSecret(_detail::Models::SecretItem const& secret); + _detail::Models::SecretSetParameters ToSetSecretParameters() const; friend struct DeletedSecret; + friend class SecretClient; + friend class SecretPropertiesPagedResponse; }; }}}} // namespace Azure::Security::KeyVault::Secrets diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_paged_response.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_paged_response.hpp index 52263ca32..b2c0c6dae 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_paged_response.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_paged_response.hpp @@ -8,6 +8,7 @@ #pragma once +#include "azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp" #include "azure/keyvault/secrets/keyvault_deleted_secret.hpp" #include "azure/keyvault/secrets/keyvault_secret_properties.hpp" @@ -34,7 +35,8 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { std::string m_secretName; std::shared_ptr m_secretClient; - + _detail::GetSecretsPagedResponse m_generatedResponse; + _detail::GetSecretVersionsPagedResponse m_generatedVersionResponse; void OnNextPage(const Azure::Core::Context& context); SecretPropertiesPagedResponse( @@ -48,6 +50,36 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { RawResponse = std::move(rawResponse); } + SecretPropertiesPagedResponse( + _detail::GetSecretsPagedResponse& secretPagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr secretClient, + std::string const& secretName = std::string()) + : m_secretName(secretName), m_secretClient(std::move(secretClient)), + m_generatedResponse(std::move(secretPagedResponse)) + { + for (auto& item : m_generatedResponse.Value.Value()) + { + Items.push_back(KeyVaultSecret(item).Properties); + } + RawResponse = std::move(rawResponse); + } + + SecretPropertiesPagedResponse( + _detail::GetSecretVersionsPagedResponse& secretPagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr secretClient, + std::string const& secretName = std::string()) + : m_secretName(secretName), m_secretClient(std::move(secretClient)), + m_generatedVersionResponse(std::move(secretPagedResponse)) + { + for (auto& item : m_generatedVersionResponse.Value.Value()) + { + Items.push_back(KeyVaultSecret(item).Properties); + } + RawResponse = std::move(rawResponse); + } + public: /** * @brief Construct a new SecretPropertiesPagedResponse object. @@ -74,6 +106,8 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { friend class Azure::Core::PagedResponse; std::shared_ptr m_secretClient; + _detail::GetDeletedSecretsPagedResponse m_generatedResponse; + void OnNextPage(const Azure::Core::Context& context); DeletedSecretPagedResponse( @@ -86,6 +120,20 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { RawResponse = std::move(rawResponse); } + DeletedSecretPagedResponse( + _detail::GetDeletedSecretsPagedResponse& secretPagedResponse, + std::unique_ptr rawResponse, + std::shared_ptr secretClient) + : m_secretClient(std::move(secretClient)), + m_generatedResponse(std::move(secretPagedResponse)) + { + for (auto& item : m_generatedResponse.Value.Value()) + { + Items.push_back(DeletedSecret(item)); + } + RawResponse = std::move(rawResponse); + } + public: /** * @brief Construct a new Deleted Key Single Page object diff --git a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_properties.hpp b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_properties.hpp index d4a316f4c..a1ffd96b1 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_properties.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/inc/azure/keyvault/secrets/keyvault_secret_properties.hpp @@ -13,8 +13,11 @@ #include #include - namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { + class SecretClient; + namespace _detail { namespace Models { + struct SecretUpdateParameters; + }} // namespace _detail::Models /** * @brief The Secret attributes managed by the KeyVault service. @@ -141,5 +144,9 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { * */ static SecretProperties CreateFromURL(std::string const& url); + + private: + _detail::Models::SecretUpdateParameters ToSecretUpdateParameters() const; + friend class SecretClient; }; }}}} // namespace Azure::Security::KeyVault::Secrets 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 4712cae46..03953a841 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 @@ -15,6 +15,7 @@ #include "azure/keyvault/secrets/keyvault_secret.hpp" #include "azure/keyvault/secrets/keyvault_secret_paged_response.hpp" #include "dll_import_export.hpp" +#include "generated.hpp" #include #include @@ -45,6 +46,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { class SecretClient final { private: + std::shared_ptr<_detail::KeyVaultClient> m_client = nullptr; // Using a shared pipeline for a client to share it with LRO (like delete key) Azure::Core::Url m_vaultUrl; std::string m_apiVersion; @@ -68,12 +70,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { * * @param keyClient An existing key vault key client. */ - explicit SecretClient(SecretClient const& keyClient) - : m_vaultUrl(keyClient.m_vaultUrl), m_apiVersion(keyClient.m_apiVersion), - m_pipeline(keyClient.m_pipeline) - - { - } + explicit SecretClient(SecretClient const& keyClient) { m_client = keyClient.m_client; } ~SecretClient() = default; @@ -278,18 +275,6 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { * * @return The key secret's primary URL endpoint. */ - std::string GetUrl() const; - - private: - 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; - std::unique_ptr SendRequest( - Azure::Core::Http::Request& request, - Azure::Core::Context const& context) const; + std::string GetUrl() const { return m_client->GetUrl(); } }; }}}} // namespace Azure::Security::KeyVault::Secrets diff --git a/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1-basic-operations/sample1_basic_operations.cpp b/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1-basic-operations/sample1_basic_operations.cpp index e730089bc..1916e09b6 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1-basic-operations/sample1_basic_operations.cpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1-basic-operations/sample1_basic_operations.cpp @@ -53,8 +53,7 @@ int main() secret.Properties.ContentType = "my content"; // update the secret KeyVaultSecret updatedSecret = secretClient.UpdateSecretProperties(secret.Properties).Value; - std::string updatedValueString - = updatedSecret.Value.HasValue() ? updatedSecret.Value.Value() : "NONE RETURNED"; + std::string updatedValueString = updatedSecret.Properties.ContentType.ValueOr("NONE RETURNED"); std::cout << "Secret's content type is now " << updatedValueString << std::endl; // @end_snippet diff --git a/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1_basic_operations.md b/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1_basic_operations.md index 273b17035..316c3fdd8 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1_basic_operations.md +++ b/sdk/keyvault/azure-security-keyvault-secrets/samples/sample1_basic_operations.md @@ -57,10 +57,8 @@ Call UpdateSecretProperties to change on of the secret properties. secret.Properties.ContentType = "my content"; // update the secret KeyVaultSecret updatedSecret = secretClient.UpdateSecretProperties(secret.Properties).Value; -std::string updatedValueString = updatedSecret.Value.HasValue() ? updatedSecret.Value.Value() - : "NONE RETURNED"; -std::cout << "Secret's content type is now " << updatedValueString - << std::endl; +std::string updatedValueString = updatedSecret.Properties.ContentType.ValueOr("NONE RETURNED"); +std::cout << "Secret's content type is now " << updatedValueString << std::endl; ``` ## Deleting a secret diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/generated.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/generated.cpp new file mode 100644 index 000000000..ac14b0edc --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/generated.cpp @@ -0,0 +1,19 @@ +// 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 "azure/keyvault/secrets/generated/models/generated_models.hpp" + +using namespace Azure::Security::KeyVault::Secrets::_detail::Models; + +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"}; diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/get_deleted_secrets_paged_response.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/get_deleted_secrets_paged_response.cpp new file mode 100644 index 000000000..018eebb19 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/get_deleted_secrets_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 "azure/keyvault/secrets/generated/key_vault_client.hpp" +#include "azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp" + +using namespace Azure::Security::KeyVault::Secrets::_detail; + +void GetDeletedSecretsPagedResponse::OnNextPage(Core::Context const& context) +{ + const auto pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetDeletedSecrets(this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/get_secret_versions_paged_response.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/get_secret_versions_paged_response.cpp new file mode 100644 index 000000000..afa60c6eb --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/get_secret_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 "azure/keyvault/secrets/generated/key_vault_client.hpp" +#include "azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp" + +using namespace Azure::Security::KeyVault::Secrets::_detail; + +void GetSecretVersionsPagedResponse::OnNextPage(Core::Context const& context) +{ + const auto pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetSecretVersions(this->m_secretName, this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/get_secrets_paged_response.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/get_secrets_paged_response.cpp new file mode 100644 index 000000000..65b7c28c9 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/get_secrets_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 "azure/keyvault/secrets/generated/key_vault_client.hpp" +#include "azure/keyvault/secrets/generated/key_vault_client_paged_responses.hpp" + +using namespace Azure::Security::KeyVault::Secrets::_detail; + +void GetSecretsPagedResponse::OnNextPage(Core::Context const& context) +{ + const auto pageToken = this->NextPageToken; + this->m_options.NextPageToken = pageToken.Value(); + *this = this->m_client->GetSecrets(this->m_options, context); + this->CurrentPageToken = pageToken.Value(); +} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/key_vault_client.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/key_vault_client.cpp new file mode 100644 index 000000000..625805fb7 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/key_vault_client.cpp @@ -0,0 +1,1973 @@ +// 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 "azure/keyvault/secrets/generated/key_vault_client.hpp" + +#include "private/package_version.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace Azure::Security::KeyVault::Secrets::_detail; + +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 = {"https://vault.azure.net/.default"}; + perRetryPolicies.emplace_back( + std::make_unique( + credential, tokenRequestContext)); + } + + m_pipeline = std::make_shared( + options, + "security-keyvault-secrets", + _detail::PackageVersion::ToString(), + std::move(perRetryPolicies), + std::move(perCallPolicies)); +} + +std::string KeyVaultClient::GetUrl() const { return m_url.GetAbsoluteUrl(); } + +Azure::Response +KeyVaultClient::SetSecret( + const std::string& secretName, + const Models::SecretSetParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("secrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + jsonRoot["value"] = parameters.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.ContentType.HasValue()) + { + jsonRoot["contentType"] = parameters.ContentType.Value(); + } + + if (parameters.SecretAttributes.HasValue()) + { + if (parameters.SecretAttributes.Value().Enabled.HasValue()) + { + jsonRoot["attributes"]["enabled"] = parameters.SecretAttributes.Value().Enabled.Value(); + } + + if (parameters.SecretAttributes.Value().NotBefore.HasValue()) + { + jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().NotBefore.Value()); + } + + if (parameters.SecretAttributes.Value().Expires.HasValue()) + { + jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().Expires.Value()); + } + + if (parameters.SecretAttributes.Value().Created.HasValue()) + { + jsonRoot["attributes"]["created"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().Created.Value()); + } + + if (parameters.SecretAttributes.Value().Updated.HasValue()) + { + jsonRoot["attributes"]["updated"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().Updated.Value()); + } + + if (parameters.SecretAttributes.Value().RecoverableDays.HasValue()) + { + jsonRoot["attributes"]["recoverableDays"] + = parameters.SecretAttributes.Value().RecoverableDays.Value(); + } + + if (parameters.SecretAttributes.Value().RecoveryLevel.HasValue()) + { + jsonRoot["attributes"]["recoveryLevel"] + = parameters.SecretAttributes.Value().RecoveryLevel.Value().ToString(); + } + } + + 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::SecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].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::DeleteSecret(const std::string& secretName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("secrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + + 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::DeletedSecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].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::UpdateSecret( + const std::string& secretName, + const std::string& secretVersion, + const Models::SecretUpdateParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("secrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + if (secretVersion.empty()) + { + throw std::invalid_argument("Parameter 'secretVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretVersion)); + + url.AppendQueryParameter("api-version", Core::Url::Encode(m_apiVersion)); + + std::string jsonBody; + { + auto jsonRoot = Core::Json::_internal::json::object(); + if (parameters.ContentType.HasValue()) + { + jsonRoot["contentType"] = parameters.ContentType.Value(); + } + + if (parameters.SecretAttributes.HasValue()) + { + if (parameters.SecretAttributes.Value().Enabled.HasValue()) + { + jsonRoot["attributes"]["enabled"] = parameters.SecretAttributes.Value().Enabled.Value(); + } + + if (parameters.SecretAttributes.Value().NotBefore.HasValue()) + { + jsonRoot["attributes"]["nbf"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().NotBefore.Value()); + } + + if (parameters.SecretAttributes.Value().Expires.HasValue()) + { + jsonRoot["attributes"]["exp"] = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().Expires.Value()); + } + + if (parameters.SecretAttributes.Value().Created.HasValue()) + { + jsonRoot["attributes"]["created"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().Created.Value()); + } + + if (parameters.SecretAttributes.Value().Updated.HasValue()) + { + jsonRoot["attributes"]["updated"] + = Core::_internal::PosixTimeConverter::DateTimeToPosixTime( + parameters.SecretAttributes.Value().Updated.Value()); + } + + if (parameters.SecretAttributes.Value().RecoverableDays.HasValue()) + { + jsonRoot["attributes"]["recoverableDays"] + = parameters.SecretAttributes.Value().RecoverableDays.Value(); + } + + if (parameters.SecretAttributes.Value().RecoveryLevel.HasValue()) + { + jsonRoot["attributes"]["recoveryLevel"] + = parameters.SecretAttributes.Value().RecoveryLevel.Value().ToString(); + } + } + + if (parameters.Tags.HasValue()) + { + jsonRoot["tags"] = Core::Json::_internal::json::object(); + + for (auto const& kv : parameters.Tags.Value()) + { + jsonRoot["tags"][kv.first] = kv.second; + } + } + + 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::SecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].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::GetSecret( + const std::string& secretName, + const std::string& secretVersion, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("secrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + if (secretVersion.empty()) + { + throw std::invalid_argument("Parameter 'secretVersion' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretVersion)); + + 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::SecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].get(); + } + } + catch (Core::Json::_internal::json::exception const& ex) + { + throw Core::RequestFailedException(ex.what()); + } + } + } + + return Response(std::move(response), std::move(rawResponse)); +} + +GetSecretsPagedResponse KeyVaultClient::GetSecrets( + const KeyVaultClientGetSecretsOptions& options, + const Core::Context& context) const +{ + Core::Url url; + if (options.NextPageToken.empty()) + { + url = m_url; + url.AppendPath("secrets"); + + 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); + } + + GetSecretsPagedResponse 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::SecretItem vectorItem{}; + + if (jsonItem.contains("id") && !jsonItem["id"].is_null()) + { + vectorItem.Id = jsonItem["id"].get(); + } + + if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null()) + { + vectorItem.Attributes = Models::SecretAttributes{}; + + 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.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("contentType") && !jsonItem["contentType"].is_null()) + { + vectorItem.ContentType = jsonItem["contentType"].get(); + } + + 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; +} + +GetSecretVersionsPagedResponse KeyVaultClient::GetSecretVersions( + const std::string& secretName, + const KeyVaultClientGetSecretVersionsOptions& options, + const Core::Context& context) const +{ + Core::Url url; + if (options.NextPageToken.empty()) + { + url = m_url; + url.AppendPath("secrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + 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); + } + + GetSecretVersionsPagedResponse response{}; + response.m_client = std::make_shared(*this); + response.m_secretName = secretName; + 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::SecretItem vectorItem{}; + + if (jsonItem.contains("id") && !jsonItem["id"].is_null()) + { + vectorItem.Id = jsonItem["id"].get(); + } + + if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null()) + { + vectorItem.Attributes = Models::SecretAttributes{}; + + 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.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("contentType") && !jsonItem["contentType"].is_null()) + { + vectorItem.ContentType = jsonItem["contentType"].get(); + } + + 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; +} + +GetDeletedSecretsPagedResponse KeyVaultClient::GetDeletedSecrets( + const KeyVaultClientGetDeletedSecretsOptions& options, + const Core::Context& context) const +{ + Core::Url url; + if (options.NextPageToken.empty()) + { + url = m_url; + url.AppendPath("deletedsecrets"); + + 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); + } + + GetDeletedSecretsPagedResponse 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::DeletedSecretItem vectorItem{}; + + if (jsonItem.contains("id") && !jsonItem["id"].is_null()) + { + vectorItem.Id = jsonItem["id"].get(); + } + + if (jsonItem.contains("attributes") && !jsonItem["attributes"].is_null()) + { + vectorItem.Attributes = Models::SecretAttributes{}; + + 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.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("contentType") && !jsonItem["contentType"].is_null()) + { + vectorItem.ContentType = jsonItem["contentType"].get(); + } + + 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::GetDeletedSecret(const std::string& secretName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("deletedsecrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + + 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::DeletedSecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].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::PurgeDeletedSecret(const std::string& secretName, const Core::Context& context) + const +{ + auto url = m_url; + url.AppendPath("deletedsecrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + + 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::PurgeDeletedSecretResult response{}; + + return Response(std::move(response), std::move(rawResponse)); +} + +Azure::Response +KeyVaultClient::RecoverDeletedSecret(const std::string& secretName, const Core::Context& context) + const +{ + auto url = m_url; + url.AppendPath("deletedsecrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + 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::SecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].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::BackupSecret(const std::string& secretName, const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("secrets/"); + if (secretName.empty()) + { + throw std::invalid_argument("Parameter 'secretName' cannot be an empty string."); + } + url.AppendPath(Core::Url::Encode(secretName)); + 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::BackupSecretResult 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::RestoreSecret( + const Models::SecretRestoreParameters& parameters, + const Core::Context& context) const +{ + auto url = m_url; + url.AppendPath("secrets/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.SecretBundleBackup); + 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::SecretBundle 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(); + } + + if (jsonRoot.contains("id") && !jsonRoot["id"].is_null()) + { + response.Id = jsonRoot["id"].get(); + } + + if (jsonRoot.contains("contentType") && !jsonRoot["contentType"].is_null()) + { + response.ContentType = jsonRoot["contentType"].get(); + } + + if (jsonRoot.contains("attributes") && !jsonRoot["attributes"].is_null()) + { + response.Attributes = Models::SecretAttributes{}; + + 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.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("kid") && !jsonRoot["kid"].is_null()) + { + response.Kid = jsonRoot["kid"].get(); + } + + if (jsonRoot.contains("managed") && !jsonRoot["managed"].is_null()) + { + response.Managed = jsonRoot["managed"].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-secrets/src/keyvault_deleted_secret.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_deleted_secret.cpp new file mode 100644 index 000000000..bbbaf1f01 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_deleted_secret.cpp @@ -0,0 +1,110 @@ +// 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 "azure/keyvault/secrets/keyvault_deleted_secret.hpp" + +#include "azure/keyvault/secrets/generated/models/generated_models.hpp" + +namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { + DeletedSecret::DeletedSecret(_detail::Models::DeletedSecretBundle const& deletedSecret) + { + if (deletedSecret.RecoveryId.HasValue()) + { + RecoveryId = deletedSecret.RecoveryId.Value(); + } + if (deletedSecret.ScheduledPurgeDate.HasValue()) + { + ScheduledPurgeDate = deletedSecret.ScheduledPurgeDate.Value(); + } + if (deletedSecret.DeletedDate.HasValue()) + { + DeletedOn = deletedSecret.DeletedDate.Value(); + } + if (deletedSecret.Value.HasValue()) + { + Value = deletedSecret.Value; + } + if (deletedSecret.Id.HasValue()) + { + Properties = SecretProperties::CreateFromURL(deletedSecret.RecoveryId.Value()); + Id = deletedSecret.Id.Value(); + Properties.Id = deletedSecret.Id.Value(); + Name = Properties.Name; + } + if (deletedSecret.ContentType.HasValue()) + { + Properties.ContentType = deletedSecret.ContentType; + } + Properties.KeyId = deletedSecret.Kid; + if (deletedSecret.Managed.HasValue()) + { + Properties.Managed = deletedSecret.Managed.Value(); + } + if (deletedSecret.Attributes.HasValue()) + { + Properties.ExpiresOn = deletedSecret.Attributes.Value().Expires; + Properties.NotBefore = deletedSecret.Attributes.Value().NotBefore; + Properties.Enabled = deletedSecret.Attributes.Value().Enabled; + Properties.CreatedOn = deletedSecret.Attributes.Value().Created; + Properties.UpdatedOn = deletedSecret.Attributes.Value().Updated; + if (deletedSecret.Attributes.Value().RecoverableDays.HasValue()) + { + Properties.RecoverableDays = deletedSecret.Attributes.Value().RecoverableDays.Value(); + } + } + if (deletedSecret.Tags.HasValue()) + { + Properties.Tags = std::unordered_map( + deletedSecret.Tags.Value().begin(), deletedSecret.Tags.Value().end()); + } + } + + DeletedSecret::DeletedSecret(_detail::Models::DeletedSecretItem const& deletedSecret) + { + if (deletedSecret.RecoveryId.HasValue()) + { + RecoveryId = deletedSecret.RecoveryId.Value(); + } + if (deletedSecret.ScheduledPurgeDate.HasValue()) + { + ScheduledPurgeDate = deletedSecret.ScheduledPurgeDate.Value(); + } + if (deletedSecret.DeletedDate.HasValue()) + { + DeletedOn = deletedSecret.DeletedDate.Value(); + } + if (deletedSecret.RecoveryId.HasValue()) + { + Properties = SecretProperties::CreateFromURL(deletedSecret.Id.Value()); + Id = deletedSecret.Id.Value(); + Properties.Id = deletedSecret.Id.Value(); + } + if (deletedSecret.ContentType.HasValue()) + { + Properties.ContentType = deletedSecret.ContentType; + } + if (deletedSecret.Managed.HasValue()) + { + Properties.Managed = deletedSecret.Managed.Value(); + } + if (deletedSecret.Attributes.HasValue()) + { + Properties.ExpiresOn = deletedSecret.Attributes.Value().Expires; + Properties.NotBefore = deletedSecret.Attributes.Value().NotBefore; + Properties.Enabled = deletedSecret.Attributes.Value().Enabled; + Properties.CreatedOn = deletedSecret.Attributes.Value().Created; + Properties.UpdatedOn = deletedSecret.Attributes.Value().Updated; + if (deletedSecret.Attributes.Value().RecoverableDays.HasValue()) + { + Properties.RecoverableDays = deletedSecret.Attributes.Value().RecoverableDays.Value(); + } + } + if (deletedSecret.Tags.HasValue()) + { + Properties.Tags = std::unordered_map( + deletedSecret.Tags.Value().begin(), deletedSecret.Tags.Value().end()); + } + } +}}}} // namespace Azure::Security::KeyVault::Secrets diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_operations.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_operations.cpp index 30572b3a4..7f7103af7 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_operations.cpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_operations.cpp @@ -34,10 +34,12 @@ std::unique_ptr RecoverDeletedSecretOperation::P Azure::Core::Context const& context) { std::unique_ptr rawResponse; - + KeyVaultSecret secretResult; try { - rawResponse = m_secretClient->GetSecret(m_value.Name, GetSecretOptions(), context).RawResponse; + auto response = m_secretClient->GetSecret(m_continuationToken, GetSecretOptions(), context); + secretResult = response.Value; + rawResponse = std::move(response.RawResponse); } catch (Azure::Core::RequestFailedException& error) { @@ -61,8 +63,7 @@ std::unique_ptr RecoverDeletedSecretOperation::P if (m_status == Azure::Core::OperationStatus::Succeeded) { - auto receivedSecret = _detail::SecretSerializer::Deserialize(m_value.Name, *rawResponse); - m_value = receivedSecret.Properties; + m_value = secretResult.Properties; } return rawResponse; @@ -125,10 +126,12 @@ std::unique_ptr DeleteSecretOperation::PollInter Azure::Core::Context const& context) { std::unique_ptr rawResponse; - + Azure::Security::KeyVault::Secrets::DeletedSecret secretResult; try { - rawResponse = m_secretClient->GetDeletedSecret(m_value.Name, context).RawResponse; + auto response = m_secretClient->GetDeletedSecret(m_continuationToken, context); + secretResult = response.Value; + rawResponse = std::move(response.RawResponse); } catch (Azure::Core::RequestFailedException& error) { @@ -152,7 +155,7 @@ std::unique_ptr DeleteSecretOperation::PollInter if (m_status == Azure::Core::OperationStatus::Succeeded) { - m_value = _detail::DeletedSecretSerializer::Deserialize(m_value.Name, *rawResponse); + m_value = secretResult; } return rawResponse; } diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret.cpp new file mode 100644 index 000000000..7a4bfcaad --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret.cpp @@ -0,0 +1,155 @@ +// 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 "azure/keyvault/secrets/keyvault_secret.hpp" + +#include "azure/keyvault/secrets/generated/models/generated_models.hpp" + +namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { + KeyVaultSecret::KeyVaultSecret(std::string const& name, std::string const& value) + : Name(name), Value(value), Properties(name) + { + if (Name.empty()) + { + throw std::invalid_argument("Name cannot be empty"); + } + + if (Value.HasValue() == false || Value.Value().empty()) + { + throw std::invalid_argument("Value cannot be empty"); + } + } + + KeyVaultSecret::KeyVaultSecret(std::string name) : Name(std::move(name)) + { + if (Name.empty()) + { + throw std::invalid_argument("Name cannot be empty"); + } + } + + KeyVaultSecret::KeyVaultSecret(_detail::Models::SecretBundle const& secret) + { + Value = secret.Value; + if (secret.Id.HasValue()) + { + Id = secret.Id.Value(); + Properties = SecretProperties::CreateFromURL(secret.Id.Value()); + Name = Properties.Name; + } + Properties.ContentType = secret.ContentType; + Properties.KeyId = secret.Kid; + if (secret.Attributes.HasValue()) + { + Properties.ExpiresOn = secret.Attributes.Value().Expires; + Properties.NotBefore = secret.Attributes.Value().NotBefore; + Properties.Enabled = secret.Attributes.Value().Enabled; + Properties.CreatedOn = secret.Attributes.Value().Created; + Properties.UpdatedOn = secret.Attributes.Value().Updated; + if (secret.Attributes.Value().RecoverableDays.HasValue()) + { + Properties.RecoverableDays = secret.Attributes.Value().RecoverableDays.Value(); + } + if (secret.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = secret.Attributes.Value().RecoveryLevel.Value().ToString(); + } + } + if (secret.Managed.HasValue()) + { + Properties.Managed = secret.Managed.Value(); + } + if (secret.Tags.HasValue()) + { + Properties.Tags = std::unordered_map( + secret.Tags.Value().begin(), secret.Tags.Value().end()); + } + } + + KeyVaultSecret::KeyVaultSecret(_detail::Models::SecretItem const& secret) + { + if (secret.Id.HasValue()) + { + Id = secret.Id.Value(); + Properties = SecretProperties::CreateFromURL(secret.Id.Value()); + Name = Properties.Name; + } + if (secret.Tags.HasValue()) + { + Properties.Tags = std::unordered_map( + secret.Tags.Value().begin(), secret.Tags.Value().end()); + } + Properties.ContentType = secret.ContentType; + if (secret.Managed.HasValue()) + { + Properties.Managed = secret.Managed.Value(); + } + if (secret.Attributes.HasValue()) + { + Properties.ExpiresOn = secret.Attributes.Value().Expires; + Properties.NotBefore = secret.Attributes.Value().NotBefore; + Properties.Enabled = secret.Attributes.Value().Enabled; + Properties.CreatedOn = secret.Attributes.Value().Created; + Properties.UpdatedOn = secret.Attributes.Value().Updated; + if (secret.Attributes.Value().RecoverableDays.HasValue()) + { + Properties.RecoverableDays = secret.Attributes.Value().RecoverableDays.Value(); + } + if (secret.Attributes.Value().RecoveryLevel.HasValue()) + { + Properties.RecoveryLevel = secret.Attributes.Value().RecoveryLevel.Value().ToString(); + } + } + } + + _detail::Models::SecretSetParameters KeyVaultSecret::ToSetSecretParameters() const + { + _detail::Models::SecretSetParameters secretParameters; + if (Properties.ContentType.HasValue()) + { + secretParameters.ContentType = Properties.ContentType; + } + if (Value.HasValue()) + { + secretParameters.Value = Value.Value(); + } + + secretParameters.Tags + = std::map(Properties.Tags.begin(), Properties.Tags.end()); + + secretParameters.SecretAttributes = _detail::Models::SecretAttributes(); + if (Properties.Enabled.HasValue()) + { + secretParameters.SecretAttributes.Value().Enabled = Properties.Enabled; + } + if (Properties.NotBefore.HasValue()) + { + secretParameters.SecretAttributes.Value().NotBefore = Properties.NotBefore; + } + if (Properties.ExpiresOn.HasValue()) + { + secretParameters.SecretAttributes.Value().Expires = Properties.ExpiresOn; + } + if (Properties.CreatedOn.HasValue()) + { + secretParameters.SecretAttributes.Value().Created = Properties.CreatedOn; + } + if (Properties.UpdatedOn.HasValue()) + { + secretParameters.SecretAttributes.Value().Updated = Properties.UpdatedOn; + } + if (Properties.RecoverableDays.HasValue()) + { + secretParameters.SecretAttributes.Value().RecoverableDays + = static_cast(Properties.RecoverableDays.Value()); + } + if (Properties.RecoveryLevel.HasValue()) + { + secretParameters.SecretAttributes.Value().RecoveryLevel + = _detail::Models::DeletionRecoveryLevel(Properties.RecoveryLevel.Value()); + } + return secretParameters; + } +}}}} // namespace Azure::Security::KeyVault::Secrets \ No newline at end of file diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret_properties.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret_properties.cpp index a5288c558..59d534904 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret_properties.cpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secret_properties.cpp @@ -9,6 +9,8 @@ #include "azure/keyvault/secrets/keyvault_secret.hpp" #include "private/secret_serializers.hpp" +#include + using namespace Azure::Security::KeyVault::Secrets; SecretProperties SecretProperties::CreateFromURL(std::string const& url) @@ -20,3 +22,46 @@ SecretProperties SecretProperties::CreateFromURL(std::string const& url) _detail::SecretSerializer::ParseIDUrl(result, urlInstance.GetAbsoluteUrl()); return result; } + +_detail::Models::SecretUpdateParameters SecretProperties::ToSecretUpdateParameters() const +{ + _detail::Models::SecretUpdateParameters secretParameters; + if (ContentType.HasValue()) + { + secretParameters.ContentType = ContentType.Value(); + } + + secretParameters.Tags = std::map(Tags.begin(), Tags.end()); + secretParameters.SecretAttributes = _detail::Models::SecretAttributes(); + if (ExpiresOn.HasValue()) + { + secretParameters.SecretAttributes.Value().Expires = ExpiresOn; + } + if (NotBefore.HasValue()) + { + secretParameters.SecretAttributes.Value().NotBefore = NotBefore; + } + if (Enabled.HasValue()) + { + secretParameters.SecretAttributes.Value().Enabled = Enabled; + } + if (RecoveryLevel.HasValue()) + { + secretParameters.SecretAttributes.Value().RecoveryLevel + = _detail::Models::DeletionRecoveryLevel(RecoveryLevel.Value()); + } + if (RecoverableDays.HasValue()) + { + secretParameters.SecretAttributes.Value().RecoverableDays + = static_cast(RecoverableDays.Value()); + } + if (CreatedOn.HasValue()) + { + secretParameters.SecretAttributes.Value().Created = CreatedOn.Value(); + } + if (UpdatedOn.HasValue()) + { + secretParameters.SecretAttributes.Value().Updated = UpdatedOn.Value(); + } + return secretParameters; +} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secrets_common_request.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secrets_common_request.cpp deleted file mode 100644 index 65eda9bf6..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/keyvault_secrets_common_request.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "private/keyvault_secrets_common_request.hpp" - -#include -#include - -#include - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Core::Http::_internal; - -std::unique_ptr _detail::KeyVaultSecretsCommonRequest::SendRequest( - Azure::Core::Http::_internal::HttpPipeline const& pipeline, - Azure::Core::Http::Request& request, - Azure::Core::Context const& context) -{ - auto response = pipeline.Send(request, context); - auto responseCode = response->GetStatusCode(); - - switch (responseCode) - { - - // 200, 201, 202, 204 are accepted responses - case Azure::Core::Http::HttpStatusCode::Ok: - case Azure::Core::Http::HttpStatusCode::Created: - case Azure::Core::Http::HttpStatusCode::Accepted: - case Azure::Core::Http::HttpStatusCode::NoContent: - break; - default: - throw Azure::Core::RequestFailedException(response); - } - return response; -} - -Azure::Core::Http::Request _detail::KeyVaultSecretsCommonRequest::CreateRequest( - Azure::Core::Url url, - std::string const& apiVersion, - Azure::Core::Http::HttpMethod method, - std::vector const& path, - Azure::Core::IO::BodyStream* content) -{ - using namespace Azure::Core::Http; - Request request = content == nullptr ? Request(std::move(method), std::move(url)) - : Request(std::move(method), std::move(url), content); - - request.SetHeader(ContentHeaderName, ApplicationJsonValue); - request.GetUrl().AppendQueryParameter(ApiVersionQueryParamName, apiVersion); - - for (std::string const& p : path) - { - if (!p.empty()) - { - request.GetUrl().AppendPath(p); - } - } - return request; -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/private/generated_package_version.hpp b/sdk/keyvault/azure-security-keyvault-secrets/src/private/generated_package_version.hpp new file mode 100644 index 000000000..22d79e9af --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/private/generated_package_version.hpp @@ -0,0 +1,50 @@ +// 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 + +#define AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MAJOR 1 +#define AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MINOR 0 +#define AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PATCH 0 +#define AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PRERELEASE "beta.1" + +#define AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA_HELPER(i) #i +#define AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA(i) \ + AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA_HELPER(i) + +namespace Azure { + namespace Security { + namespace KeyVault { + namespace Secrets { + namespace Generated { + namespace _detail { + class PackageVersion final { + public: + static constexpr std::int32_t Major = AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MAJOR; + static constexpr std::int32_t Minor = AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MINOR; + static constexpr std::int32_t Patch = AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PATCH; + + static constexpr bool IsPreRelease + = sizeof(AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PRERELEASE) != sizeof(""); + + static constexpr const char* ToString() + { + return IsPreRelease + ? AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA(AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MAJOR) "." AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA( + AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MINOR) "." AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA(AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PATCH) "-" AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PRERELEASE + : AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA(AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MAJOR) "." AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA( + AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MINOR) "." AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA(AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PATCH); + } + }; +}}}}}} // namespace Azure::Security::KeyVault::Secrets::Generated::_detail + +#undef AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA_HELPER +#undef AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_ITOA +#undef AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MAJOR +#undef AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_MINOR +#undef AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PATCH +#undef AZURE_SECURITY_KEYVAULT_SECRETS_GENERATED_VERSION_PRERELEASE diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/private/keyvault_secrets_common_request.hpp b/sdk/keyvault/azure-security-keyvault-secrets/src/private/keyvault_secrets_common_request.hpp deleted file mode 100644 index 7e299e487..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/private/keyvault_secrets_common_request.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** - * @brief Provides a wrapper class for the Azure Core Pipeline for Secrets service. - * - */ - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail { - - constexpr static const char ContentHeaderName[] = "content-type"; - constexpr static const char ApplicationJsonValue[] = "application/json"; - constexpr static const char ApiVersionQueryParamName[] = "api-version"; - - struct KeyVaultSecretsCommonRequest final - { - static Azure::Core::Http::Request CreateRequest( - Azure::Core::Url url, - std::string const& apiVersion, - Azure::Core::Http::HttpMethod method, - std::vector const& path, - Azure::Core::IO::BodyStream* content); - - static std::unique_ptr SendRequest( - Azure::Core::Http::_internal::HttpPipeline const& pipeline, - Azure::Core::Http::Request& request, - Azure::Core::Context const& context); - }; - -}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/private/package_version.hpp b/sdk/keyvault/azure-security-keyvault-secrets/src/private/package_version.hpp index db7877c54..97b28a400 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/private/package_version.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/private/package_version.hpp @@ -1,55 +1,31 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -/** - * @file - * @brief Provides version information. - */ +// 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 -#define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MAJOR 4 -#define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MINOR 3 +#define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MAJOR 1 +#define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MINOR 0 #define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PATCH 0 -#define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PRERELEASE "beta.3" +#define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PRERELEASE "beta.1" #define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_ITOA_HELPER(i) #i #define AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_ITOA(i) \ AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_ITOA_HELPER(i) namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail { - /** - * @brief Provides version information. - */ class PackageVersion final { public: - /** - * @brief Major numeric identifier. - */ - static constexpr int32_t Major = AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MAJOR; + static constexpr std::int32_t Major = AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MAJOR; + static constexpr std::int32_t Minor = AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MINOR; + static constexpr std::int32_t Patch = AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PATCH; - /** - * @brief Minor numeric identifier. - */ - static constexpr int32_t Minor = AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MINOR; - - /** - * @brief Patch numeric identifier. - */ - static constexpr int32_t Patch = AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PATCH; - - /** - * @brief Indicates whether the SDK is in a pre-release state. - */ static constexpr bool IsPreRelease = sizeof(AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PRERELEASE) != sizeof(""); - /** - * @brief The version in string format used for telemetry following the `semver.org` standard - * (https://semver.org). - */ static constexpr const char* ToString() { return IsPreRelease @@ -63,7 +39,6 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { #undef AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_ITOA_HELPER #undef AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_ITOA - #undef AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MAJOR #undef AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_MINOR #undef AZURE_SECURITY_KEYVAULT_SECRETS_VERSION_PATCH diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/private/secret_serializers.hpp b/sdk/keyvault/azure-security-keyvault-secrets/src/private/secret_serializers.hpp index b76ee8209..7bc5c7307 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/private/secret_serializers.hpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/private/secret_serializers.hpp @@ -24,20 +24,6 @@ using namespace Azure::Security::KeyVault::Secrets; namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail { struct SecretSerializer final { - // Creates a new key based on a name and an HTTP raw response. - static KeyVaultSecret Deserialize( - std::string const& name, - Azure::Core::Http::RawResponse const& rawResponse); - - // Create from HTTP raw response only. - static KeyVaultSecret Deserialize(Azure::Core::Http::RawResponse const& rawResponse); - - // Updates a Key based on an HTTP raw response. - static void Deserialize(KeyVaultSecret& key, Azure::Core::Http::RawResponse const& rawResponse); - - // Serializes a key vault secret for set action - static std::string Serialize(KeyVaultSecret const& parameters); - // Extract the host out of the URL (with port if available) static std::string GetUrlAuthorityWithScheme(Azure::Core::Url const& url) { @@ -84,47 +70,4 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { } } }; - - struct DeletedSecretSerializer final - { - // Creates a new deleted secret based on a name and an HTTP raw response. - static DeletedSecret Deserialize( - std::string const& name, - Azure::Core::Http::RawResponse const& rawResponse); - - // Create deleted secret from HTTP raw response only. - static DeletedSecret Deserialize(Azure::Core::Http::RawResponse const& rawResponse); - - // Updates a deleted secret based on an HTTP raw response. - static void Deserialize( - DeletedSecret& secret, - Azure::Core::Http::RawResponse const& rawResponse); - }; - - struct SecretPropertiesSerializer final - { - static std::string Serialize(SecretProperties const& properties); - }; - - struct BackupSecretSerializer final - { - static BackupSecretResult Deserialize(Azure::Core::Http::RawResponse const& rawResponse); - }; - - struct RestoreSecretSerializer final - { - static std::string Serialize(std::vector const& backup); - }; - - struct SecretPropertiesPagedResultSerializer final - { - static SecretPropertiesPagedResponse Deserialize( - Azure::Core::Http::RawResponse const& rawResponse); - }; - - struct DeletedSecretPagedResultSerializer final - { - static DeletedSecretPagedResponse Deserialize( - Azure::Core::Http::RawResponse const& rawResponse); - }; }}}}} // namespace Azure::Security::KeyVault::Secrets::_detail diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/secret_client.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/secret_client.cpp index aba14d2c7..ebf884122 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/secret_client.cpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/secret_client.cpp @@ -8,9 +8,9 @@ #include "azure/keyvault/secrets/secret_client.hpp" +#include "azure/keyvault/secrets/generated.hpp" #include "azure/keyvault/secrets/keyvault_operations.hpp" #include "private/keyvault_protocol.hpp" -#include "private/keyvault_secrets_common_request.hpp" #include "private/package_version.hpp" #include "private/secret_constants.hpp" #include "private/secret_serializers.hpp" @@ -29,63 +29,21 @@ using namespace Azure::Core::Http::Policies; using namespace Azure::Core::Http::Policies::_internal; using namespace Azure::Security::KeyVault::Secrets::_detail; -std::unique_ptr SecretClient::SendRequest( - Azure::Core::Http::Request& request, - Azure::Core::Context const& context) const -{ - return KeyVaultSecretsCommonRequest::SendRequest(*m_pipeline, request, context); -} - -Request SecretClient::CreateRequest( - HttpMethod method, - std::vector const& path, - Azure::Core::IO::BodyStream* content) const -{ - return KeyVaultSecretsCommonRequest::CreateRequest( - m_vaultUrl, m_apiVersion, method, path, content); -} - -Request SecretClient::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); -} - SecretClient::SecretClient( std::string const& vaultUrl, std::shared_ptr credential, SecretClientOptions options) - : m_vaultUrl(vaultUrl), m_apiVersion(options.ApiVersion) { - auto apiVersion = options.ApiVersion; - Azure::Core::Url url(vaultUrl); - - std::vector> perRetryPolicies; - { - Azure::Core::Credentials::TokenRequestContext tokenContext; - tokenContext.Scopes = {_internal::UrlScope::GetScopeFromUrl(url)}; - - perRetryPolicies.emplace_back( - std::make_unique<_internal::KeyVaultChallengeBasedAuthenticationPolicy>( - credential, tokenContext)); - } - - std::vector> perCallPolicies; - - m_pipeline = std::make_shared( - options, - KeyVaultServicePackageName, - PackageVersion::ToString(), - std::move(perRetryPolicies), - std::move(perCallPolicies)); + _detail::KeyVaultClientOptions generatedOptions; + generatedOptions.ApiVersion = options.ApiVersion; + generatedOptions.Log = options.Log; + generatedOptions.Retry = options.Retry; + generatedOptions.Transport = options.Transport; + generatedOptions.Telemetry = options.Telemetry; + generatedOptions.PerOperationPolicies = std::move(options.PerOperationPolicies); + generatedOptions.PerRetryPolicies = std::move(options.PerRetryPolicies); + m_client = std::make_shared<_detail::KeyVaultClient>( + _detail::KeyVaultClient(vaultUrl, credential, generatedOptions)); } Azure::Response SecretClient::GetSecret( @@ -93,24 +51,20 @@ Azure::Response SecretClient::GetSecret( GetSecretOptions const& options, Azure::Core::Context const& context) const { - auto request = CreateRequest(HttpMethod::Get, {_detail::SecretPath, name, options.Version}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::SecretSerializer::Deserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto secret = m_client->GetSecret(name, options.Version.empty() ? "/" : options.Version, context); + KeyVaultSecret secretResult(secret.Value); + secretResult.Properties.VaultUrl = m_vaultUrl.GetAbsoluteUrl(); + return Azure::Response(std::move(secretResult), std::move(secret.RawResponse)); } Azure::Response SecretClient::GetDeletedSecret( std::string const& name, Azure::Core::Context const& context) const { - auto request = CreateRequest(HttpMethod::Get, {_detail::DeletedSecretPath, name}); - - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::DeletedSecretSerializer::Deserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->GetDeletedSecret(name, context); + DeletedSecret secretResult(response.Value); + secretResult.Properties.VaultUrl = m_vaultUrl.GetAbsoluteUrl(); + return Azure::Response(std::move(secretResult), std::move(response.RawResponse)); } Azure::Response SecretClient::SetSecret( @@ -118,8 +72,11 @@ Azure::Response SecretClient::SetSecret( std::string const& value, Azure::Core::Context const& context) const { - KeyVaultSecret setParameters(name, value); - return SetSecret(name, setParameters, context); + _detail::Models::SecretSetParameters secretParameters; + secretParameters.Value = value; + auto response = m_client->SetSecret(name, secretParameters, context); + KeyVaultSecret secretResult(response.Value); + return Azure::Response(std::move(secretResult), std::move(response.RawResponse)); } Azure::Response SecretClient::SetSecret( @@ -127,97 +84,75 @@ Azure::Response SecretClient::SetSecret( KeyVaultSecret const& secret, Azure::Core::Context const& context) const { - auto payload = _detail::SecretSerializer::Serialize(secret); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - auto request = CreateRequest(HttpMethod::Put, {_detail::SecretPath, name}, &payloadStream); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::SecretSerializer::Deserialize(name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + _detail::Models::SecretSetParameters secretParameters = secret.ToSetSecretParameters(); + auto response = m_client->SetSecret(name, secretParameters, context); + KeyVaultSecret secretResult(response.Value); + return Azure::Response(std::move(secretResult), std::move(response.RawResponse)); } Azure::Response SecretClient::UpdateSecretProperties( SecretProperties const& properties, Azure::Core::Context const& context) const { - auto payload = _detail::SecretPropertiesSerializer::Serialize(properties); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - auto request = CreateRequest( - HttpMethod::Patch, - {_detail::SecretPath, properties.Name, properties.Version}, - &payloadStream); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::SecretSerializer::Deserialize(properties.Name, *rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + _detail::Models::SecretUpdateParameters secretParameters = properties.ToSecretUpdateParameters(); + auto response + = m_client->UpdateSecret(properties.Name, properties.Version, secretParameters, context); + KeyVaultSecret secretResult(response.Value); + return Azure::Response(std::move(secretResult), std::move(response.RawResponse)); } Azure::Response SecretClient::BackupSecret( std::string const& name, Azure::Core::Context const& context) const { - auto request - = CreateRequest(HttpMethod::Post, {_detail::SecretPath, name, _detail::BackupSecretPath}); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::BackupSecretSerializer::Deserialize(*rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->BackupSecret(name, context); + BackupSecretResult backupResult; + backupResult.Secret = std::move(response.Value.Value.Value()); + return Azure::Response( + std::move(backupResult), std::move(response.RawResponse)); } Azure::Response SecretClient::RestoreSecretBackup( BackupSecretResult const& backup, Azure::Core::Context const& context) const { - auto payload = _detail::RestoreSecretSerializer::Serialize(backup.Secret); - Azure::Core::IO::MemoryBodyStream payloadStream( - reinterpret_cast(payload.data()), payload.size()); - - auto request = CreateRequest( - HttpMethod::Post, {_detail::SecretPath, _detail::RestoreSecretPath}, &payloadStream); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::SecretSerializer::Deserialize(*rawResponse); - return Azure::Response(std::move(value), std::move(rawResponse)); + _detail::Models::SecretRestoreParameters restoreParameters; + restoreParameters.SecretBundleBackup = backup.Secret; + auto response = m_client->RestoreSecret(restoreParameters, context); + KeyVaultSecret secretResult(response.Value); + return Azure::Response(std::move(secretResult), std::move(response.RawResponse)); } Azure::Response SecretClient::PurgeDeletedSecret( std::string const& name, Azure::Core::Context const& context) const { - auto request = CreateRequest(HttpMethod::Delete, {_detail::DeletedSecretPath, name}); - // Send and parse response - auto rawResponse = SendRequest(request, context); - PurgedSecret value; - return Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->PurgeDeletedSecret(name, context); + PurgedSecret purgedResult; + return Azure::Response(std::move(purgedResult), std::move(response.RawResponse)); } Azure::Security::KeyVault::Secrets::DeleteSecretOperation SecretClient::StartDeleteSecret( std::string const& name, Azure::Core::Context const& context) const { - auto request = CreateRequest(HttpMethod::Delete, {_detail::SecretPath, name}); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::DeletedSecretSerializer::Deserialize(name, *rawResponse); - auto responseT = Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->DeleteSecret(name, context); + DeletedSecret value(response.Value); + auto responseT + = Azure::Response(std::move(value), std::move(response.RawResponse)); + return DeleteSecretOperation(std::make_shared(*this), std::move(responseT)); } Azure::Security::KeyVault::Secrets::RecoverDeletedSecretOperation SecretClient:: StartRecoverDeletedSecret(std::string const& name, Azure::Core::Context const& context) const { - auto request = CreateRequest( - HttpMethod::Post, {_detail::DeletedSecretPath, name, _detail::RecoverDeletedSecretPath}); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto parsedResponse = _detail::SecretSerializer::Deserialize(name, *rawResponse); - - auto value = parsedResponse.Properties; - auto responseT = Azure::Response(std::move(value), std::move(rawResponse)); + auto response = m_client->RecoverDeletedSecret(name, context); + KeyVaultSecret value(response.Value); + value.Name = name; + value.Properties.Name = name; + auto responseT = Azure::Response( + std::move(value.Properties), std::move(response.RawResponse)); return RecoverDeletedSecretOperation(std::make_shared(*this), std::move(responseT)); } @@ -225,14 +160,16 @@ SecretPropertiesPagedResponse SecretClient::GetPropertiesOfSecrets( GetPropertiesOfSecretsOptions const& options, Azure::Core::Context const& context) const { - // Request and settings - auto request = ContinuationTokenRequest({SecretPath}, options.NextPageToken); + _detail::KeyVaultClientGetSecretsOptions generatedOptions; + if (options.NextPageToken.HasValue()) + { + generatedOptions.NextPageToken = options.NextPageToken.Value(); + } + auto response = m_client->GetSecrets(generatedOptions, context); + SecretPropertiesPagedResponse secretPropertiesPagedResponse( + response, std::move(response.RawResponse), std::make_unique(*this)); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::SecretPropertiesPagedResultSerializer::Deserialize(*rawResponse); - return SecretPropertiesPagedResponse( - std::move(value), std::move(rawResponse), std::make_unique(*this)); + return secretPropertiesPagedResponse; } SecretPropertiesPagedResponse SecretClient::GetPropertiesOfSecretsVersions( @@ -240,29 +177,31 @@ SecretPropertiesPagedResponse SecretClient::GetPropertiesOfSecretsVersions( GetPropertiesOfSecretVersionsOptions const& options, Azure::Core::Context const& context) const { - // Request and settings - auto request = ContinuationTokenRequest( - {_detail::SecretPath, name, _detail::VersionsName}, options.NextPageToken); + _detail::KeyVaultClientGetSecretVersionsOptions generatedOptions; + if (options.NextPageToken.HasValue()) + { + generatedOptions.NextPageToken = options.NextPageToken.Value(); + } + auto response = m_client->GetSecretVersions(name, generatedOptions, context); + SecretPropertiesPagedResponse secretPropertiesPagedResponse( + response, std::move(response.RawResponse), std::make_unique(*this), name); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::SecretPropertiesPagedResultSerializer::Deserialize(*rawResponse); - return SecretPropertiesPagedResponse( - std::move(value), std::move(rawResponse), std::make_unique(*this), name); + return secretPropertiesPagedResponse; } DeletedSecretPagedResponse SecretClient::GetDeletedSecrets( GetDeletedSecretsOptions const& options, Azure::Core::Context const& context) const { - // Request and settings - auto request = ContinuationTokenRequest({_detail::DeletedSecretPath}, options.NextPageToken); + _detail::KeyVaultClientGetDeletedSecretsOptions generatedOptions; + if (options.NextPageToken.HasValue()) + { + generatedOptions.NextPageToken = options.NextPageToken.Value(); + } + _detail::GetDeletedSecretsPagedResponse response + = m_client->GetDeletedSecrets(generatedOptions, context); + DeletedSecretPagedResponse deletedSecretPagedResponse( + response, std::move(response.RawResponse), std::make_unique(*this)); - // Send and parse response - auto rawResponse = SendRequest(request, context); - auto value = _detail::DeletedSecretPagedResultSerializer::Deserialize(*rawResponse); - return DeletedSecretPagedResponse( - std::move(value), std::move(rawResponse), std::make_unique(*this)); + return deletedSecretPagedResponse; } - -std::string SecretClient::GetUrl() const { return m_vaultUrl.GetAbsoluteUrl(); } diff --git a/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp b/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp index 4f9e2a098..8c248ac61 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/src/secret_serializers.cpp @@ -20,406 +20,3 @@ using namespace Azure::Core::Json::_internal; using Azure::Core::_internal::PosixTimeConverter; using namespace Azure::Security::KeyVault::Secrets; using namespace Azure::Security::KeyVault::Secrets::_detail; - -// Creates a new key based on a name and an HTTP raw response. -KeyVaultSecret SecretSerializer::Deserialize( - std::string const& name, - Azure::Core::Http::RawResponse const& rawResponse) -{ - KeyVaultSecret secret; - secret.Name = name; - _detail::SecretSerializer::Deserialize(secret, rawResponse); - return secret; -} - -// Create from HTTP raw response only. -KeyVaultSecret SecretSerializer::Deserialize(Azure::Core::Http::RawResponse const& rawResponse) -{ - KeyVaultSecret secret; - _detail::SecretSerializer::Deserialize(secret, rawResponse); - return secret; -} - -// Updates a Key based on an HTTP raw response. -void SecretSerializer::Deserialize( - KeyVaultSecret& secret, - Azure::Core::Http::RawResponse const& rawResponse) -{ - auto const& body = rawResponse.GetBody(); - auto jsonParser = json::parse(body); - - secret.Id = jsonParser[_detail::IdPropertyName]; - secret.Properties.Id = secret.Id; - - ParseIDUrl(secret.Properties, secret.Id); - if (!secret.Properties.Name.empty()) - { - secret.Name = secret.Properties.Name; - } - else - { - secret.Properties.Name = secret.Name; - } - // Parse URL for the various attributes - if (jsonParser.contains(_detail::AttributesPropertyName)) - { - auto attributes = jsonParser[_detail::AttributesPropertyName]; - - JsonOptional::SetIfExists(secret.Properties.Enabled, attributes, _detail::EnabledPropertyName); - - JsonOptional::SetIfExists( - secret.Properties.NotBefore, - attributes, - _detail::NbfPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - secret.Properties.ExpiresOn, - attributes, - _detail::ExpPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - secret.Properties.CreatedOn, - attributes, - _detail::CreatedPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - secret.Properties.UpdatedOn, - attributes, - _detail::UpdatedPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - secret.Properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName); - JsonOptional::SetIfExists( - secret.Properties.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName); - } - - // "Tags" - if (jsonParser.contains(_detail::TagsPropertyName)) - { - auto const& tags = jsonParser[_detail::TagsPropertyName]; - { - for (auto tag = tags.begin(); tag != tags.end(); ++tag) - { - secret.Properties.Tags.emplace(tag.key(), tag.value().get()); - } - } - } - - // managed - if (jsonParser.contains(_detail::ManagedPropertyName)) - { - secret.Properties.Managed = jsonParser[_detail::ManagedPropertyName].get(); - } - - // value - if (jsonParser.contains(_detail::ValuePropertyName)) - { - secret.Value = jsonParser[_detail::ValuePropertyName]; - } - - // key id - JsonOptional::SetIfExists( - secret.Properties.KeyId, jsonParser, _detail::KeyIdPropertyName); - - // content type - JsonOptional::SetIfExists( - secret.Properties.ContentType, jsonParser, _detail::ContentTypePropertyName); -} - -DeletedSecret DeletedSecretSerializer::Deserialize( - std::string const& name, - Azure::Core::Http::RawResponse const& rawResponse) -{ - DeletedSecret deletedSecret(name); - Deserialize(deletedSecret, rawResponse); - return deletedSecret; -} - -// Create deleted secret from HTTP raw response only. -DeletedSecret DeletedSecretSerializer::Deserialize( - Azure::Core::Http::RawResponse const& rawResponse) -{ - DeletedSecret deletedSecret; - Deserialize(deletedSecret, rawResponse); - return deletedSecret; -} - -// Updates a deleted secret based on an HTTP raw response. -void DeletedSecretSerializer::Deserialize( - DeletedSecret& secret, - Azure::Core::Http::RawResponse const& rawResponse) -{ - SecretSerializer::Deserialize(secret, rawResponse); - - auto const& body = rawResponse.GetBody(); - auto jsonParser = json::parse(body); - - secret.RecoveryId = jsonParser[_detail::RecoveryIdPropertyName]; - secret.ScheduledPurgeDate = PosixTimeConverter::PosixTimeToDateTime( - jsonParser[_detail::ScheduledPurgeDatePropertyName]); - secret.DeletedOn - = PosixTimeConverter::PosixTimeToDateTime(jsonParser[_detail::DeletedDatePropertyName]); -} - -// serializes a set secret parameters object -std::string SecretSerializer::Serialize(KeyVaultSecret const& parameters) -{ - json payload; - - JsonOptional::SetFromNullable(parameters.Value, payload, _detail::ValuePropertyName); - - JsonOptional::SetFromNullable( - parameters.Properties.ContentType, payload, _detail::ContentTypePropertyName); - - json attributes; - - JsonOptional::SetFromNullable( - parameters.Properties.CreatedOn, - attributes, - _detail::CreatedPropertyName, - PosixTimeConverter::DateTimeToPosixTime); - JsonOptional::SetFromNullable( - parameters.Properties.Enabled, attributes, _detail::EnabledPropertyName); - JsonOptional::SetFromNullable( - parameters.Properties.ExpiresOn, - attributes, - _detail::ExpPropertyName, - PosixTimeConverter::DateTimeToPosixTime); - JsonOptional::SetFromNullable( - parameters.Properties.NotBefore, - attributes, - _detail::NbfPropertyName, - PosixTimeConverter::DateTimeToPosixTime); - JsonOptional::SetFromNullable( - parameters.Properties.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName); - JsonOptional::SetFromNullable( - parameters.Properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName); - JsonOptional::SetFromNullable( - parameters.Properties.UpdatedOn, - attributes, - _detail::UpdatedPropertyName, - PosixTimeConverter::DateTimeToPosixTime); - - // optional tags - attributes[TagsPropertyName] = json(parameters.Properties.Tags); - - payload[AttributesPropertyName] = attributes; - - return payload.dump(); -} - -std::string SecretPropertiesSerializer::Serialize(SecretProperties const& properties) -{ - json payload; - - // content type - JsonOptional::SetFromNullable(properties.ContentType, payload, _detail::ContentTypePropertyName); - - // optional tags - payload[TagsPropertyName] = json(properties.Tags); - - // attributes - json attributes; - - JsonOptional::SetFromNullable( - properties.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName); - JsonOptional::SetFromNullable( - properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName); - JsonOptional::SetFromNullable(properties.Enabled, attributes, _detail::EnabledPropertyName); - JsonOptional::SetFromNullable( - properties.NotBefore, - attributes, - _detail::NbfPropertyName, - PosixTimeConverter::DateTimeToPosixTime); - JsonOptional::SetFromNullable( - properties.ExpiresOn, - attributes, - _detail::ExpPropertyName, - PosixTimeConverter::DateTimeToPosixTime); - - payload[AttributesPropertyName] = attributes; - - return payload.dump(); -} - -BackupSecretResult BackupSecretSerializer::Deserialize( - Azure::Core::Http::RawResponse const& rawResponse) -{ - auto const& body = rawResponse.GetBody(); - auto jsonParser = json::parse(body); - auto encodedResult = jsonParser[_detail::ValuePropertyName].get(); - BackupSecretResult data; - data.Secret = Base64Url::Base64UrlDecode(encodedResult); - - return data; -} - -std::string RestoreSecretSerializer::Serialize(std::vector const& backup) -{ - json payload; - payload[_detail::ValuePropertyName] = Base64Url::Base64UrlEncode(backup); - return payload.dump(); -} - -SecretPropertiesPagedResponse SecretPropertiesPagedResultSerializer::Deserialize( - Azure::Core::Http::RawResponse const& rawResponse) -{ - SecretPropertiesPagedResponse result; - auto const& body = rawResponse.GetBody(); - auto jsonParser = json::parse(body); - - JsonOptional::SetIfExists(result.NextPageToken, jsonParser, "nextLink"); - - // Key properties - auto secretsPropertiesJson = jsonParser["value"]; - - for (auto const& secretProperties : secretsPropertiesJson) - { - SecretProperties item; - item.Id = secretProperties[_detail::IdPropertyName].get(); - _detail::SecretSerializer::ParseIDUrl(item, item.Id); - // Parse URL for the various attributes - if (secretProperties.contains(_detail::AttributesPropertyName)) - { - auto attributes = secretProperties[_detail::AttributesPropertyName]; - - JsonOptional::SetIfExists(item.Enabled, attributes, _detail::EnabledPropertyName); - - JsonOptional::SetIfExists( - item.NotBefore, - attributes, - _detail::NbfPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.ExpiresOn, - attributes, - _detail::ExpPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.CreatedOn, - attributes, - _detail::CreatedPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.UpdatedOn, - attributes, - _detail::UpdatedPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName); - JsonOptional::SetIfExists( - item.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName); - } - - // "Tags" - if (secretProperties.contains(_detail::TagsPropertyName)) - { - auto const& tags = secretProperties[_detail::TagsPropertyName]; - { - for (auto tag = tags.begin(); tag != tags.end(); ++tag) - { - item.Tags.emplace(tag.key(), tag.value().get()); - } - } - } - - // managed - if (secretProperties.contains(_detail::ManagedPropertyName)) - { - item.Managed = secretProperties[_detail::ManagedPropertyName].get(); - } - - // content type - JsonOptional::SetIfExists( - item.ContentType, secretProperties, _detail::ContentTypePropertyName); - result.Items.emplace_back(item); - } - - return result; -} - -DeletedSecretPagedResponse DeletedSecretPagedResultSerializer::Deserialize( - Azure::Core::Http::RawResponse const& rawResponse) -{ - - DeletedSecretPagedResponse result; - auto const& body = rawResponse.GetBody(); - auto jsonParser = json::parse(body); - auto string = jsonParser.dump(); - JsonOptional::SetIfExists(result.NextPageToken, jsonParser, "nextLink"); - - // Key properties - auto secretsPropertiesJson = jsonParser["value"]; - - for (auto const& secretProperties : secretsPropertiesJson) - { - DeletedSecret item; - item.Id = secretProperties[_detail::IdPropertyName].get(); - _detail::SecretSerializer::ParseIDUrl(item.Properties, item.Id); - item.Name = item.Properties.Name; - // Parse URL for the various attributes - if (secretProperties.contains(_detail::AttributesPropertyName)) - { - auto attributes = secretProperties[_detail::AttributesPropertyName]; - - JsonOptional::SetIfExists(item.Properties.Enabled, attributes, _detail::EnabledPropertyName); - - JsonOptional::SetIfExists( - item.Properties.NotBefore, - attributes, - _detail::NbfPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.Properties.ExpiresOn, - attributes, - _detail::ExpPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.Properties.CreatedOn, - attributes, - _detail::CreatedPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.Properties.UpdatedOn, - attributes, - _detail::UpdatedPropertyName, - PosixTimeConverter::PosixTimeToDateTime); - JsonOptional::SetIfExists( - item.Properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName); - JsonOptional::SetIfExists( - item.Properties.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName); - } - - // "Tags" - if (secretProperties.contains(_detail::TagsPropertyName)) - { - auto const& tags = secretProperties[_detail::TagsPropertyName]; - { - for (auto tag = tags.begin(); tag != tags.end(); ++tag) - { - item.Properties.Tags.emplace(tag.key(), tag.value().get()); - } - } - } - - // managed - if (secretProperties.contains(_detail::ManagedPropertyName)) - { - item.Properties.Managed = secretProperties[_detail::ManagedPropertyName].get(); - } - - // content type - JsonOptional::SetIfExists( - item.Properties.ContentType, secretProperties, _detail::ContentTypePropertyName); - - item.RecoveryId = secretProperties[_detail::RecoveryIdPropertyName]; - item.ScheduledPurgeDate = PosixTimeConverter::PosixTimeToDateTime( - secretProperties[_detail::ScheduledPurgeDatePropertyName]); - item.DeletedOn = PosixTimeConverter::PosixTimeToDateTime( - secretProperties[_detail::DeletedDatePropertyName]); - - result.Items.emplace_back(item); - } - - return result; -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/CMakeLists.txt b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/CMakeLists.txt index 9d3402d94..34dc08442 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/CMakeLists.txt +++ b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/CMakeLists.txt @@ -18,16 +18,8 @@ add_executable ( azure-security-keyvault-secrets-test challenge_based_authentication_policy_test.cpp macro_guard.cpp - secret_backup_deserialize_test.cpp - secret_backup_deserialize_test.hpp secret_client_base_test.hpp secret_client_test.cpp - secret_get_client_deserialize_test.cpp - secret_get_client_deserialize_test.hpp - secret_paged_deserialize_test.cpp - secret_paged_deserialize_test.hpp - secret_set_parameters_serializer_test.cpp - secret_update_properties_test.cpp ) target_compile_definitions(azure-security-keyvault-secrets-test PRIVATE _azure_BUILDING_TESTS) diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_backup_deserialize_test.cpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_backup_deserialize_test.cpp deleted file mode 100644 index 4737b5e19..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_backup_deserialize_test.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "secret_backup_deserialize_test.hpp" - -#include "../src/private/secret_serializers.hpp" -#include "azure/keyvault/secrets/secret_client.hpp" - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Security::KeyVault::Secrets::_test; -using namespace Azure::Security::KeyVault::Secrets::_detail; -using namespace Azure::Core::Json::_internal; -TEST(BackupSecretSerializer, EmptyValue) -{ - auto response = BackupHelpers::GetEmptyResponse(); - - auto secret = _detail::BackupSecretSerializer::Deserialize(response); - - EXPECT_EQ(secret.Secret.size(), size_t(0)); -} - -TEST(BackupSecretSerializer, FullValue) -{ - auto response = BackupHelpers::GetFullResponse(); - - auto secret = _detail::BackupSecretSerializer::Deserialize(response); - - EXPECT_EQ(secret.Secret.size(), size_t(10)); - std::string str(secret.Secret.begin(), secret.Secret.end()); - EXPECT_EQ(str, "my name is"); -} - -TEST(RestoreSecretSerializer, EmptyValue) -{ - std::string str = ""; - auto data = std::vector(str.begin(), str.end()); - auto secret = _detail::RestoreSecretSerializer::Serialize(data); - auto jsonParser = json::parse(secret); - - EXPECT_EQ(secret.size(), size_t(12)); - EXPECT_EQ(jsonParser["value"].get().empty(), true); -} - -TEST(RestoreSecretSerializer, SomeValue) -{ - std::string str = "my name is"; - - auto data = std::vector(str.begin(), str.end()); - auto secret = _detail::RestoreSecretSerializer::Serialize(data); - auto jsonParser = json::parse(secret); - - EXPECT_EQ(secret.size(), size_t(26)); - // cspell: disable-next-line - EXPECT_EQ(jsonParser["value"], "bXkgbmFtZSBpcw"); -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_backup_deserialize_test.hpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_backup_deserialize_test.hpp deleted file mode 100644 index c76f0a9d7..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_backup_deserialize_test.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp" -#include "azure/keyvault/secrets/keyvault_secret.hpp" - -#include -#include - -#include - -#include - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Core::Http::_internal; - -namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _test { - struct BackupHelpers - { - static Azure::Core::Http::RawResponse GetEmptyResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "value": "" - } -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetFullResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - // cspell: disable-next-line - constexpr static const uint8_t responseBody[] = R"json({"value": "bXkgbmFtZSBpcw=="})json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetIncorrectResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "value": "my name is" - } -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - }; -}}}}} // namespace Azure::Security::KeyVault::Secrets::_test diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_client_test.cpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_client_test.cpp index 78b3d9755..e3fa65f53 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_client_test.cpp +++ b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_client_test.cpp @@ -33,7 +33,7 @@ TEST(SecretClient, ServiceVersion) // Default - 7.5 EXPECT_NO_THROW(auto options = SecretClientOptions(); SecretClient SecretClient("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 = SecretClientOptions(); options.ApiVersion = "7.4"; @@ -115,7 +115,7 @@ TEST_F(KeyVaultSecretClientTest, SecondCreateTest) } } -TEST_F(KeyVaultSecretClientTest, DISABLED_UpdateTest) +TEST_F(KeyVaultSecretClientTest, UpdateTest) { auto secretName = "UpdateTest"; SecretProperties properties; @@ -135,17 +135,15 @@ TEST_F(KeyVaultSecretClientTest, DISABLED_UpdateTest) auto secret = secretResponse.Value; properties = secret.Properties; EXPECT_EQ(secret.Value.Value(), secretValue); - EXPECT_EQ(properties.Name, secretName); } { - properties.ContentType = "xyz"; - UpdateSecretPropertiesOptions options; - auto props = properties; + properties.RecoverableDays = 90; + properties.Name = secretName; + properties.Version = "/"; auto secretResponse = client.UpdateSecretProperties(properties); CheckValidResponse(secretResponse); auto secret = secretResponse.Value; - EXPECT_EQ(secret.Properties.Name, secretName); - EXPECT_EQ(secret.Properties.ContentType.Value(), properties.ContentType.Value()); + EXPECT_EQ(secret.Properties.RecoverableDays.Value(), 90); } { auto operation = client.StartDeleteSecret(secretName); @@ -184,7 +182,7 @@ TEST_F(KeyVaultSecretClientTest, BackupRestore) auto deletedSecretResponse = client.GetDeletedSecret(secretName); CheckValidResponse(deletedSecretResponse); auto secret = deletedSecretResponse.Value; - EXPECT_EQ(secret.Name, secretName); + EXPECT_EQ(secret.Properties.RecoverableDays.Value(), 90); } { auto purgedResponse = client.PurgeDeletedSecret(secretName); @@ -221,7 +219,7 @@ TEST_F(KeyVaultSecretClientTest, BackupRestore) auto restore = client.RestoreSecretBackup(backupData); CheckValidResponse(restore); auto restored = restore.Value; - EXPECT_TRUE(restored.Id.length() > 0); + EXPECT_EQ(restored.Properties.RecoverableDays.Value(), 90); } } @@ -262,8 +260,7 @@ TEST_F(KeyVaultSecretClientTest, RecoverSecret) auto operationResult = operation.Value(); auto restoredSecret = client.GetSecret(secretName); auto secret = restoredSecret.Value; - EXPECT_EQ(secret.Name, secretName); - EXPECT_EQ(operationResult.Name, secretName); + EXPECT_EQ(operationResult.RecoverableDays.Value(), secret.Properties.RecoverableDays.Value()); EXPECT_EQ(operation.GetRawResponse().GetStatusCode(), Azure::Core::Http::HttpStatusCode::Ok); } } @@ -281,7 +278,6 @@ TEST_F(KeyVaultSecretClientTest, TestGetPropertiesOfSecret) auto secretResponse = client.SetSecret(name, "secretValue"); CheckValidResponse(secretResponse); auto secret = secretResponse.Value; - EXPECT_EQ(secret.Name, name); // Avoid server Throttled while creating keys TestSleep(); } @@ -299,3 +295,14 @@ TEST_F(KeyVaultSecretClientTest, TestGetPropertiesOfSecret) EXPECT_TRUE(secretProps.size() >= static_cast(capacity)); } + +TEST(SecretProperties, FactoryValid) +{ + std::string url( + "https://myvault.vault.azure.net/secrets/my_secret_name/4387e9f3d6e14c459867679a90fd0f79"); + SecretProperties props = SecretProperties::CreateFromURL(url); + EXPECT_EQ(props.Name, "my_secret_name"); + EXPECT_EQ(props.Version, "4387e9f3d6e14c459867679a90fd0f79"); + EXPECT_EQ(props.Id, url); + EXPECT_EQ(props.VaultUrl, "https://myvault.vault.azure.net"); +} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_get_client_deserialize_test.cpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_get_client_deserialize_test.cpp deleted file mode 100644 index 87a09f1a9..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_get_client_deserialize_test.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "secret_get_client_deserialize_test.hpp" - -#include "../src/private/secret_serializers.hpp" -#include "azure/keyvault/secrets/secret_client.hpp" - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Security::KeyVault::Secrets::_test; -using namespace Azure::Security::KeyVault::Secrets::_detail; - -TEST(KeyVaultSecretSerializer, GetClientDeserializePartial1) -{ - auto response = Helpers::GetPartialResponse(); - - KeyVaultSecret secret = _detail::SecretSerializer::Deserialize(response); - Helpers::RunPartialExpect(secret); -} - -TEST(KeyVaultSecretSerializer, GetClientDeserializePartial2) -{ - auto response = Helpers::GetPartialResponse(); - - KeyVaultSecret secret = _detail::SecretSerializer::Deserialize("name1", response); - - Helpers::RunPartialExpect(secret); -} - -TEST(KeyVaultSecretSerializer, GetClientDeserializePartial3) -{ - auto response = Helpers::GetPartialResponse(); - - KeyVaultSecret secret = KeyVaultSecret("name2", "a"); - _detail::SecretSerializer::Deserialize(secret, response); - - Helpers::RunPartialExpect(secret); -} - -TEST(KeyVaultSecretSerializer, GetClientdeserializeFull1) -{ - auto response = Helpers::GetFullResponse(); - - KeyVaultSecret secret = _detail::SecretSerializer::Deserialize(response); - Helpers::RunFullExpect(secret); -} - -TEST(KeyVaultSecretSerializer, GetClientdeserializeFull2) -{ - auto response = Helpers::GetFullResponse(); - - KeyVaultSecret secret = _detail::SecretSerializer::Deserialize("name1", response); - - Helpers::RunFullExpect(secret); -} - -TEST(KeyVaultSecretSerializer, GetClientdeserializeFull3) -{ - auto response = Helpers::GetFullResponse(); - - KeyVaultSecret secret = KeyVaultSecret("name2", "a"); - _detail::SecretSerializer::Deserialize(secret, response); - - Helpers::RunFullExpect(secret); -} - -TEST(DeletedSecretSerializer, GetDeletedClientDeserializeFull1) -{ - auto response = Helpers::GetDeletedFullResponse(); - - DeletedSecret secret = _detail::DeletedSecretSerializer::Deserialize(response); - - Helpers::RunFullExpect(secret, false); - Helpers::RunDeletedExtras(secret); -} - -TEST(DeletedSecretSerializer, GetDeletedClientDeserializeFull2) -{ - auto response = Helpers::GetDeletedFullResponse(); - - DeletedSecret secret = _detail::DeletedSecretSerializer::Deserialize("name1", response); - - Helpers::RunFullExpect(secret, false); - Helpers::RunDeletedExtras(secret); -} - -TEST(DeletedSecretSerializer, GetDeletedClientDeserializeFull3) -{ - auto response = Helpers::GetDeletedFullResponse(); - - DeletedSecret secret = DeletedSecret("name2"); - _detail::DeletedSecretSerializer::Deserialize(secret, response); - - Helpers::RunFullExpect(secret, false); - Helpers::RunDeletedExtras(secret); -} - -TEST(SecretProperties, FactoryValid) -{ - std::string url( - "https://myvault.vault.azure.net/secrets/my_secret_name/4387e9f3d6e14c459867679a90fd0f79"); - SecretProperties props = SecretProperties::CreateFromURL(url); - EXPECT_EQ(props.Name, "my_secret_name"); - EXPECT_EQ(props.Version, "4387e9f3d6e14c459867679a90fd0f79"); - EXPECT_EQ(props.Id, url); - EXPECT_EQ(props.VaultUrl, "https://myvault.vault.azure.net"); -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_get_client_deserialize_test.hpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_get_client_deserialize_test.hpp deleted file mode 100644 index 34a9f941f..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_get_client_deserialize_test.hpp +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp" -#include "azure/keyvault/secrets/keyvault_secret.hpp" - -#include -#include - -#include - -#include - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Core::Http::_internal; - -namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _test { - struct Helpers - { - - static Azure::Core::Http::RawResponse GetPartialResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "value": "my_secret_value", - "id": "https://myvault.vault.azure.net/secrets/my_secret_name/4387e9f3d6e14c459867679a90fd0f79", - "managed":true, - "attributes": { - "enabled": true, - "created": 1493938410, - "updated": 1493938410, - "recoveryLevel": "Recoverable+Purgeable" - } - } -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetFullResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "value": "my_secret_value", - "id": "https://myvault.vault.azure.net/secrets/my_secret_name/4387e9f3d6e14c459867679a90fd0f79", - "contentType" : "ct", - "kid": "kid", - "managed": true, - "attributes": { - "enabled": true, - "created": 1493938410, - "updated": 1493938410, - "recoveryLevel": "Recoverable+Purgeable" - } - } -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetDeletedFullResponse() - - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "recoveryId": "https://myvault.vault.azure.net/deletedsecrets/GetDeletedSecretTest", - "deletedDate": 1493938433, - "scheduledPurgeDate": 1501714433, - "managed": true, - "id": "https://myvault.vault.azure.net/secrets/my_secret_name/4387e9f3d6e14c459867679a90fd0f79", - "attributes": { - "enabled": true, - "created": 1493938433, - "updated": 1493938433, - "recoveryLevel": "Recoverable+Purgeable" - } -})json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static void RunPartialExpect(KeyVaultSecret& secret, bool expectValue = true) - { - if (expectValue) - { - EXPECT_EQ(secret.Value.Value(), "my_secret_value"); - } - - EXPECT_EQ(secret.Name, "my_secret_name"); - EXPECT_EQ(secret.Properties.VaultUrl, "https://myvault.vault.azure.net"); - EXPECT_EQ(secret.Properties.Version, "4387e9f3d6e14c459867679a90fd0f79"); - EXPECT_EQ(secret.Properties.Id, secret.Id); - EXPECT_EQ( - secret.Id, - "https://myvault.vault.azure.net/secrets/my_secret_name/" - "4387e9f3d6e14c459867679a90fd0f79"); - EXPECT_EQ(secret.Properties.Managed, true); - EXPECT_EQ(secret.Properties.KeyId.HasValue(), false); - EXPECT_EQ(secret.Properties.UpdatedOn.HasValue(), true); - EXPECT_EQ(secret.Properties.CreatedOn.HasValue(), true); - } - - static void RunFullExpect(KeyVaultSecret& secret, bool expectValue = true) - { - if (expectValue) - { - EXPECT_EQ(secret.Value.Value(), "my_secret_value"); - EXPECT_EQ(secret.Properties.ContentType.Value(), "ct"); - EXPECT_EQ(secret.Properties.KeyId.Value(), "kid"); - } - - EXPECT_EQ(secret.Name, "my_secret_name"); - EXPECT_EQ(secret.Properties.VaultUrl, "https://myvault.vault.azure.net"); - EXPECT_EQ(secret.Properties.Version, "4387e9f3d6e14c459867679a90fd0f79"); - EXPECT_EQ(secret.Properties.Id, secret.Id); - EXPECT_EQ( - secret.Id, - "https://myvault.vault.azure.net/secrets/my_secret_name/" - "4387e9f3d6e14c459867679a90fd0f79"); - EXPECT_EQ(secret.Properties.Enabled.Value(), true); - EXPECT_EQ(secret.Properties.Managed, true); - EXPECT_EQ(secret.Properties.UpdatedOn.HasValue(), true); - EXPECT_EQ(secret.Properties.CreatedOn.HasValue(), true); - } - - static void RunDeletedExtras(DeletedSecret& secret) - { - EXPECT_EQ( - secret.RecoveryId, "https://myvault.vault.azure.net/deletedsecrets/GetDeletedSecretTest"); - EXPECT_EQ(secret.ScheduledPurgeDate.Value().ToString(), "2017-08-02T22:53:53Z"); - EXPECT_EQ(secret.DeletedOn.Value().ToString(), "2017-05-04T22:53:53Z"); - } - }; -}}}}} // namespace Azure::Security::KeyVault::Secrets::_test diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_paged_deserialize_test.cpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_paged_deserialize_test.cpp deleted file mode 100644 index 19e2f3928..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_paged_deserialize_test.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "secret_paged_deserialize_test.hpp" - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Security::KeyVault::Secrets::_test; -using namespace Azure::Security::KeyVault::Secrets::_detail; -using namespace Azure::Core::Json::_internal; - -TEST(SecretPropertiesPagedResponse, SingleWithNext) -{ - auto response = _test::PagedHelpers::GetFirstResponse(); - - auto result = _detail::SecretPropertiesPagedResultSerializer::Deserialize(response); - - EXPECT_EQ(result.Items.size(), size_t(1)); - EXPECT_EQ( - result.NextPageToken.Value(), - "https://gearama-test2.vault.azure.net:443/" - "secrets?api-version=7.2&$skiptoken=" - "eyJOZXh0TWFya2VyIjoiMiE4NCFNREF3TURFM0lYTmxZM0psZEM5VFQwMUZVMFZEVWtWVUlUQXdNREF5T0NFNU9UazVM" - "VEV5TFRNeFZESXpPalU1T2pVNUxqazVPVGs1T1RsYUlRLS0iLCJUYXJnZXRMb2NhdGlvbiI6MH0&maxresults=1"); - - auto item = result.Items[0]; - EXPECT_EQ(item.Enabled.Value(), true); - EXPECT_EQ(item.RecoverableDays.Value(), 90); - EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/magic"); -} - -TEST(SecretPropertiesPagedResponse, MultipleNoNext) -{ - auto response = _test::PagedHelpers::GetMultipleResponse(); - - auto result = _detail::SecretPropertiesPagedResultSerializer::Deserialize(response); - - EXPECT_EQ(result.Items.size(), size_t(3)); - EXPECT_EQ(result.NextPageToken.HasValue(), false); - - auto item = result.Items[0]; - EXPECT_EQ(item.Enabled.Value(), true); - EXPECT_EQ(item.RecoverableDays.Value(), 90); - EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ( - item.Id, - "https://gearama-test2.vault.azure.net/secrets/magic/5a0fdd819481420eac6f3282ce722461"); - EXPECT_EQ(item.Name, "magic"); - EXPECT_EQ(item.Version, "5a0fdd819481420eac6f3282ce722461"); - - item = result.Items[1]; - EXPECT_EQ(item.Enabled.Value(), true); - EXPECT_EQ(item.RecoverableDays.Value(), 90); - EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ( - item.Id, - "https://gearama-test2.vault.azure.net/secrets/magic/8faafbb99216484dbbd75f9dd6bcaadf"); - EXPECT_EQ(item.Name, "magic"); - EXPECT_EQ(item.Version, "8faafbb99216484dbbd75f9dd6bcaadf"); - - item = result.Items[2]; - EXPECT_EQ(item.Enabled.Value(), true); - EXPECT_EQ(item.RecoverableDays.Value(), 90); - EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ( - item.Id, - "https://gearama-test2.vault.azure.net/secrets/magic/d75080822f03400ab4d658bd0e988ac5"); - EXPECT_EQ(item.Name, "magic"); - EXPECT_EQ(item.Version, "d75080822f03400ab4d658bd0e988ac5"); -} - -TEST(SecretPropertiesPagedResponse, NoneNoNext) -{ - auto response = _test::PagedHelpers::GetEmptyResponse(); - - auto result = _detail::SecretPropertiesPagedResultSerializer::Deserialize(response); - - EXPECT_EQ(result.Items.size(), size_t(0)); - EXPECT_EQ(result.NextPageToken.HasValue(), false); -} - -TEST(DeletedSecretPagedResultSerializer, SingleWithNext) -{ - auto response = _test::PagedHelpers::GetDeletedFirstResponse(); - - auto result = _detail::DeletedSecretPagedResultSerializer::Deserialize(response); - - EXPECT_EQ(result.Items.size(), size_t(1)); - EXPECT_EQ(result.NextPageToken.Value(), "nextLink"); - - auto item = result.Items[0]; - EXPECT_EQ(item.Properties.Enabled.Value(), true); - EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90); - EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/eqwewq"); - EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq"); -} - -TEST(DeletedSecretPagedResultSerializer, MultipleNoNext) -{ - auto response = _test::PagedHelpers::GetDeletedMultipleResponse(); - - auto result = _detail::DeletedSecretPagedResultSerializer::Deserialize(response); - - EXPECT_EQ(result.Items.size(), size_t(3)); - EXPECT_FALSE(result.NextPageToken.HasValue()); - - auto item = result.Items[0]; - EXPECT_EQ(item.Properties.Enabled.Value(), true); - EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90); - EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/eqwewq"); - EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq"); - - item = result.Items[1]; - EXPECT_EQ(item.Properties.Enabled.Value(), true); - EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90); - EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/someSecret"); - EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/secrets/someSecret"); - - item = result.Items[2]; - EXPECT_EQ(item.Properties.Enabled.Value(), true); - EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90); - EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable"); - EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/someSecret2"); - EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/deletedsecrets/someSecret2"); -} - -TEST(DeletedSecretPagedResultSerializer, NoneNoNext) -{ - auto response = _test::PagedHelpers::GetEmptyResponse(); - - auto result = _detail::DeletedSecretPagedResultSerializer::Deserialize(response); - - EXPECT_EQ(result.Items.size(), size_t(0)); - EXPECT_EQ(result.NextPageToken.HasValue(), false); -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_paged_deserialize_test.hpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_paged_deserialize_test.hpp deleted file mode 100644 index 8606f0aba..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_paged_deserialize_test.hpp +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "../src/private/secret_serializers.hpp" -#include "azure/keyvault/secrets/keyvault_secret_paged_response.hpp" -#include "azure/keyvault/secrets/secret_client.hpp" -#include "private/secret_constants.hpp" -#include "private/secret_serializers.hpp" - -#include -#include -#include -#include -#include - -#include -#include - -#include - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Core::Http::_internal; - -namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _test { - struct PagedHelpers - { - - static Azure::Core::Http::RawResponse GetFirstResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "nextLink": "https://gearama-test2.vault.azure.net:443/secrets?api-version=7.2&$skiptoken=eyJOZXh0TWFya2VyIjoiMiE4NCFNREF3TURFM0lYTmxZM0psZEM5VFQwMUZVMFZEVWtWVUlUQXdNREF5T0NFNU9UazVMVEV5TFRNeFZESXpPalU1T2pVNUxqazVPVGs1T1RsYUlRLS0iLCJUYXJnZXRMb2NhdGlvbiI6MH0&maxresults=1", - "value": [{ - "attributes": { - "created": 1627404049, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1627404049 - }, - "id": "https://gearama-test2.vault.azure.net/secrets/magic" - }] -} -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetMultipleResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "nextLink": null, - "value": [{ - "attributes": { - "created": 1628101925, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1628101925 - }, - "contentType": "content", - "id": "https://gearama-test2.vault.azure.net/secrets/magic/5a0fdd819481420eac6f3282ce722461", - "tags": {} - }, { - "attributes": { - "created": 1627404049, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1627404049 - }, - "id": "https://gearama-test2.vault.azure.net/secrets/magic/8faafbb99216484dbbd75f9dd6bcaadf" - }, { - "attributes": { - "created": 1628101911, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1628101911 - }, - "id": "https://gearama-test2.vault.azure.net/secrets/magic/d75080822f03400ab4d658bd0e988ac5", - "tags": {} - }] -} -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetEmptyResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "nextLink": null, - "value": [] -} -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetDeletedFirstResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "nextLink": "nextLink", - "value": [{ - "attributes": { - "created": 1628110306, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1628110306 - }, - "deletedDate": 1628110318, - "id": "https://gearama-test2.vault.azure.net/secrets/eqwewq", - "recoveryId": "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq", - "scheduledPurgeDate": 1635886318, - "tags": {} - }] -} -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - - static Azure::Core::Http::RawResponse GetDeletedMultipleResponse() - { - auto response - = Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK"); - - constexpr static const uint8_t responseBody[] = R"json({ - "nextLink": null, - "value": [{ - "attributes": { - "created": 1628110306, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1628110306 - }, - "deletedDate": 1628110318, - "id": "https://gearama-test2.vault.azure.net/secrets/eqwewq", - "recoveryId": "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq", - "scheduledPurgeDate": 1635886318, - "tags": {} - }, { - "attributes": { - "created": 1626967532, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1626967532 - }, - "deletedDate": 1628110252, - "id": "https://gearama-test2.vault.azure.net/secrets/someSecret", - "recoveryId": "https://gearama-test2.vault.azure.net/secrets/someSecret", - "scheduledPurgeDate": 1635886252 - }, { - "attributes": { - "created": 1627101774, - "enabled": true, - "recoverableDays": 90, - "recoveryLevel": "Recoverable+Purgeable", - "updated": 1627101774 - }, - "deletedDate": 1628110259, - "id": "https://gearama-test2.vault.azure.net/secrets/someSecret2", - "recoveryId": "https://gearama-test2.vault.azure.net/deletedsecrets/someSecret2", - "scheduledPurgeDate": 1635886259 - }] -} -)json"; - - response.SetHeader(HttpShared::ContentType, "application/json"); - response.SetHeader(HttpShared::MsRequestId, "1"); - response.SetHeader(HttpShared::MsClientRequestId, "2"); - response.SetBody(std::vector(responseBody, responseBody + sizeof(responseBody))); - response.SetBodyStream(std::make_unique( - responseBody, sizeof(responseBody) - 1)); - - return response; - } - }; -}}}}} // namespace Azure::Security::KeyVault::Secrets::_test diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_set_parameters_serializer_test.cpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_set_parameters_serializer_test.cpp deleted file mode 100644 index e90f49a54..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_set_parameters_serializer_test.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "../src/private/secret_serializers.hpp" -#include "azure/core/internal/json/json.hpp" -#include "azure/core/internal/json/json_optional.hpp" -#include "azure/core/internal/json/json_serializable.hpp" -#include "azure/keyvault/secrets/secret_client.hpp" -#include "private/secret_constants.hpp" -#include "private/secret_serializers.hpp" -#include "secret_get_client_deserialize_test.hpp" - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Security::KeyVault::Secrets::_detail; -using namespace Azure::Core::Json::_internal; - -TEST(KeyvaultSecretSetParametersSerializer, SetValue) -{ - KeyVaultSecret params("name", "value"); - - std::string result = SecretSerializer::Serialize(params); - - auto jsonParser = json::parse(result); - - EXPECT_EQ(jsonParser[ValuePropertyName], params.Value.Value()); - EXPECT_EQ(jsonParser[IdPropertyName], nullptr); - EXPECT_EQ(jsonParser[ContentTypePropertyName], nullptr); -} - -TEST(KeyvaultSecretSetParametersSerializer, SetValueCT) -{ - KeyVaultSecret params("name", "value"); - - params.Properties.ContentType = "ct"; - - std::string result = SecretSerializer::Serialize(params); - - auto jsonParser = json::parse(result); - - EXPECT_EQ(jsonParser[ValuePropertyName], params.Value.Value()); - EXPECT_EQ(jsonParser[ContentTypePropertyName], params.Properties.ContentType.Value()); -} - -TEST(KeyvaultSecretSetParametersSerializer, SetValueCTAttrTag) -{ - KeyVaultSecret params("name", "value"); - - params.Properties.ContentType = "ct"; - params.Properties.Enabled = true; - params.Properties.Tags = std::unordered_map{{"a", "b"}}; - - std::string result = SecretSerializer::Serialize(params); - - auto jsonParser = json::parse(result); - - EXPECT_EQ(jsonParser[ValuePropertyName], params.Value.Value()); - EXPECT_EQ(jsonParser[AttributesPropertyName][TagsPropertyName]["a"], "b"); - EXPECT_EQ(jsonParser[AttributesPropertyName][EnabledPropertyName], true); - EXPECT_EQ(jsonParser[ContentTypePropertyName], params.Properties.ContentType.Value()); -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_update_properties_test.cpp b/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_update_properties_test.cpp deleted file mode 100644 index 61c1496ff..000000000 --- a/sdk/keyvault/azure-security-keyvault-secrets/test/ut/secret_update_properties_test.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "../src/private/secret_serializers.hpp" -#include "azure/core/internal/json/json.hpp" -#include "azure/core/internal/json/json_optional.hpp" -#include "azure/core/internal/json/json_serializable.hpp" -#include "azure/keyvault/secrets/secret_client.hpp" -#include "private/secret_constants.hpp" -#include "secret_get_client_deserialize_test.hpp" - -using namespace Azure::Security::KeyVault::Secrets; -using namespace Azure::Security::KeyVault::Secrets::_detail; -using namespace Azure::Core::Json::_internal; - -TEST(SecretPropertiesSerializer, Serialize1) -{ - SecretProperties properties; - - properties.ContentType = "contentType"; - properties.Enabled = true; - - auto serialized = _detail::SecretPropertiesSerializer::Serialize(properties); - - auto jsonParser = json::parse(serialized); - - EXPECT_EQ(properties.ContentType.Value(), jsonParser[_detail::ContentTypePropertyName]); - EXPECT_EQ( - properties.Enabled.Value(), - jsonParser[_detail::AttributesPropertyName][_detail::EnabledPropertyName]); -} - -TEST(SecretPropertiesSerializer, Serialize2) -{ - SecretProperties properties; - - properties.ContentType = "contentType"; - properties.Enabled = true; - properties.Tags.emplace("a", "b"); - - auto serialized = _detail::SecretPropertiesSerializer::Serialize(properties); - - auto jsonParser = json::parse(serialized); - - EXPECT_EQ(properties.ContentType.Value(), jsonParser[_detail::ContentTypePropertyName]); - EXPECT_EQ( - properties.Enabled.Value(), - jsonParser[_detail::AttributesPropertyName][_detail::EnabledPropertyName]); - EXPECT_EQ(properties.Tags["a"], jsonParser[_detail::TagsPropertyName]["a"]); -} - -TEST(SecretPropertiesSerializer, Serialize3) -{ - SecretProperties properties; - - properties.ContentType = "contentType"; - properties.Enabled = true; - properties.Tags.emplace("a", "b"); - properties.Tags.emplace("c", "d"); - - auto serialized = _detail::SecretPropertiesSerializer::Serialize(properties); - - auto jsonParser = json::parse(serialized); - - EXPECT_EQ(properties.ContentType.Value(), jsonParser[_detail::ContentTypePropertyName]); - EXPECT_EQ( - properties.Enabled.Value(), - jsonParser[_detail::AttributesPropertyName][_detail::EnabledPropertyName]); - for (auto kvp : properties.Tags) - { - EXPECT_EQ(properties.Tags[kvp.first], jsonParser[_detail::TagsPropertyName][kvp.first]); - } -} diff --git a/sdk/keyvault/azure-security-keyvault-secrets/tsp-location.yaml b/sdk/keyvault/azure-security-keyvault-secrets/tsp-location.yaml new file mode 100644 index 000000000..b32ccdc08 --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-secrets/tsp-location.yaml @@ -0,0 +1,5 @@ +directory: specification/keyvault/Security.KeyVault.Secrets +commit: bc18a6a035dbab575177a5548c936621e47d1124 +repo: Azure/azure-rest-api-specs +additionalDirectories: +- specification/keyvault/Security.KeyVault.Common/ \ No newline at end of file diff --git a/sdk/keyvault/azure-security-keyvault-secrets/tspconfig.yaml b/sdk/keyvault/azure-security-keyvault-secrets/tspconfig.yaml index 882fa330f..ff65e03cb 100644 --- a/sdk/keyvault/azure-security-keyvault-secrets/tspconfig.yaml +++ b/sdk/keyvault/azure-security-keyvault-secrets/tspconfig.yaml @@ -18,4 +18,5 @@ options: "@azure-tools/typespec-cpp": flavor: azure package-dir: "azure-security-keyvault-secrets" - namespace: "Azure::Security::KeyVault::Secrets" + namespace: "Azure::Security::KeyVault::Secrets::_detail" + headersOutputPath: "azure/keyvault/secrets/generated" diff --git a/sdk/keyvault/ci.yml b/sdk/keyvault/ci.yml index a228c91d8..5c8070fb6 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: 81 - BranchCoverageTarget: 42 + LineCoverageTarget: 77 + BranchCoverageTarget: 48 Artifacts: - Name: azure-security-keyvault-keys Path: azure-security-keyvault-keys