GetSecret Api implementation for Keyvault Secret (#2656)
* Progress stream reader * format * Update sdk/core/azure-core/src/io/body_stream.cpp Co-authored-by: JinmingHu <jinmhu@microsoft.com> * PR comments * remove * one more comment * replaced if null with azure_assert * moved from pointer to reference * first pass * src builds * new line * huzaaaaa * readme * strating point * get progress, need to deserialize now * serializer * some more * tests * more tests * some refactor * start * comment and formatting * working again * couple of updates * clang * remove pedantic ; * include * pr comments * clang format * trigger * trigger 2 * PR comments * name value swap Co-authored-by: JinmingHu <jinmhu@microsoft.com>
This commit is contained in:
parent
4805900fb6
commit
0d4f138cb3
@ -15,6 +15,7 @@
|
||||
#include "curl_connection_private.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <azure/core/http/curl_transport.hpp>
|
||||
#include <condition_variable>
|
||||
#include <curl/curl.h>
|
||||
#include <list>
|
||||
|
||||
@ -20,9 +20,9 @@ include(AzureGlobalCompileOptions)
|
||||
az_vcpkg_integrate()
|
||||
|
||||
if(NOT AZ_ALL_LIBRARIES)
|
||||
find_package(azure-core-cpp "1.0.0" CONFIG QUIET)
|
||||
find_package(azure-core-cpp "1.1.0" CONFIG QUIET)
|
||||
if(NOT azure-core-cpp_FOUND)
|
||||
find_package(azure-core-cpp "1.0.0" REQUIRED)
|
||||
find_package(azure-core-cpp "1.1.0" REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -30,13 +30,19 @@ set(
|
||||
AZURE_SECURITY_KEYVAULT_SECRETS_HEADER
|
||||
inc/azure/keyvault/secrets/dll_import_export.hpp
|
||||
inc/azure/keyvault/secrets/secret_client.hpp
|
||||
inc/azure/keyvault/secrets/keyvault_secret.hpp
|
||||
inc/azure/keyvault/keyvault_secrets.hpp
|
||||
)
|
||||
|
||||
set(
|
||||
AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE
|
||||
src/private/package_version.hpp
|
||||
src/private/keyvault_protocol.hpp
|
||||
src/private/secret_constants.hpp
|
||||
src/private/secret_serializers.hpp
|
||||
src/keyvault_protocol.cpp
|
||||
src/secret_client.cpp
|
||||
src/secret_serializers.cpp
|
||||
)
|
||||
|
||||
add_library(azure-security-keyvault-secrets ${AZURE_SECURITY_KEYVAULT_SECRETS_HEADER} ${AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE})
|
||||
@ -49,7 +55,7 @@ target_include_directories(
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
|
||||
#target_link_libraries(azure-security-keyvault-secrets PUBLIC Azure::azure-security-keyvault-secrets)
|
||||
target_link_libraries(azure-security-keyvault-secrets PUBLIC Azure::azure-core)
|
||||
|
||||
# coverage. Has no effect if BUILD_CODE_COVERAGE is OFF
|
||||
create_code_coverage(keyvault-secrets azure-security-keyvault-secrets azure-security-keyvault-secrets-test)
|
||||
@ -64,6 +70,7 @@ if(BUILD_TESTING)
|
||||
endif()
|
||||
|
||||
add_subdirectory(test/ut)
|
||||
add_subdirectory(test/sample)
|
||||
endif()
|
||||
|
||||
if (BUILD_PERFORMANCE_TESTS)
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Keyvault Secret definition
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <azure/keyvault/secrets/keyvault_secret_properties.hpp>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
struct KeyVaultSecret final
|
||||
{
|
||||
/**
|
||||
* @brief The name of the secret.
|
||||
*
|
||||
*/
|
||||
std::string Name;
|
||||
|
||||
/**
|
||||
* @brief The secret value.
|
||||
*
|
||||
*/
|
||||
std::string Value;
|
||||
|
||||
/**
|
||||
* @brief The secret id.
|
||||
*
|
||||
*/
|
||||
std::string Id;
|
||||
|
||||
/**
|
||||
* @brief The secret Properties bundle.
|
||||
*
|
||||
*/
|
||||
KeyvaultSecretProperties Properties;
|
||||
|
||||
/**
|
||||
* @brief Construct a new KeyVaultSecret object.
|
||||
*
|
||||
*/
|
||||
KeyVaultSecret() = default;
|
||||
|
||||
/**
|
||||
* @brief Construct a new KeyVaultSecret object.
|
||||
*
|
||||
* @param name The name of the secret.
|
||||
* @param value The name of the secret.
|
||||
*/
|
||||
KeyVaultSecret(std::string name, std::string value)
|
||||
: Name(std::move(name)), Value(std::move(value))
|
||||
{
|
||||
if (Name.empty())
|
||||
{
|
||||
throw std::invalid_argument("Name cannot be empty");
|
||||
}
|
||||
}
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::Secrets
|
||||
@ -0,0 +1,127 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Keyvault Secret Attributes definition
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/datetime.hpp>
|
||||
#include <azure/core/nullable.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
|
||||
/**
|
||||
* @brief The Secret attributes managed by the KeyVault service.
|
||||
*
|
||||
*/
|
||||
struct KeyvaultSecretProperties final
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief Indicate whether the secret is enabled and useable for cryptographic operations.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<bool> Enabled;
|
||||
|
||||
/**
|
||||
* @brief Indicate when the secret will be valid and can be used for cryptographic operations.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<Azure::DateTime> NotBefore;
|
||||
|
||||
/**
|
||||
* @brief Indicate when the secret will expire and cannot be used for cryptographic operations.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<Azure::DateTime> ExpiresOn;
|
||||
|
||||
/**
|
||||
* @brief Indicate when the secret was created.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<Azure::DateTime> CreatedOn;
|
||||
|
||||
/**
|
||||
* @brief Indicate when the secret was updated.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<Azure::DateTime> UpdatedOn;
|
||||
|
||||
/**
|
||||
* @brief The number of days a secret is retained before being deleted for a soft delete-enabled
|
||||
* Key Vault.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<int64_t> RecoverableDays;
|
||||
|
||||
/**
|
||||
* @brief The recovery level currently in effect for secrets in the Key Vault.
|
||||
*
|
||||
* @remark If Purgeable, the secret can be permanently deleted by an authorized user; otherwise,
|
||||
* only the service can purge the secret at the end of the retention interval.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<std::string> RecoveryLevel;
|
||||
|
||||
/**
|
||||
* @brief The content type of the secret.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<std::string> ContentType;
|
||||
|
||||
/**
|
||||
* @brief If this is a secret backing a KV certificate, then this field specifies the
|
||||
* corresponding key backing the KV certificate.
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<std::string> KeyId;
|
||||
|
||||
/**
|
||||
* @brief Application specific metadata in the form of key-value pairs.
|
||||
*
|
||||
*/
|
||||
std::unordered_map<std::string, std::string> Tags;
|
||||
|
||||
/**
|
||||
* @brief True if the secret's lifetime is managed by key vault. If this is a secret
|
||||
* backing a certificate, then managed will be true.
|
||||
*
|
||||
*/
|
||||
bool Managed = false;
|
||||
|
||||
/**
|
||||
* @brief The secret id.
|
||||
*
|
||||
*/
|
||||
std::string Id;
|
||||
|
||||
/**
|
||||
* @brief The name of the secret.
|
||||
*
|
||||
*/
|
||||
std::string Name;
|
||||
|
||||
/**
|
||||
* @brief The vault url of the secret.
|
||||
*
|
||||
*/
|
||||
std::string VaultUrl;
|
||||
|
||||
/**
|
||||
* @brief The version of the secret.
|
||||
*
|
||||
*/
|
||||
std::string Version;
|
||||
|
||||
/**
|
||||
* @brief Construct a new secret Properties object.
|
||||
*
|
||||
*/
|
||||
KeyvaultSecretProperties() = default;
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::Secrets
|
||||
@ -1,14 +1,137 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
/**
|
||||
* @file
|
||||
* @brief Defines the Key Vault Secret client.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../src/private/keyvault_protocol.hpp"
|
||||
#include "dll_import_export.hpp"
|
||||
|
||||
#include <azure/keyvault/secrets/keyvault_secret.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
|
||||
class SecretClient final {
|
||||
class ServiceVersion final {
|
||||
private:
|
||||
std::string m_version;
|
||||
|
||||
public:
|
||||
std::string ClientVersion() const;
|
||||
/**
|
||||
* @brief Construct a new Service Version object
|
||||
*
|
||||
* @param version The string version for the Key Vault keys service.
|
||||
*/
|
||||
ServiceVersion(std::string version) : m_version(std::move(version)) {}
|
||||
|
||||
/**
|
||||
* @brief Enable comparing the ext enum.
|
||||
*
|
||||
* @param other Another #ServiceVersion to be compared.
|
||||
*/
|
||||
bool operator==(ServiceVersion const& other) const { return m_version == other.m_version; }
|
||||
|
||||
/**
|
||||
* @brief Return the #ServiceVersion string representation.
|
||||
*
|
||||
*/
|
||||
std::string const& ToString() const { return m_version; }
|
||||
|
||||
/**
|
||||
* @brief Use to send request to the 7.2 version of Key Vault service.
|
||||
*
|
||||
*/
|
||||
AZURE_SECURITY_KEYVAULT_SECRETS_DLLEXPORT static const ServiceVersion V7_2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Define the options to create an SDK Keys client.
|
||||
*
|
||||
*/
|
||||
struct SecretClientOptions final : public Azure::Core::_internal::ClientOptions
|
||||
{
|
||||
ServiceVersion Version;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Secret Client Options object.
|
||||
*
|
||||
* @param version Optional version for the client.
|
||||
*/
|
||||
SecretClientOptions(ServiceVersion version = ServiceVersion::V7_2)
|
||||
: Azure::Core::_internal::ClientOptions(), Version(version)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for SecretClient::GetSecret
|
||||
*
|
||||
*/
|
||||
struct GetSecretOptions final
|
||||
{
|
||||
/**
|
||||
* @brief Specify the key version to get.
|
||||
*
|
||||
*/
|
||||
std::string Version;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The SecretClient provides synchronous methods to manage a secret in the Azure Key
|
||||
* Vault. The client supports creating, retrieving, updating, deleting, purging, backing up,
|
||||
* restoring, and listing the secret.
|
||||
*/
|
||||
class SecretClient
|
||||
#if !defined(TESTING_BUILD)
|
||||
final
|
||||
#endif
|
||||
{
|
||||
|
||||
protected:
|
||||
// Using a shared pipeline for a client to share it with LRO (like delete key)
|
||||
std::shared_ptr<Azure::Security::KeyVault::_detail::KeyVaultProtocolClient> m_protocolClient;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new SecretClient object
|
||||
*
|
||||
* @param vaultUrl The URL address where the client will send the requests to.
|
||||
* @param credential The authentication method to use.
|
||||
* @param options The options to customize the client behavior.
|
||||
*/
|
||||
explicit SecretClient(
|
||||
std::string const& vaultUrl,
|
||||
std::shared_ptr<Azure::Core::Credentials::TokenCredential const> credential,
|
||||
SecretClientOptions options = SecretClientOptions());
|
||||
|
||||
/**
|
||||
* @brief Construct a new Key Client object from another key client.
|
||||
*
|
||||
* @param keyClient An existing key vault key client.
|
||||
*/
|
||||
explicit SecretClient(SecretClient const& keyClient)
|
||||
: m_protocolClient(keyClient.m_protocolClient){};
|
||||
|
||||
~SecretClient() = default;
|
||||
|
||||
/**
|
||||
* @brief Get a specified secret from a given key vault
|
||||
* This operation is applicable to any secret stored in Azure Key Vault.
|
||||
* This operation requires the secrets/get permission.
|
||||
*
|
||||
* @param name The name of the secret<span class="x x-first x-last">.</span>
|
||||
* @param options The optional parameters for this request.
|
||||
*
|
||||
* @param context The context for the operation can be used for request cancellation.
|
||||
* @return The Secret wrapped in the Response.
|
||||
*/
|
||||
Azure::Response<KeyVaultSecret> GetSecret(
|
||||
std::string const& name,
|
||||
GetSecretOptions const& options = GetSecretOptions(),
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Secrets
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "private/keyvault_protocol.hpp"
|
||||
#include "private/secret_constants.hpp"
|
||||
#include <azure/core/exception.hpp>
|
||||
#include <azure/core/http/http.hpp>
|
||||
|
||||
using namespace Azure::Security::KeyVault;
|
||||
using namespace Azure::Core::Http::_internal;
|
||||
|
||||
Azure::Core::Http::Request _detail::KeyVaultProtocolClient::CreateRequest(
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
Azure::Core::IO::BodyStream* content,
|
||||
std::vector<std::string> const& path) const
|
||||
{
|
||||
Azure::Core::Http::Request request = content == nullptr
|
||||
? Azure::Core::Http::Request(method, m_vaultUrl)
|
||||
: Azure::Core::Http::Request(method, m_vaultUrl, content);
|
||||
|
||||
request.SetHeader(HttpShared::ContentType, HttpShared::ApplicationJson);
|
||||
request.SetHeader(HttpShared::Accept, HttpShared::ApplicationJson);
|
||||
|
||||
request.GetUrl().AppendQueryParameter(
|
||||
Azure::Security::KeyVault::Secrets::_detail::ApiVersion, m_apiVersion);
|
||||
|
||||
for (std::string const& p : path)
|
||||
{
|
||||
if (!p.empty())
|
||||
{
|
||||
request.GetUrl().AppendPath(p);
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
Azure::Core::Http::Request _detail::KeyVaultProtocolClient::CreateRequest(
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
std::vector<std::string> const& path) const
|
||||
{
|
||||
return CreateRequest(method, nullptr, path);
|
||||
}
|
||||
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> _detail::KeyVaultProtocolClient::SendRequest(
|
||||
Azure::Core::Context const& context,
|
||||
Azure::Core::Http::Request& request) const
|
||||
{
|
||||
auto response = m_pipeline.Send(request, context);
|
||||
auto responseCode = response->GetStatusCode();
|
||||
switch (responseCode)
|
||||
{
|
||||
|
||||
// 200, 2001, 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;
|
||||
}
|
||||
@ -0,0 +1,189 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief Provides a wrapper class for the Azure Core Pipeline for all Key Vault services where
|
||||
* common functionality is set up.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/internal/http/pipeline.hpp>
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_serializable.hpp>
|
||||
#include <azure/core/response.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace _detail {
|
||||
|
||||
/**
|
||||
* @brief The Protocol layer used by Key Vault clients.
|
||||
*
|
||||
*/
|
||||
class KeyVaultProtocolClient final {
|
||||
Azure::Core::Url m_vaultUrl;
|
||||
Azure::Core::Http::_internal::HttpPipeline m_pipeline;
|
||||
std::string m_apiVersion;
|
||||
|
||||
/**
|
||||
* @brief Create a Request to be sent.
|
||||
*
|
||||
* @param method Represent an HTTP method.
|
||||
* @param path The path for the HTTP request.
|
||||
* @return A constructed request.
|
||||
*/
|
||||
Azure::Core::Http::Request CreateRequest(
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
std::vector<std::string> const& path) const;
|
||||
|
||||
/**
|
||||
* @brief Create a Key Vault request with payload.
|
||||
*
|
||||
* @param method The HTTP method.
|
||||
* @param content The HTTP payload.
|
||||
* @param path The HTTP request path.
|
||||
* @return A constructed request.
|
||||
*/
|
||||
Azure::Core::Http::Request CreateRequest(
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
Azure::Core::IO::BodyStream* content,
|
||||
std::vector<std::string> const& path) const;
|
||||
|
||||
/**
|
||||
* @brief Start the HTTP transfer based on the \p request.
|
||||
*
|
||||
* @param context The context for per-operation options or cancellation.
|
||||
* @param request The HTTP request to be sent.
|
||||
* @return The raw response from the network.
|
||||
*/
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> SendRequest(
|
||||
Azure::Core::Context const& context,
|
||||
Azure::Core::Http::Request& request) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Key Vault Protocol Client.
|
||||
*
|
||||
* @param vaultUrl The URL address for the Key Vault.
|
||||
* @param apiVersion The service API version.
|
||||
* @param pipeline The HTTP pipeline for sending requests with.
|
||||
*/
|
||||
explicit KeyVaultProtocolClient(
|
||||
Azure::Core::Url vaultUrl,
|
||||
std::string apiVersion,
|
||||
Azure::Core::Http::_internal::HttpPipeline&& pipeline)
|
||||
: m_vaultUrl(std::move(vaultUrl)), m_pipeline(pipeline), m_apiVersion(std::move(apiVersion))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create and send the HTTP request. Uses the \p factoryFn function to create
|
||||
* the response type.
|
||||
*
|
||||
* @param context The context for per-operation options or cancellation.
|
||||
* @param method The method for the request.
|
||||
* @param factoryFn The function to deserialize and produce T from the raw response.
|
||||
* @param path A path for the request represented as a vector of strings.
|
||||
* @param query Optional query parameters for constructing the request.
|
||||
* @return The object produced by the \p factoryFn and the raw response from the network.
|
||||
*/
|
||||
template <class T>
|
||||
Azure::Response<T> SendRequest(
|
||||
Azure::Core::Context const& context,
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
std::function<T(Azure::Core::Http::RawResponse const& rawResponse)> factoryFn,
|
||||
std::vector<std::string> const& path,
|
||||
std::unique_ptr<std::map<std::string, std::string>> const& query = nullptr)
|
||||
{
|
||||
auto request = CreateRequest(method, path);
|
||||
if (query != nullptr)
|
||||
{
|
||||
for (auto const& queryParameter : *query)
|
||||
{
|
||||
request.GetUrl().AppendQueryParameter(queryParameter.first, queryParameter.second);
|
||||
}
|
||||
}
|
||||
auto response = SendRequest(context, request);
|
||||
// Saving the value in a local is required before passing it in to Response<T> to avoid
|
||||
// compiler optimizations re-ordering the `factoryFn` function call and the RawResponse move.
|
||||
T value = factoryFn(*response);
|
||||
return Azure::Response<T>(std::move(value), std::move(response));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create and send the HTTP request with payload content. Uses the \p factoryFn function
|
||||
* to create the response type.
|
||||
*
|
||||
* @param context The context for per-operation options or cancellation.
|
||||
* @param method The method for the request.
|
||||
* @param content The HTTP payload.
|
||||
* @param factoryFn The function to deserialize and produce T from the raw response.
|
||||
* @param path A path for the request represented as a vector of strings.
|
||||
* @return The object produced by the \p factoryFn and the raw response from the network.
|
||||
*/
|
||||
template <class T>
|
||||
Azure::Response<T> SendRequest(
|
||||
Azure::Core::Context const& context,
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
Azure::Core::Json::_internal::JsonSerializable const& content,
|
||||
std::function<T(Azure::Core::Http::RawResponse const& rawResponse)> factoryFn,
|
||||
std::vector<std::string> const& path)
|
||||
{
|
||||
auto serialContent = content.Serialize();
|
||||
auto streamContent = Azure::Core::IO::MemoryBodyStream(
|
||||
reinterpret_cast<const uint8_t*>(serialContent.data()), serialContent.size());
|
||||
|
||||
auto request = CreateRequest(method, &streamContent, path);
|
||||
auto response = SendRequest(context, request);
|
||||
// Saving the value in a local is required before passing it in to Response<T> to avoid
|
||||
// compiler optimizations re-ordering the `factoryFn` function call and the RawResponse move.
|
||||
T value = factoryFn(*response);
|
||||
return Azure::Response<T>(value, std::move(response));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Azure::Response<T> SendRequest(
|
||||
Azure::Core::Context const& context,
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
std::function<std::string()> serializeContentFn,
|
||||
std::function<T(Azure::Core::Http::RawResponse const& rawResponse)> factoryFn,
|
||||
std::vector<std::string> const& path)
|
||||
{
|
||||
auto serialContent = serializeContentFn();
|
||||
auto streamContent = Azure::Core::IO::MemoryBodyStream(
|
||||
reinterpret_cast<const uint8_t*>(serialContent.data()), serialContent.size());
|
||||
|
||||
auto request = CreateRequest(method, &streamContent, path);
|
||||
auto response = SendRequest(context, request);
|
||||
// Saving the value in a local is required before passing it in to Response<T> to avoid
|
||||
// compiler optimizations re-ordering the `factoryFn` function call and the RawResponse move.
|
||||
T value = factoryFn(*response);
|
||||
return Azure::Response<T>(value, std::move(response));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a key vault request and send it using the Azure Core pipeline directly to avoid
|
||||
* checking the respone code.
|
||||
*
|
||||
* @param context A context for cancellation.
|
||||
* @param method The HTTP method for the request.
|
||||
* @param path The path for the request.
|
||||
* @return A unique ptr to an HTTP raw response.
|
||||
*/
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> Send(
|
||||
Azure::Core::Context const& context,
|
||||
Azure::Core::Http::HttpMethod method,
|
||||
std::vector<std::string> const& path)
|
||||
{
|
||||
auto request = CreateRequest(method, path);
|
||||
// Use the core pipeline directly to avoid checking the response code.
|
||||
return m_pipeline.Send(request, context);
|
||||
}
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::_detail
|
||||
@ -0,0 +1,36 @@
|
||||
// Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Centralize the string constants used by Key Vault Secret Client.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail {
|
||||
|
||||
/***************** KeyVault Secret *****************/
|
||||
constexpr static const char SecretPath[] = "secrets";
|
||||
|
||||
/******************* Secret property names ***********/
|
||||
|
||||
constexpr static const char AttributesPropertyName[] = "attributes";
|
||||
constexpr static const char EnabledPropertyName[] = "enabled";
|
||||
constexpr static const char NbfPropertyName[] = "nbf";
|
||||
constexpr static const char ExpPropertyName[] = "exp";
|
||||
constexpr static const char CreatedPropertyName[] = "created";
|
||||
constexpr static const char UpdatedPropertyName[] = "updated";
|
||||
constexpr static const char ManagedPropertyName[] = "managed";
|
||||
constexpr static const char TagsPropertyName[] = "tags";
|
||||
constexpr static const char IdPropertyName[] = "id";
|
||||
constexpr static const char KeyIdPropertyName[] = "kid";
|
||||
constexpr static const char ValuePropertyName[] = "value";
|
||||
constexpr static const char RecoveryLevelPropertyName[] = "recoveryLevel";
|
||||
constexpr static const char ContentTypePropertyName[] = "contentType";
|
||||
constexpr static const char RecoverableDaysPropertyName[] = "recoverableDays";
|
||||
|
||||
/**************** KeyVault QueryParameters *********/
|
||||
static constexpr char const ApiVersion[] = "api-version";
|
||||
}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail
|
||||
@ -0,0 +1,79 @@
|
||||
// Copyright(c) Microsoft Corporation.All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Serializers/sdeserializers for the KeyVault Secret client.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/keyvault/secrets/keyvault_secret.hpp>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail {
|
||||
struct KeyVaultSecretSerializer final
|
||||
{
|
||||
// Creates a new key based on a name and an HTTP raw response.
|
||||
static KeyVaultSecret KeyVaultSecretDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// Create from HTTP raw response only.
|
||||
static KeyVaultSecret KeyVaultSecretDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// Updates a Key based on an HTTP raw response.
|
||||
static void KeyVaultSecretDeserialize(
|
||||
KeyVaultSecret& key,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// extract the host out of the URL (with port if available)
|
||||
static std::string GetUrlAuthorityWithScheme(Azure::Core::Url const& url)
|
||||
{
|
||||
std::string urlString;
|
||||
if (!url.GetScheme().empty())
|
||||
{
|
||||
urlString += url.GetScheme() + "://";
|
||||
}
|
||||
urlString += url.GetHost();
|
||||
if (url.GetPort() != 0)
|
||||
{
|
||||
urlString += ":" + std::to_string(url.GetPort());
|
||||
}
|
||||
return urlString;
|
||||
}
|
||||
|
||||
// parse the ID url to extract relevant data
|
||||
void static inline ParseIDUrl(
|
||||
KeyvaultSecretProperties& secretProperties,
|
||||
std::string const& url)
|
||||
{
|
||||
Azure::Core::Url sid(url);
|
||||
secretProperties.Id = url;
|
||||
secretProperties.VaultUrl = GetUrlAuthorityWithScheme(sid);
|
||||
auto const& path = sid.GetPath();
|
||||
// path is in the form of `verb/keyName{/keyVersion}`
|
||||
auto const separatorChar = '/';
|
||||
auto pathEnd = path.end();
|
||||
auto start = path.begin();
|
||||
start = std::find(start, pathEnd, separatorChar);
|
||||
start += 1;
|
||||
auto separator = std::find(start, pathEnd, separatorChar);
|
||||
if (separator != pathEnd)
|
||||
{
|
||||
secretProperties.Name = std::string(start, separator);
|
||||
start = separator + 1;
|
||||
secretProperties.Version = std::string(start, pathEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing but the name+
|
||||
secretProperties.Name = std::string(start, pathEnd);
|
||||
}
|
||||
}
|
||||
};
|
||||
}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail
|
||||
@ -5,13 +5,63 @@
|
||||
* @brief Keyvault Secrets Client definition.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "azure/keyvault/secrets/secret_client.hpp"
|
||||
|
||||
#include "private/keyvault_protocol.hpp"
|
||||
#include "private/package_version.hpp"
|
||||
#include "private/secret_constants.hpp"
|
||||
#include "private/secret_serializers.hpp"
|
||||
|
||||
#include <azure/core/credentials/credentials.hpp>
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace Azure::Security::KeyVault::Secrets::_detail;
|
||||
using namespace Azure::Core::Http::Policies;
|
||||
using namespace Azure::Core::Http::Policies::_internal;
|
||||
|
||||
std::string SecretClient::ClientVersion() const { return PackageVersion::ToString(); }
|
||||
namespace {
|
||||
constexpr static const char TelemetryName[] = "keyvault-secrets";
|
||||
}
|
||||
|
||||
SecretClient::SecretClient(
|
||||
std::string const& vaultUrl,
|
||||
std::shared_ptr<Core::Credentials::TokenCredential const> credential,
|
||||
SecretClientOptions options)
|
||||
{
|
||||
auto apiVersion = options.Version.ToString();
|
||||
|
||||
std::vector<std::unique_ptr<HttpPolicy>> perRetrypolicies;
|
||||
{
|
||||
Azure::Core::Credentials::TokenRequestContext const tokenContext
|
||||
= {{"https://vault.azure.net/.default"}};
|
||||
|
||||
perRetrypolicies.emplace_back(
|
||||
std::make_unique<BearerTokenAuthenticationPolicy>(credential, tokenContext));
|
||||
}
|
||||
|
||||
m_protocolClient = std::make_shared<Azure::Security::KeyVault::_detail::KeyVaultProtocolClient>(
|
||||
Azure::Core::Url(vaultUrl),
|
||||
apiVersion,
|
||||
Azure::Core::Http::_internal::HttpPipeline(
|
||||
options, TelemetryName, apiVersion, std::move(perRetrypolicies), {}));
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultSecret> SecretClient::GetSecret(
|
||||
std::string const& name,
|
||||
GetSecretOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return m_protocolClient->SendRequest<KeyVaultSecret>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::SecretPath, name, options.Version});
|
||||
}
|
||||
|
||||
const ServiceVersion ServiceVersion::V7_2("7.2");
|
||||
|
||||
@ -0,0 +1,113 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Keyvault Secret serializers
|
||||
*/
|
||||
|
||||
#include "private/secret_serializers.hpp"
|
||||
#include "private/secret_constants.hpp"
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
#include <azure/core/internal/json/json_serializable.hpp>
|
||||
|
||||
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 KeyVaultSecretSerializer::KeyVaultSecretDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
KeyVaultSecret secret(name, "");
|
||||
_detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(secret, rawResponse);
|
||||
return secret;
|
||||
}
|
||||
|
||||
// Create from HTTP raw response only.
|
||||
KeyVaultSecret KeyVaultSecretSerializer::KeyVaultSecretDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
KeyVaultSecret secret;
|
||||
_detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(secret, rawResponse);
|
||||
return secret;
|
||||
}
|
||||
|
||||
// Updates a Key based on an HTTP raw response.
|
||||
void KeyVaultSecretSerializer::KeyVaultSecretDeserialize(
|
||||
KeyVaultSecret& secret,
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
auto const& body = rawResponse.GetBody();
|
||||
auto jsonParser = json::parse(body);
|
||||
|
||||
secret.Value = jsonParser[_detail::ValuePropertyName];
|
||||
secret.Id = jsonParser[_detail::IdPropertyName];
|
||||
secret.Properties.Id = secret.Id;
|
||||
|
||||
ParseIDUrl(secret.Properties, secret.Id);
|
||||
secret.Name = secret.Properties.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<int64_t, Azure::DateTime>(
|
||||
secret.Properties.NotBefore,
|
||||
attributes,
|
||||
_detail::NbfPropertyName,
|
||||
PosixTimeConverter::PosixTimeToDateTime);
|
||||
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
|
||||
secret.Properties.ExpiresOn,
|
||||
attributes,
|
||||
_detail::ExpPropertyName,
|
||||
PosixTimeConverter::PosixTimeToDateTime);
|
||||
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
|
||||
secret.Properties.CreatedOn,
|
||||
attributes,
|
||||
_detail::CreatedPropertyName,
|
||||
PosixTimeConverter::PosixTimeToDateTime);
|
||||
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
|
||||
secret.Properties.UpdatedOn,
|
||||
attributes,
|
||||
_detail::UpdatedPropertyName,
|
||||
PosixTimeConverter::PosixTimeToDateTime);
|
||||
JsonOptional::SetIfExists<std::string>(
|
||||
secret.Properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName);
|
||||
JsonOptional::SetIfExists<int64_t>(
|
||||
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<std::string>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// managed
|
||||
if (jsonParser.contains(_detail::ManagedPropertyName))
|
||||
{
|
||||
secret.Properties.Managed = jsonParser[_detail::ManagedPropertyName].get<bool>();
|
||||
}
|
||||
|
||||
// key id
|
||||
JsonOptional::SetIfExists<std::string>(
|
||||
secret.Properties.KeyId, jsonParser, _detail::KeyIdPropertyName);
|
||||
|
||||
// content type
|
||||
JsonOptional::SetIfExists<std::string>(
|
||||
secret.Properties.ContentType, jsonParser, _detail::ContentTypePropertyName);
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (keyvault-secrets-test-app LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
keyvault-secrets-test-app
|
||||
test_app.cpp
|
||||
macro_guard.cpp
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(keyvault-secrets-test-app PUBLIC /wd6326 /wd26495 /wd26812)
|
||||
endif()
|
||||
|
||||
target_link_libraries(keyvault-secrets-test-app PRIVATE azure-security-keyvault-secrets azure-identity)
|
||||
@ -0,0 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Define `min` and `max` as function-like macros before including all public
|
||||
// headers to ensure that uses of those identifiers are defended against
|
||||
// expansion as function-like macros. Define `small` as an object-like macro to
|
||||
// ensure that identifier isn't used at all. Windows.h is badly behaved and
|
||||
// defines similar macros with these names and we want to ensure the SDK headers
|
||||
// function even when a naive user includes Windows.h first.
|
||||
//
|
||||
#define small FAIL><TO][COMPILE)(VERY{{{LOUDLY!!!
|
||||
#define max(x, y) small
|
||||
#define min(x, y) small
|
||||
|
||||
#include "azure/keyvault/keyvault_secrets.hpp"
|
||||
@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/identity.hpp>
|
||||
|
||||
#include <azure/keyvault/keyvault_secrets.hpp>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tenantId = std::getenv("AZURE_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_CLIENT_SECRET");
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
// just a response, with a secret
|
||||
auto response = secretClient.GetSecret("testSecret");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -11,8 +11,11 @@ include(GoogleTest)
|
||||
|
||||
add_executable (
|
||||
azure-security-keyvault-secrets-test
|
||||
|
||||
macro_guard.cpp
|
||||
secret_client_test.cpp
|
||||
secret_get_client_deserialize_test.hpp
|
||||
secret_get_client_deserialize_test.cpp
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
|
||||
@ -1,15 +1,44 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "azure/core/context.hpp"
|
||||
#include "azure/identity/client_secret_credential.hpp"
|
||||
#include "azure/keyvault/secrets/secret_client.hpp"
|
||||
|
||||
#include <azure/keyvault/secrets/secret_client.hpp>
|
||||
#include <exception>
|
||||
#include <gtest/gtest.h>
|
||||
#include <memory>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
|
||||
TEST(SecretClient, Basic)
|
||||
TEST(SecretClient, InitClient)
|
||||
{
|
||||
SecretClient secretClient;
|
||||
|
||||
EXPECT_FALSE(secretClient.ClientVersion().empty());
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>("tenantID", "AppId", "SecretId");
|
||||
{
|
||||
EXPECT_NO_THROW(SecretClient SecretClient("vaultUrl", credential));
|
||||
}
|
||||
{
|
||||
SecretClientOptions options;
|
||||
options.Retry.MaxRetries = 10;
|
||||
EXPECT_NO_THROW(SecretClient secretClient("vaultUrl", credential, options));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SecretClient, ServiceVersion)
|
||||
{
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>("tenantID", "AppId", "SecretId");
|
||||
{
|
||||
// 7.2
|
||||
EXPECT_NO_THROW(auto options = SecretClientOptions(ServiceVersion::V7_2);
|
||||
SecretClient SecretClient("vaultUrl", credential, options);
|
||||
EXPECT_EQ(options.Version.ToString(), "7.2"););
|
||||
}
|
||||
{
|
||||
// arbitrary version
|
||||
EXPECT_NO_THROW(auto options = SecretClientOptions(ServiceVersion("1.0"));
|
||||
SecretClient secretClient("vaultUrl", credential, options);
|
||||
EXPECT_EQ(options.Version.ToString(), "1.0"););
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#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::_detail;
|
||||
|
||||
TEST(KeyVaultSecretSerializer, GetClientDeserializePartial1)
|
||||
{
|
||||
auto response = getPartialResponse();
|
||||
|
||||
KeyVaultSecret secret = _detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(response);
|
||||
runPartialExpect(secret);
|
||||
}
|
||||
|
||||
TEST(KeyVaultSecretSerializer, GetClientDeserializePartial2)
|
||||
{
|
||||
auto response = getPartialResponse();
|
||||
|
||||
KeyVaultSecret secret
|
||||
= _detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize("name1", response);
|
||||
|
||||
runPartialExpect(secret);
|
||||
}
|
||||
|
||||
TEST(KeyVaultSecretSerializer, GetClientDeserializePartial3)
|
||||
{
|
||||
auto response = getPartialResponse();
|
||||
|
||||
KeyVaultSecret secret = KeyVaultSecret("name2", "");
|
||||
_detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(secret, response);
|
||||
|
||||
runPartialExpect(secret);
|
||||
}
|
||||
|
||||
TEST(KeyVaultSecretSerializer, GetClientdeserializeFull1)
|
||||
{
|
||||
auto response = getFullResponse();
|
||||
|
||||
KeyVaultSecret secret = _detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(response);
|
||||
runFullExpect(secret);
|
||||
}
|
||||
|
||||
TEST(KeyVaultSecretSerializer, GetClientdeserializeFull2)
|
||||
{
|
||||
auto response = getFullResponse();
|
||||
|
||||
KeyVaultSecret secret
|
||||
= _detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize("name1", response);
|
||||
|
||||
runFullExpect(secret);
|
||||
}
|
||||
|
||||
TEST(KeyVaultSecretSerializer, GetClientdeserializeFull3)
|
||||
{
|
||||
auto response = getFullResponse();
|
||||
|
||||
KeyVaultSecret secret = KeyVaultSecret("name2", "");
|
||||
_detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(secret, response);
|
||||
|
||||
runFullExpect(secret);
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/core/http/http.hpp"
|
||||
#include "azure/core/http/policies/policy.hpp"
|
||||
#include "azure/keyvault/secrets/keyvault_secret.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace Azure::Core::Http::_internal;
|
||||
|
||||
namespace {
|
||||
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": "mysecretvalue",
|
||||
"id": "https://myvault.vault.azure.net/secrets/mysecretname/4387e9f3d6e14c459867679a90fd0f79",
|
||||
"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<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
|
||||
response.SetBodyStream(
|
||||
std::make_unique<Azure::Core::IO::MemoryBodyStream>(responseBody, sizeof(responseBody) - 1));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
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": "mysecretvalue",
|
||||
"id": "https://myvault.vault.azure.net/secrets/mysecretname/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<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
|
||||
response.SetBodyStream(
|
||||
std::make_unique<Azure::Core::IO::MemoryBodyStream>(responseBody, sizeof(responseBody) - 1));
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void runPartialExpect(KeyVaultSecret& secret)
|
||||
{
|
||||
EXPECT_EQ(secret.Name, "mysecretname");
|
||||
EXPECT_EQ(secret.Value, "mysecretvalue");
|
||||
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/mysecretname/4387e9f3d6e14c459867679a90fd0f79");
|
||||
EXPECT_EQ(secret.Properties.KeyId.HasValue(), false);
|
||||
EXPECT_EQ(secret.Properties.Enabled.Value(), true);
|
||||
EXPECT_EQ(secret.Properties.Managed, false);
|
||||
EXPECT_EQ(secret.Properties.UpdatedOn.HasValue(), true);
|
||||
EXPECT_EQ(secret.Properties.CreatedOn.HasValue(), true);
|
||||
}
|
||||
|
||||
void runFullExpect(KeyVaultSecret& secret)
|
||||
{
|
||||
EXPECT_EQ(secret.Name, "mysecretname");
|
||||
EXPECT_EQ(secret.Value, "mysecretvalue");
|
||||
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/mysecretname/4387e9f3d6e14c459867679a90fd0f79");
|
||||
EXPECT_EQ(secret.Properties.Enabled.Value(), true);
|
||||
EXPECT_EQ(secret.Properties.Managed, true);
|
||||
EXPECT_EQ(secret.Properties.ContentType.Value(), "ct");
|
||||
EXPECT_EQ(secret.Properties.KeyId.Value(), "kid");
|
||||
EXPECT_EQ(secret.Properties.UpdatedOn.HasValue(), true);
|
||||
EXPECT_EQ(secret.Properties.CreatedOn.HasValue(), true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Loading…
Reference in New Issue
Block a user