[Keyvault] APIs (#1967)
Adding the next APIs: UpdateKeyProperties, fixes: #1541 GetPropertiesOfKeys , fixes: #1542 GetPropertiesOfKeyVersions, fixes: #1543 GetDeletedKeys, fixes: #1546 PurgeDeletedKey, fixes: #1547 StartRecoveryDeletedKey, fixes: #1548 BackupKey, fixes: #1549 RestoreKeyBackup, fixes: #1550 ImportKey, fixes: #1551 Add samples, fixes: #1987
This commit is contained in:
parent
7490709db4
commit
a4ae81708b
@ -25,7 +25,7 @@ namespace Azure { namespace Core { namespace Json { namespace _internal {
|
||||
{
|
||||
/**
|
||||
* @brief If the optional key \p key is present in the json node \p jsonKey set the value of \p
|
||||
* destination.
|
||||
* the Nullable destination.
|
||||
*
|
||||
* @remark If the key is not in the json node, the \p destination is not modified.
|
||||
*
|
||||
@ -39,7 +39,7 @@ namespace Azure { namespace Core { namespace Json { namespace _internal {
|
||||
Azure::Core::Json::_internal::json const& jsonKey,
|
||||
std::string const& key) noexcept
|
||||
{
|
||||
if (jsonKey.contains(key))
|
||||
if (jsonKey.contains(key) && !jsonKey[key].is_null()) // In Json and not-Null
|
||||
{
|
||||
destination = jsonKey[key].get<T>();
|
||||
}
|
||||
@ -54,6 +54,36 @@ namespace Azure { namespace Core { namespace Json { namespace _internal {
|
||||
* @param jsonKey The json node to review.
|
||||
* @param key The key name for the optional property.
|
||||
* @param destination The value to update if the key name property is in the json node.
|
||||
* @param decorator A callback used to convert the Json value from `V` type to the `T` type. For
|
||||
* example, getting std::string from Json (the V type) and setting a Nullable<Datatime> (where T
|
||||
* type is Datetime), the decorator would define how to create the Datetime from the
|
||||
* std::string.
|
||||
*/
|
||||
template <class V, class T>
|
||||
static inline void SetIfExists(
|
||||
T& destination,
|
||||
Azure::Core::Json::_internal::json const& jsonKey,
|
||||
std::string const& key,
|
||||
std::function<T(V value)> decorator) noexcept
|
||||
{
|
||||
if (jsonKey.contains(key))
|
||||
{
|
||||
if (!jsonKey[key].is_null())
|
||||
{
|
||||
destination = decorator(jsonKey[key].get<V>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief If the optional key \p key is present in the json node \p jsonKey set the value of \p
|
||||
* the Nullable destination.
|
||||
*
|
||||
* @remark If the key is not in the json node, the \p destination is not modified.
|
||||
*
|
||||
* @param jsonKey The json node to review.
|
||||
* @param key The key name for the optional property.
|
||||
* @param destination The value to update if the key name property is in the json node.
|
||||
* @param decorator A optional function to update the json value before updating the \p
|
||||
* destination.
|
||||
*/
|
||||
@ -71,4 +101,29 @@ namespace Azure { namespace Core { namespace Json { namespace _internal {
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
static inline void SetFromNullable(
|
||||
Azure::Nullable<T> const& source,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName,
|
||||
std::function<R(T const&)> factory)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
jsonKey[keyName] = factory(source.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void SetFromNullable(
|
||||
Azure::Nullable<T> const& source,
|
||||
Azure::Core::Json::_internal::json& jsonKey,
|
||||
std::string const& keyName)
|
||||
{
|
||||
if (source)
|
||||
{
|
||||
jsonKey[keyName] = source.GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
}}}} // namespace Azure::Core::Json::_internal
|
||||
|
||||
@ -25,6 +25,12 @@ namespace Azure { namespace Core { namespace Json { namespace _internal {
|
||||
* @return The json string representation.
|
||||
*/
|
||||
virtual std::string Serialize() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Default destructor for serializable objects.
|
||||
*
|
||||
*/
|
||||
virtual ~JsonSerializable() = default;
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Core::Json::_internal
|
||||
|
||||
@ -243,6 +243,13 @@ namespace Azure { namespace Core {
|
||||
*/
|
||||
std::string GetUrlWithoutQuery() const { return GetUrlWithoutQuery(false); }
|
||||
|
||||
/**
|
||||
* @brief Get Scheme, host and port.
|
||||
*
|
||||
* @return Url authority.
|
||||
*/
|
||||
std::string GetUrlAuthorityWithScheme() const;
|
||||
|
||||
/**
|
||||
* @brief Get the path and query parameters.
|
||||
*
|
||||
|
||||
@ -178,21 +178,29 @@ void Url::AppendQueryParameters(const std::string& query)
|
||||
}
|
||||
}
|
||||
|
||||
std::string Url::GetUrlAuthorityWithScheme() const
|
||||
{
|
||||
std::string url;
|
||||
|
||||
if (!m_scheme.empty())
|
||||
{
|
||||
url += m_scheme + "://";
|
||||
}
|
||||
url += m_host;
|
||||
if (m_port != 0)
|
||||
{
|
||||
url += ":" + std::to_string(m_port);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
std::string Url::GetUrlWithoutQuery(bool relative) const
|
||||
{
|
||||
std::string url;
|
||||
|
||||
if (!relative)
|
||||
{
|
||||
if (!m_scheme.empty())
|
||||
{
|
||||
url += m_scheme + "://";
|
||||
}
|
||||
url += m_host;
|
||||
if (m_port != 0)
|
||||
{
|
||||
url += ":" + std::to_string(m_port);
|
||||
}
|
||||
url += GetUrlAuthorityWithScheme();
|
||||
}
|
||||
|
||||
if (!m_encodedPath.empty())
|
||||
|
||||
@ -59,7 +59,7 @@ namespace Azure { namespace Perf { namespace Test {
|
||||
Azure::Core::Http::Request request(Azure::Core::Http::HttpMethod::Get, m_url);
|
||||
auto response = _detail::HttpClient->Send(request, ctx);
|
||||
// Read the body from network
|
||||
auto bodyStream = response->GetBodyStream();
|
||||
auto bodyStream = response->ExtractBodyStream();
|
||||
response->SetBody(bodyStream->ReadToEnd(ctx));
|
||||
}
|
||||
|
||||
|
||||
@ -28,8 +28,10 @@ endif()
|
||||
|
||||
set(
|
||||
AZURE_KEYVAULT_COMMON_HEADER
|
||||
inc/azure/keyvault/common/internal/base64url.hpp
|
||||
inc/azure/keyvault/common/internal/keyvault_pipeline.hpp
|
||||
inc/azure/keyvault/common/internal/unix_time_helper.hpp
|
||||
inc/azure/keyvault/common/client_options.hpp
|
||||
inc/azure/keyvault/common/keyvault_constants.hpp
|
||||
inc/azure/keyvault/common/keyvault_exception.hpp
|
||||
inc/azure/keyvault/common/version.hpp
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Defines the base options to create a Key Vault client.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/internal/client_options.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Common {
|
||||
|
||||
/**
|
||||
* @brief Available and supported service versions.
|
||||
*
|
||||
*/
|
||||
enum class ServiceVersion
|
||||
{
|
||||
/**
|
||||
* @brief Use to send request to the 7.0 version of Key Vault service.
|
||||
*
|
||||
*/
|
||||
V7_0,
|
||||
/**
|
||||
* @brief Use to send request to the 7.1 version of Key Vault service.
|
||||
*
|
||||
*/
|
||||
V7_1,
|
||||
/**
|
||||
* @brief Use to send request to the 7.2 version of Key Vault service.
|
||||
*
|
||||
*/
|
||||
V7_2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Define the base options to create an KeyVault SDK client.
|
||||
*
|
||||
*/
|
||||
struct ClientOptions : public Azure::Core::_internal::ClientOptions
|
||||
{
|
||||
/**
|
||||
* @brief The service version. All request are created with this version.
|
||||
*
|
||||
*/
|
||||
ServiceVersion Version;
|
||||
|
||||
ClientOptions(ServiceVersion version)
|
||||
: Azure::Core::_internal::ClientOptions(), Version(version)
|
||||
{
|
||||
}
|
||||
|
||||
std::string GetVersionString() const
|
||||
{
|
||||
switch (Version)
|
||||
{
|
||||
case ServiceVersion::V7_0:
|
||||
return "7.0";
|
||||
case ServiceVersion::V7_1:
|
||||
return "7.1";
|
||||
case ServiceVersion::V7_2:
|
||||
return "7.2";
|
||||
default:
|
||||
throw std::runtime_error("Version not found");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Common
|
||||
@ -0,0 +1,59 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief Provides helper method for base64url.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <azure/core/base64.hpp>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Common { namespace _internal {
|
||||
|
||||
/**
|
||||
* @brief Provides conversion methods for base64url.
|
||||
*/
|
||||
struct Base64Url
|
||||
{
|
||||
static inline std::string Base64UrlEncode(const std::vector<uint8_t>& data)
|
||||
{
|
||||
auto base64 = Azure::Core::Convert::Base64Encode(data);
|
||||
// update to base64url
|
||||
auto trail = base64.find('=');
|
||||
if (trail != std::string::npos)
|
||||
{
|
||||
base64 = base64.substr(0, trail);
|
||||
}
|
||||
std::replace(base64.begin(), base64.end(), '+', '-');
|
||||
std::replace(base64.begin(), base64.end(), '/', '_');
|
||||
return base64;
|
||||
}
|
||||
|
||||
static inline std::vector<uint8_t> Base64UrlDecode(const std::string& text)
|
||||
{
|
||||
std::string base64url(text);
|
||||
// base64url to base64
|
||||
std::replace(base64url.begin(), base64url.end(), '-', '+');
|
||||
std::replace(base64url.begin(), base64url.end(), '_', '/');
|
||||
switch (base64url.size() % 4)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 2:
|
||||
base64url.append("==");
|
||||
break;
|
||||
case 3:
|
||||
base64url.append("=");
|
||||
break;
|
||||
default:
|
||||
throw new std::invalid_argument("Unexpected base64 encoding in the http response.");
|
||||
}
|
||||
return Azure::Core::Convert::Base64Decode(base64url);
|
||||
}
|
||||
};
|
||||
}}}}} // namespace Azure::Security::KeyVault::Common::_internal
|
||||
@ -90,6 +90,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Common { n
|
||||
* @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>
|
||||
@ -97,9 +98,17 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Common { n
|
||||
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::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);
|
||||
return Azure::Response<T>(factoryFn(*response), std::move(response));
|
||||
}
|
||||
@ -132,6 +141,23 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Common { n
|
||||
return Azure::Response<T>(factoryFn(*response), 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);
|
||||
return Azure::Response<T>(factoryFn(*response), std::move(response));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a key vault request and send it using the Azure Core pipeline directly to avoid
|
||||
* checking the respone code.
|
||||
|
||||
@ -29,5 +29,18 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Common { n
|
||||
{
|
||||
return Azure::DateTime(1970) + std::chrono::seconds(unixTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a #Azure::Core::Datetime to unix time.
|
||||
*
|
||||
* @param dateTime The date time to convert.
|
||||
*/
|
||||
static inline uint64_t DatetimeToUnixTime(Azure::DateTime dateTime)
|
||||
{
|
||||
// This count starts at the Unix Epoch which was January 1st, 1970 at UTC.
|
||||
auto secondsSince1970
|
||||
= std::chrono::duration_cast<std::chrono::seconds>(dateTime - Azure::DateTime(1970));
|
||||
return secondsSince1970.count();
|
||||
}
|
||||
};
|
||||
}}}}} // namespace Azure::Security::KeyVault::Common::_internal
|
||||
|
||||
@ -30,17 +30,21 @@ set(
|
||||
AZURE_KEYVAULT_KEYS_HEADER
|
||||
inc/azure/keyvault/keys/delete_key_operation.hpp
|
||||
inc/azure/keyvault/keys/deleted_key.hpp
|
||||
inc/azure/keyvault/keys/details/key_backup.hpp
|
||||
inc/azure/keyvault/keys/details/key_constants.hpp
|
||||
inc/azure/keyvault/keys/details/key_request_parameters.hpp
|
||||
inc/azure/keyvault/keys/import_key_options.hpp
|
||||
inc/azure/keyvault/keys/json_web_key.hpp
|
||||
inc/azure/keyvault/keys/key_client.hpp
|
||||
inc/azure/keyvault/keys/details/key_constants.hpp
|
||||
inc/azure/keyvault/keys/key_create_options.hpp
|
||||
inc/azure/keyvault/keys/key_curve_name.hpp
|
||||
inc/azure/keyvault/keys/key_client_options.hpp
|
||||
inc/azure/keyvault/keys/key_operation.hpp
|
||||
inc/azure/keyvault/keys/key_properties.hpp
|
||||
inc/azure/keyvault/keys/details/key_request_parameters.hpp
|
||||
inc/azure/keyvault/keys/key_type.hpp
|
||||
inc/azure/keyvault/keys/key_vault_key.hpp
|
||||
inc/azure/keyvault/keys/list_keys_single_page_result.hpp
|
||||
inc/azure/keyvault/keys/recover_deleted_key_operation.hpp
|
||||
inc/azure/keyvault/keys/version.hpp
|
||||
)
|
||||
|
||||
@ -48,11 +52,16 @@ set(
|
||||
AZURE_KEYVAULT_KEYS_SOURCE
|
||||
src/delete_key_operation.cpp
|
||||
src/deleted_key.cpp
|
||||
src/import_key_options.cpp
|
||||
src/json_web_key.cpp
|
||||
src/key_backup.cpp
|
||||
src/key_client.cpp
|
||||
src/key_curve_name.cpp
|
||||
src/key_request_parameters.cpp
|
||||
src/key_type.cpp
|
||||
src/key_vault_key.cpp
|
||||
src/list_keys_single_page_result.cpp
|
||||
src/recover_deleted_key_operation.cpp
|
||||
)
|
||||
|
||||
add_library(azure-security-keyvault-keys
|
||||
@ -90,7 +99,7 @@ if (BUILD_PERFORMANCE_TESTS)
|
||||
endif()
|
||||
|
||||
if(BUILD_SAMPLES)
|
||||
add_subdirectory(sample)
|
||||
add_subdirectory(test/samples)
|
||||
endif()
|
||||
|
||||
az_vcpkg_export(
|
||||
|
||||
@ -11,10 +11,16 @@
|
||||
#include "azure/keyvault/keys/delete_key_operation.hpp"
|
||||
#include "azure/keyvault/keys/deleted_key.hpp"
|
||||
#include "azure/keyvault/keys/dll_import_export.hpp"
|
||||
#include "azure/keyvault/keys/import_key_options.hpp"
|
||||
#include "azure/keyvault/keys/json_web_key.hpp"
|
||||
#include "azure/keyvault/keys/key_client.hpp"
|
||||
#include "azure/keyvault/keys/key_client_options.hpp"
|
||||
#include "azure/keyvault/keys/key_create_options.hpp"
|
||||
#include "azure/keyvault/keys/key_curve_name.hpp"
|
||||
#include "azure/keyvault/keys/key_operation.hpp"
|
||||
#include "azure/keyvault/keys/key_properties.hpp"
|
||||
#include "azure/keyvault/keys/key_type.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
#include "azure/keyvault/keys/list_keys_single_page_result.hpp"
|
||||
#include "azure/keyvault/keys/recover_deleted_key_operation.hpp"
|
||||
#include "azure/keyvault/keys/version.hpp"
|
||||
|
||||
@ -53,12 +53,4 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
*/
|
||||
Azure::DateTime ScheduledPurgeDate;
|
||||
};
|
||||
|
||||
/*********************** Deserializer / Serializer ******************************/
|
||||
namespace _detail {
|
||||
DeletedKey DeletedKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
} // namespace _detail
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Internal wrapper layer on top of a uint_8 array.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/internal/json/json_serializable.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail {
|
||||
|
||||
struct KeyBackup : public Azure::Core::Json::_internal::JsonSerializable
|
||||
{
|
||||
|
||||
std::vector<uint8_t> Value;
|
||||
|
||||
std::string Serialize() const override;
|
||||
|
||||
static KeyBackup Deserialize(Azure::Core::Http::RawResponse const& rawResponse);
|
||||
};
|
||||
}}}}} // namespace Azure::Security::KeyVault::Keys::_detail
|
||||
@ -22,6 +22,13 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
|
||||
constexpr static const char AttributesPropertyName[] = "attributes";
|
||||
constexpr static const char TagsPropertyName[] = "tags";
|
||||
constexpr static const char ReleasePolicyPropertyName[] = "release_policy";
|
||||
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 RecoverableDaysPropertyName[] = "recoverableDays";
|
||||
constexpr static const char RecoveryLevelPropertyName[] = "recoveryLevel";
|
||||
|
||||
/***************** Key Request Parameters *****************/
|
||||
constexpr static const char KeyTypePropertyName[] = "kty";
|
||||
@ -69,4 +76,21 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
|
||||
constexpr static const char P384OidValue[] = "1.3.132.0.34";
|
||||
constexpr static const char P521OidValue[] = "1.3.132.0.35";
|
||||
|
||||
/***************** Import Key *****************/
|
||||
constexpr static const char HsmPropertyName[] = "hsm";
|
||||
|
||||
/***************** Encryption Algorithm *********/
|
||||
constexpr static const char Rsa15Value[] = "RSA1_5";
|
||||
constexpr static const char RsaOaepValue[] = "RSA-OAEP";
|
||||
constexpr static const char RsaOaep256Value[] = "RSA-OAEP-256";
|
||||
constexpr static const char A128GcmValue[] = "A128GCM";
|
||||
constexpr static const char A192GcmValue[] = "A192GCM";
|
||||
constexpr static const char A256GcmValue[] = "A256GCM";
|
||||
constexpr static const char A128CbcValue[] = "A128CBC";
|
||||
constexpr static const char A192CbcValue[] = "A192CBC";
|
||||
constexpr static const char A256CbcValue[] = "A256CBC";
|
||||
constexpr static const char A128CbcPadValue[] = "A128CBCPAD";
|
||||
constexpr static const char A192CbcPadValue[] = "A192CBCPAD";
|
||||
constexpr static const char A256CbcPadValue[] = "A256CBCPAD";
|
||||
|
||||
}}}}} // namespace Azure::Security::KeyVault::Keys::_detail
|
||||
|
||||
@ -17,22 +17,51 @@
|
||||
#include "azure/keyvault/keys/key_type.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail {
|
||||
|
||||
class KeyRequestParameters : public Azure::Core::Json::_internal::JsonSerializable {
|
||||
private:
|
||||
JsonWebKeyType m_keyType;
|
||||
CreateKeyOptions const& m_options;
|
||||
Azure::Nullable<JsonWebKeyType> m_keyType;
|
||||
CreateKeyOptions m_options;
|
||||
|
||||
public:
|
||||
Azure::Nullable<KeyCurveName> Curve;
|
||||
Azure::Nullable<uint64_t> KeySize;
|
||||
Azure::Nullable<uint64_t> PublicExponent;
|
||||
|
||||
explicit KeyRequestParameters(
|
||||
KeyProperties const& key,
|
||||
Azure::Nullable<std::list<KeyOperation>> const& operations)
|
||||
: m_options(CreateKeyOptions())
|
||||
{
|
||||
if (key.Enabled)
|
||||
{
|
||||
m_options.Enabled = key.Enabled.GetValue();
|
||||
}
|
||||
if (key.ExpiresOn)
|
||||
{
|
||||
m_options.ExpiresOn = key.ExpiresOn.GetValue();
|
||||
}
|
||||
if (key.NotBefore)
|
||||
{
|
||||
m_options.NotBefore = key.NotBefore.GetValue();
|
||||
}
|
||||
if (key.Tags.size() > 0)
|
||||
{
|
||||
m_options.Tags = std::unordered_map<std::string, std::string>(key.Tags);
|
||||
}
|
||||
if (operations)
|
||||
{
|
||||
m_options.KeyOperations = std::list<KeyOperation>(operations.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
explicit KeyRequestParameters(JsonWebKeyType keyType, CreateKeyOptions const& options)
|
||||
: m_keyType(keyType), m_options(options)
|
||||
{
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Centralize the serialize and de-serialize methods for the key vault keys models.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/deleted_key.hpp"
|
||||
#include "azure/keyvault/keys/import_key_options.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
#include "azure/keyvault/keys/list_keys_single_page_result.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace _detail {
|
||||
/***************** KeyVault Key *****************/
|
||||
struct KeyVaultKeySerializer
|
||||
{
|
||||
// Creates a new key based on a name and an http raw response.
|
||||
static KeyVaultKey KeyVaultKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// Create from http raw response only.
|
||||
static KeyVaultKey KeyVaultKeyDeserialize(Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// Updates a Key based on an Http raw response.
|
||||
static void KeyVaultKeyDeserialize(
|
||||
KeyVaultKey& key,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// Create from json node directly. Used from listKeys
|
||||
static void KeyVaultKeyDeserialize(
|
||||
KeyVaultKey& key,
|
||||
Azure::Core::Json::_internal::json const& json);
|
||||
|
||||
void static inline ParseKeyUrl(KeyProperties& keyProperties, std::string const& url)
|
||||
{
|
||||
Azure::Core::Url kid(url);
|
||||
keyProperties.Id = url;
|
||||
keyProperties.VaultUrl = kid.GetUrlAuthorityWithScheme();
|
||||
auto const& path = kid.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)
|
||||
{
|
||||
keyProperties.Name = std::string(start, separator);
|
||||
start = separator + 1;
|
||||
keyProperties.Version = std::string(start, pathEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing but the name+
|
||||
keyProperties.Name = std::string(start, pathEnd);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************** Deleted Key *******************/
|
||||
struct DeletedKeySerializer
|
||||
{
|
||||
static DeletedKey DeletedKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
};
|
||||
|
||||
/**************** Import Key Options ***********/
|
||||
struct ImportKeyOptionsSerializer
|
||||
{
|
||||
static std::string ImportKeyOptionsSerialize(ImportKeyOptions const& importKeyOptions);
|
||||
};
|
||||
|
||||
/**************** Key Properties Single Page ************/
|
||||
struct KeyPropertiesSinglePageSerializer
|
||||
{
|
||||
static KeyPropertiesSinglePage KeyPropertiesSinglePageDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
static DeletedKeySinglePage DeletedKeySinglePageDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
};
|
||||
|
||||
}}}}} // namespace Azure::Security::KeyVault::Keys::_detail
|
||||
@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Defines the properties to import a Key.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/nullable.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/json_web_key.hpp"
|
||||
#include "azure/keyvault/keys/key_operation.hpp"
|
||||
#include "azure/keyvault/keys/key_properties.hpp"
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
|
||||
/**
|
||||
* @brief A key resource and its properties.
|
||||
*
|
||||
*/
|
||||
struct ImportKeyOptions
|
||||
{
|
||||
/**
|
||||
* @brief The cryptographic key, the key type, and the operations you can perform using the key.
|
||||
*
|
||||
*/
|
||||
JsonWebKey Key;
|
||||
|
||||
/**
|
||||
* @brief The additional properties.
|
||||
*
|
||||
*/
|
||||
KeyProperties Properties;
|
||||
|
||||
/**
|
||||
* @brief Get or Set a value indicating whether to import the key into a hardware security
|
||||
* module (HSM).
|
||||
*
|
||||
*/
|
||||
Azure::Nullable<bool> HardwareProtected;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Key Vault ImportKeyOptions object.
|
||||
*
|
||||
* @param name The name of the key.
|
||||
*/
|
||||
ImportKeyOptions(std::string name, JsonWebKey keyMaterial)
|
||||
: Key(keyMaterial), Properties(std::move(name))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the Key.
|
||||
*
|
||||
* @return The name of the key.
|
||||
*/
|
||||
std::string const& Name() const { return Properties.Name; }
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/nullable.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/key_curve_name.hpp"
|
||||
@ -71,8 +72,31 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
*/
|
||||
Azure::Nullable<KeyCurveName> CurveName;
|
||||
|
||||
/**** RSA fields ****/
|
||||
|
||||
/// The RSA modulus.
|
||||
std::vector<uint8_t> N;
|
||||
/// The RSA public exponent.
|
||||
std::vector<uint8_t> E;
|
||||
/// The RSA private key parameter.
|
||||
std::vector<uint8_t> DP;
|
||||
/// The RSA private key parameter.
|
||||
std::vector<uint8_t> DQ;
|
||||
/// The RSA private key parameter.
|
||||
std::vector<uint8_t> QI;
|
||||
/// The RSA secret prime.
|
||||
std::vector<uint8_t> P;
|
||||
/// The RSA secret prime.
|
||||
std::vector<uint8_t> Q;
|
||||
|
||||
/// The RSA private exponent or EC private key.
|
||||
std::vector<uint8_t> D;
|
||||
|
||||
private:
|
||||
std::vector<KeyOperation> m_keyOps;
|
||||
};
|
||||
|
||||
// Define the serialization of a JsonWebKey
|
||||
void to_json(Azure::Core::Json::_internal::json& j, JsonWebKey const& p);
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -12,16 +12,44 @@
|
||||
#include <azure/keyvault/common/internal/keyvault_pipeline.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/delete_key_operation.hpp"
|
||||
#include "azure/keyvault/keys/import_key_options.hpp"
|
||||
#include "azure/keyvault/keys/key_client_options.hpp"
|
||||
#include "azure/keyvault/keys/key_create_options.hpp"
|
||||
#include "azure/keyvault/keys/key_type.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
#include "azure/keyvault/keys/list_keys_single_page_result.hpp"
|
||||
#include "azure/keyvault/keys/recover_deleted_key_operation.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
|
||||
/**
|
||||
* @brief Define a model for a purged key.
|
||||
*
|
||||
*/
|
||||
struct PurgedKey
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for KeyVaultClient::GetKey
|
||||
*
|
||||
*/
|
||||
struct GetKeyOptions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
/**
|
||||
* @brief Specify the key version to get.
|
||||
*/
|
||||
std::string Version;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The KeyClient provides synchronous methods to manage a KeyVaultKe in the Azure Key
|
||||
* Vault. The client supports creating, retrieving, updating, deleting, purging, backing up,
|
||||
@ -45,22 +73,6 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
std::shared_ptr<Core::Credentials::TokenCredential const> credential,
|
||||
KeyClientOptions options = KeyClientOptions());
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for KeyVaultClient::GetKey
|
||||
*
|
||||
*/
|
||||
struct GetKeyOptions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
/**
|
||||
* @brief Specify the key version to get.
|
||||
*/
|
||||
std::string Version;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Gets the public part of a stored key.
|
||||
*
|
||||
@ -145,6 +157,55 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
CreateOctKeyOptions const& octKeyOptions,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Get a single page with the properties of all keys in the specified vault. You can use
|
||||
* the returned #KeyProperties.Name in subsequent calls to #GetKey.
|
||||
*
|
||||
* @remark Retrieves a list of the keys in the Key Vault that contains the public part of a
|
||||
* stored key. The operation is applicable to all key types, however only the base key
|
||||
* identifier, attributes, and tags are provided in the response. Individual versions of a key
|
||||
* are not listed in the response. This operation requires the keys/list permission.
|
||||
*
|
||||
* @remark Use \p options to control which page to get. If
|
||||
* #GetPropertiesOfKeysSinglePageOptions.NextLink is not set, the operation will get the first
|
||||
* page and it will set the `ContinuationToken` from the #KeyPropertiesSinglePage as the next
|
||||
* page of the response if there is a next page.
|
||||
*
|
||||
* @param options The #GetPropertiesOfKeysSinglePageOptions object to for setting the operation
|
||||
* up.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return Azure::Response<KeyPropertiesSinglePage>
|
||||
*/
|
||||
Azure::Response<KeyPropertiesSinglePage> GetPropertiesOfKeysSinglePage(
|
||||
GetPropertiesOfKeysSinglePageOptions const& options
|
||||
= GetPropertiesOfKeysSinglePageOptions(),
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Get one page listing the properties of all the versions of the specified key. You can
|
||||
* use the returned #KeyProperties.Name and #KeyProperties.Version in subsequent calls to
|
||||
* #GetKey.
|
||||
*
|
||||
* @remark The full identifier, attributes, and tags are provided in the response. This
|
||||
* operation requires the keys/list permission.
|
||||
*
|
||||
* @remark Use \p options to control which page to get. If
|
||||
* #GetPropertiesOfKeyVersionsSinglePageOptions.NextLink is not set, the operation will get the
|
||||
* first page and it will set the `ContinuationToken` from the #KeyPropertiesSinglePage as the
|
||||
* next page of the response if there is a next page.
|
||||
*
|
||||
* @param name The name of the key.
|
||||
* @param options The #GetPropertiesOfKeyVersionsSinglePageOptions object to for setting the
|
||||
* operation up.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return Azure::Response<KeyPropertiesSinglePage>
|
||||
*/
|
||||
Azure::Response<KeyPropertiesSinglePage> GetPropertiesOfKeyVersionsSinglePage(
|
||||
std::string const& name,
|
||||
GetPropertiesOfKeyVersionsSinglePageOptions const& options
|
||||
= GetPropertiesOfKeyVersionsSinglePageOptions(),
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes a key of any type from storage in Azure Key Vault.
|
||||
*
|
||||
@ -178,5 +239,156 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
Azure::Response<DeletedKey> GetDeletedKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Get on page listing the deleted keys in the specified vault.
|
||||
*
|
||||
* @remark Retrieves a list of the keys in the Key Vault that contains the public part od the
|
||||
* deleted key. This operation includes deletion-specific information. This operation is
|
||||
* applicable for vaults enabled fr soft-delete. While the operation can be invoked on any
|
||||
* vault, it will return error if invoked on a non soft-delete enabled vault. This operation
|
||||
* requires the keys/list permission.
|
||||
*
|
||||
* @remark Use \p options to control which page to get. If
|
||||
* #GetPropertiesOfKeyVersionsSinglePageOptions.NextLink is not set, the operation will get the
|
||||
* first page and it will set the `ContinuationToken` from the #KeyPropertiesSinglePage as the
|
||||
* next page of the response if there is a next page.
|
||||
*
|
||||
* @param options The #GetDeletedKeysSinglePageOptions object to for setting the operation up.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return Azure::Response<DeletedKeySinglePage>
|
||||
*/
|
||||
Azure::Response<DeletedKeySinglePage> GetDeletedKeysSinglePage(
|
||||
GetDeletedKeysSinglePageOptions const& options = GetDeletedKeysSinglePageOptions(),
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Permanently deletes the specified key.
|
||||
*
|
||||
* @remark The Purge Deleted Key operation is applicable for soft-delete enabled values. While
|
||||
* the operation can be invoked on any vault, it will return an error if invoked on a non
|
||||
* soft-delete enabled vault. This operation requires the keys/purge permission.
|
||||
*
|
||||
* @param name The name of the key.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
*/
|
||||
Azure::Response<PurgedKey> PurgeDeletedKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Recovers the deleted key to its latest version.
|
||||
*
|
||||
* @remark The Recover Deleted Key operation is applicable for deleted keys in soft-delete
|
||||
* enabled vaults. It recovers the deleted key back to its latest version under /keys. An
|
||||
* attempt to recover an non-deleted key will return an error. Consider this the inverse of the
|
||||
* delete operation on soft-delete enabled vaults. This operation requires the keys/recover
|
||||
* permission.
|
||||
*
|
||||
* @param name The name of the key.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation
|
||||
*/
|
||||
Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation StartRecoverDeletedKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief The update key operation changes specified attributes of a stored key and can be
|
||||
* applied to any key type and key version stored in Azure Key Vault.
|
||||
*
|
||||
* @remark In order to perform this operation, the key must already exist in the Key Vault.
|
||||
* Note: The cryptographic material of a key itself cannot be changed. This operation requires
|
||||
* the keys/update permission.
|
||||
*
|
||||
* @param properties The #KeyProperties object with updated properties.
|
||||
* @param keyOperations Optional list of supported #KeyOperation. If no operation list provided,
|
||||
* no changes will be made to existing key operations.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return Azure::Response<KeyVaultKey>
|
||||
*/
|
||||
Azure::Response<KeyVaultKey> UpdateKeyProperties(
|
||||
KeyProperties const& properties,
|
||||
Azure::Nullable<std::list<KeyOperation>> const& keyOperations
|
||||
= Azure::Nullable<std::list<KeyOperation>>(),
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Request that a backup of the specified be downloaded to the client.
|
||||
*
|
||||
* @remark The Key Backup operation exports a key from Azure Key Vault in a protected form. Note
|
||||
* that this operation does NOT return the actual key in a form that can be used outside the
|
||||
* Azure Key Vault system, the returned key is either protected to a Azure Key Vault HSM or to
|
||||
* Azure Key Vault itself. The intent of this operation is to allow a client to GENERATE a key
|
||||
* in one Azure Key Vault instance, BACKUP the key, and then RESTORE it into another Azure Key
|
||||
* Vault instance. The BACKUP operation may be used to export, in protected form, any key type
|
||||
* from Azure Key Vault. Individual versions of a key cannot be backed up. BACKUP / RESTORE can
|
||||
* be performed within geographical boundaries only; meaning that a BACKUP from one geographical
|
||||
* are cannot be restored to another geographical are. For example, a backup from the US
|
||||
* geographical are cannot be restored in an EU geographical area. This operation requires the
|
||||
* key/backup permission.
|
||||
*
|
||||
* @param name The name of the key.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
*/
|
||||
Azure::Response<std::vector<uint8_t>> BackupKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Restores a backed up key to keyvault.
|
||||
*
|
||||
* @remark Imports a previously backed up key into Azure Key Vault, restoring the key, its key
|
||||
* identifier, attributes, and access control policies. The RESTORE operation may be used to
|
||||
* import a previously backed up key. Individual versions of a key cannot be restored. The key
|
||||
* is restored in its entirety with the same key name as it had when it was backed up. If the
|
||||
* key name is not available in the target Key Vault, the RESTORE operation will be rejected.
|
||||
* While the key name is retained during restore, the final key identifier will change if the
|
||||
* key is restored to a different vault. Restore will restore all versions and preserve version
|
||||
* identifiers. The RESTORE operation is subject to security constrains: The target Key Vault
|
||||
* must be owned by the same Microsoft Azure Subscription as the source Key Vault. The user must
|
||||
* have RESTORE permission in the target Key Vault. This operation requires the keys/restore
|
||||
* permission.
|
||||
*
|
||||
* @param backup The backup blob associated with a key.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
*/
|
||||
Azure::Response<KeyVaultKey> RestoreKeyBackup(
|
||||
std::vector<uint8_t> const& backup,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Imports an externally created ket, stores it, and returns jey parameters and
|
||||
* attributes to the client.
|
||||
*
|
||||
* @remark The import key operation may be used to import any key type into an Azure Key Vault.
|
||||
* If the named key already exists, Azure Key Vault creates a new version of the key. This
|
||||
* operation requires the keys/import permission.
|
||||
*
|
||||
* @param name The name of the key.
|
||||
* @param keyMaterial The #JsonWebKey being imported.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
* @return Azure::Response<KeyVaultKey>
|
||||
*/
|
||||
Azure::Response<KeyVaultKey> ImportKey(
|
||||
std::string const& name,
|
||||
JsonWebKey const& keyMaterial,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Imports an externally created key, stores it, and returns key parameters and
|
||||
* attributes to the client.
|
||||
*
|
||||
* @remark The import operation may be used to import any key type into an Azure Key Vault. If
|
||||
* the named key already exists, Azure Key Vault creates a new version of the key. This
|
||||
* operation requires the keys/import permission.
|
||||
*
|
||||
* @param importKeyOptions The key import configuration object containing information about the
|
||||
* #JsonWebKey being imported.
|
||||
* @param context A #Azure::Core::Context controlling the request lifetime.
|
||||
*/
|
||||
Azure::Response<KeyVaultKey> ImportKey(
|
||||
ImportKeyOptions const& importKeyOptions,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -9,61 +9,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/internal/client_options.hpp>
|
||||
#include <azure/core/response.hpp>
|
||||
#include <azure/keyvault/common/client_options.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
|
||||
/**
|
||||
* @brief Available and supported service versions.
|
||||
*
|
||||
*/
|
||||
enum class ServiceVersion
|
||||
{
|
||||
V7_0,
|
||||
V7_1,
|
||||
V7_2
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Define the options to create an SDK Keys client.
|
||||
*
|
||||
*/
|
||||
struct KeyClientOptions : public Azure::Core::_internal::ClientOptions
|
||||
struct KeyClientOptions : public Azure::Security::KeyVault::Common::ClientOptions
|
||||
{
|
||||
/**
|
||||
* @brief The service version. All request are created with this version.
|
||||
*
|
||||
*/
|
||||
ServiceVersion Version;
|
||||
|
||||
/**
|
||||
* @brief Construct a new Key Client Options object.
|
||||
*
|
||||
* @param version Optional version for the client.
|
||||
*/
|
||||
KeyClientOptions(ServiceVersion version = ServiceVersion::V7_2)
|
||||
: ClientOptions(), Version(version)
|
||||
KeyClientOptions(
|
||||
Azure::Security::KeyVault::Common::ServiceVersion version
|
||||
= Azure::Security::KeyVault::Common::ServiceVersion::V7_2)
|
||||
: ClientOptions(version)
|
||||
{
|
||||
}
|
||||
|
||||
std::string GetVersionString() const
|
||||
{
|
||||
switch (Version)
|
||||
{
|
||||
case ServiceVersion::V7_0:
|
||||
return "7.0";
|
||||
case ServiceVersion::V7_1:
|
||||
return "7.1";
|
||||
case ServiceVersion::V7_2:
|
||||
return "7.2";
|
||||
default:
|
||||
throw std::runtime_error("Version not found");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -53,7 +53,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
* Key Vault certificate, the value will be true.
|
||||
*
|
||||
*/
|
||||
bool Managed;
|
||||
bool Managed = false;
|
||||
|
||||
/**
|
||||
* @brief Dictionary of tags with specific metadata about the key.
|
||||
|
||||
@ -52,9 +52,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
OctHsm,
|
||||
};
|
||||
|
||||
namespace _detail {
|
||||
JsonWebKeyType KeyTypeFromString(std::string const& name);
|
||||
std::string KeyTypeToString(JsonWebKeyType kty);
|
||||
} // namespace _detail
|
||||
struct KeyType
|
||||
{
|
||||
static JsonWebKeyType KeyTypeFromString(std::string const& name);
|
||||
static std::string KeyTypeToString(JsonWebKeyType kty);
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -15,8 +15,8 @@
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
|
||||
/**
|
||||
@ -78,18 +78,4 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
*/
|
||||
std::vector<KeyOperation> const& KeyOperations() const { return Key.KeyOperations(); }
|
||||
};
|
||||
|
||||
/*********************** Deserializer / Serializer ******************************/
|
||||
namespace _detail {
|
||||
// Creates a new key based on a name and an http raw response.
|
||||
KeyVaultKey KeyVaultKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
|
||||
// Updates a Key based on an Http raw response.
|
||||
void KeyVaultKeyDeserialize(
|
||||
KeyVaultKey& key,
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
} // namespace _detail
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Defines a page of listing keys from a Key Vault.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "azure/keyvault/keys/deleted_key.hpp"
|
||||
#include "azure/keyvault/keys/json_web_key.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
|
||||
struct SinglePage
|
||||
{
|
||||
Azure::Nullable<std::string> ContinuationToken;
|
||||
};
|
||||
|
||||
struct KeyPropertiesSinglePage : public SinglePage
|
||||
{
|
||||
std::vector<KeyProperties> Items;
|
||||
};
|
||||
|
||||
struct DeletedKeySinglePage : public SinglePage
|
||||
{
|
||||
std::vector<DeletedKey> Items;
|
||||
};
|
||||
|
||||
struct GetSinglePageOptions
|
||||
{
|
||||
Azure::Nullable<std::string> ContinuationToken;
|
||||
Azure::Nullable<uint32_t> MaxResults;
|
||||
};
|
||||
struct GetPropertiesOfKeysSinglePageOptions : public GetSinglePageOptions
|
||||
{
|
||||
};
|
||||
|
||||
struct GetPropertiesOfKeyVersionsSinglePageOptions : public GetSinglePageOptions
|
||||
{
|
||||
};
|
||||
|
||||
struct GetDeletedKeysSinglePageOptions : public GetSinglePageOptions
|
||||
{
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
@ -0,0 +1,103 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief A long-running operation for recovering a Key.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/operation.hpp>
|
||||
#include <azure/core/operation_status.hpp>
|
||||
#include <azure/core/response.hpp>
|
||||
|
||||
#include <azure/keyvault/common/internal/keyvault_pipeline.hpp>
|
||||
#include <azure/keyvault/common/keyvault_exception.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
|
||||
|
||||
/**
|
||||
* @brief A long running operation to recover a key.
|
||||
*
|
||||
*/
|
||||
class RecoverDeletedKeyOperation : public Azure::Core::Operation<KeyVaultKey> {
|
||||
private:
|
||||
/* RecoverDeletedKeyOperation can be constructed only by friends classes (internal creation).
|
||||
* The constructor is private and requires internal components.*/
|
||||
friend class KeyClient;
|
||||
|
||||
std::shared_ptr<Azure::Security::KeyVault::Common::_internal::KeyVaultPipeline> m_pipeline;
|
||||
Azure::Security::KeyVault::Keys::KeyVaultKey m_value;
|
||||
std::string m_continuationToken;
|
||||
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> PollInternal(
|
||||
Azure::Core::Context& context) override;
|
||||
|
||||
Azure::Response<Azure::Security::KeyVault::Keys::KeyVaultKey> PollUntilDoneInternal(
|
||||
std::chrono::milliseconds period,
|
||||
Azure::Core::Context& context) override
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
// Poll will update the raw response.
|
||||
Poll(context);
|
||||
if (IsDone())
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(period);
|
||||
}
|
||||
|
||||
return Azure::Response<Azure::Security::KeyVault::Keys::KeyVaultKey>(
|
||||
m_value, std::make_unique<Azure::Core::Http::RawResponse>(*m_rawResponse));
|
||||
}
|
||||
|
||||
/*
|
||||
* Only friend classes are permitted to construct a RecoverDeletedKeyOperation. This is because
|
||||
* a KeyVaultPipelne is required and it is not exposed to customers.
|
||||
*
|
||||
* Since C++ doesn't offer `internal` access, we use friends-only instead.
|
||||
*/
|
||||
RecoverDeletedKeyOperation(
|
||||
std::shared_ptr<Azure::Security::KeyVault::Common::_internal::KeyVaultPipeline>
|
||||
keyvaultPipeline,
|
||||
Azure::Response<Azure::Security::KeyVault::Keys::KeyVaultKey> response);
|
||||
|
||||
/**
|
||||
* @brief Get the #Azure::Core::Http::RawResponse of the operation request.
|
||||
* @return A reference to an #Azure::Core::Http::RawResponse.
|
||||
* @note Does not give up ownership of the RawResponse.
|
||||
*/
|
||||
Azure::Core::Http::RawResponse const& GetRawResponseInternal() const override
|
||||
{
|
||||
return *m_rawResponse;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the #Azure::Security::KeyVault::Keys::KeyVaultKey object.
|
||||
*
|
||||
* @remark The deleted key contains the recovery id if the key can be recovered.
|
||||
*
|
||||
* @return A deleted key object.
|
||||
*/
|
||||
Azure::Security::KeyVault::Keys::KeyVaultKey Value() const override { return m_value; }
|
||||
|
||||
/**
|
||||
* @brief Get an Url as string which can be used to get the status of the delete key operation.
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
std::string GetResumeToken() const override { return m_continuationToken; }
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Keys
|
||||
@ -1,15 +0,0 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (azure-security-keyvault-keys-sample-get-key LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
azure-security-keyvault-keys-sample-get-key
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(azure-security-keyvault-keys-sample-get-key PRIVATE azure-security-keyvault-keys azure-identity)
|
||||
@ -1,70 +0,0 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief The next sample provides the code implementation to use the Key Vault SDK client for C++
|
||||
* to create a key client and get a key from Key Vault service.
|
||||
*
|
||||
* @remark Make sure to set the next environment variables before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the KeyVault account url.
|
||||
* - AZURE_KEYVAULT_TENANT_ID: Tenant id for the Azure account.
|
||||
* - AZURE_KEYVAULT_CLIENT_ID: The client id to authenticate the request.
|
||||
* - AZURE_KEYVAULT_CLIENT_SECRET: The secret id from the client id.
|
||||
*
|
||||
* Also, make sure the key is already created. Then set the key name as `KEY_VAULT_KEY_NAME` before
|
||||
* the main() method below.
|
||||
*
|
||||
* @remark The sample has logging enabled and will log the HTTP response into the standard output.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/logging/logging.hpp>
|
||||
#include <azure/identity/client_secret_credential.hpp>
|
||||
#include <azure/keyvault/common/keyvault_exception.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
// Define the name of the key to get
|
||||
#define KEY_VAULT_KEY_NAME "keyName"
|
||||
|
||||
int main()
|
||||
{
|
||||
auto tenantId = std::getenv("AZURE_KEYVAULT_TENANT_ID");
|
||||
auto clientId = std::getenv("AZURE_KEYVAULT_CLIENT_ID");
|
||||
auto clientSecret = std::getenv("AZURE_KEYVAULT_CLIENT_SECRET");
|
||||
auto credential
|
||||
= std::make_shared<Azure::Identity::ClientSecretCredential>(tenantId, clientId, clientSecret);
|
||||
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
try
|
||||
{
|
||||
auto responseT = keyClient.GetKey(KEY_VAULT_KEY_NAME);
|
||||
auto key = responseT.ExtractValue();
|
||||
std::cout << "KeyId: " << key.Key.Id << std::endl;
|
||||
std::cout << "Operations:" << std::endl;
|
||||
for (KeyOperation operation : key.KeyOperations())
|
||||
{
|
||||
std::cout << " - " << operation.ToString() << std::endl;
|
||||
}
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
}
|
||||
catch (Azure::Security::KeyVault::Common::KeyVaultException const& e)
|
||||
{
|
||||
std::cout << "KeyVault Client Exception happened:" << std::endl << e.Message << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
sdk/keyvault/azure-security-keyvault-keys/samples/README.md
Normal file
19
sdk/keyvault/azure-security-keyvault-keys/samples/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
page_type: sample
|
||||
languages:
|
||||
- c++ 14
|
||||
products:
|
||||
- azure
|
||||
- azure-key-vault
|
||||
name: Azure Security KeyVault Keys samples for C++
|
||||
description: Samples for the azure-security-keyVault-keys client library.
|
||||
---
|
||||
|
||||
# Azure.Security.KeyVault.Keys Samples
|
||||
|
||||
- Creating, getting, updating, and deleting keys
|
||||
- Back up and restore a key
|
||||
- Listing keys, key versions, and deleted keys
|
||||
- Encrypting and decrypt keys
|
||||
- Signing and verifying keys
|
||||
- Wrapping and unwrap a key
|
||||
@ -0,0 +1,101 @@
|
||||
# Creating, getting, updating, and deleting keys
|
||||
|
||||
This sample demonstrates how to create, get, update, and delete a key in Azure Key Vault.
|
||||
To get started, you'll need a URI to an Azure Key Vault. See the [README](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/keyvault/Azure.Security.KeyVault.Keys/README.md) for links and instructions.
|
||||
|
||||
## Creating a KeyClient
|
||||
|
||||
To create a new `KeyClient` to create, get, update, or delete keys, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Keys client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the tenant id, client id and client secret as environment variables.
|
||||
|
||||
```cpp Snippet:KeysSample1CreateCredential
|
||||
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);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:KeysSample1KeyClient
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a key
|
||||
|
||||
Let's create an RSA key valid for 1 year.
|
||||
If the key already exists in the Azure Key Vault, then a new version of the key is created.
|
||||
|
||||
```cpp Snippet:KeysSample1CreateKey
|
||||
auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
|
||||
rsaKey.KeySize = 2048;
|
||||
rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(rsaKey);
|
||||
```
|
||||
|
||||
## Getting a key
|
||||
|
||||
Let's get the cloud RSA key from the Azure Key Vault.
|
||||
|
||||
```cpp Snippet:KeysSample1GetKey
|
||||
KeyVaultKey cloudRsaKey = keyClient.GetKey(rsaKeyName).ExtractValue();
|
||||
std::cout << "Key is returned with name " << cloudRsaKey.Name() << " and type "
|
||||
<< KeyType::KeyTypeToString(cloudRsaKey.GetKeyType()) << std::endl;
|
||||
|
||||
```
|
||||
|
||||
## Updating key properties
|
||||
|
||||
After one year, the cloud RSA key is still required, so we need to update the expiry time of the key.
|
||||
The update method can be used to update the expiry attribute of the key.
|
||||
|
||||
```cpp Snippet:KeysSample1UpdateKeyProperties
|
||||
cloudRsaKey.Properties.ExpiresOn
|
||||
= cloudRsaKey.Properties.ExpiresOn.GetValue() + std::chrono::hours(24 * 365);
|
||||
KeyVaultKey updatedKey = keyClient.UpdateKeyProperties(cloudRsaKey.Properties).ExtractValue();
|
||||
std::cout << "Key's updated expiry time is " << updatedKey.Properties.ExpiresOn->ToString()
|
||||
<< std::endl;
|
||||
```
|
||||
|
||||
## Updating a key size
|
||||
|
||||
We need the cloud RSA key with bigger key size, so you want to update the key in Azure Key Vault to ensure it has the required size.
|
||||
Calling `CreateRsaKey` on an existing key creates a new version of the key in the Azure Key Vault with the new specified size.
|
||||
|
||||
```cpp Snippet:KeysSample1UpdateKey
|
||||
CreateRsaKeyOptions newRsaKey(rsaKeyName);
|
||||
newRsaKey.KeySize = 4096;
|
||||
newRsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(newRsaKey);
|
||||
```
|
||||
|
||||
## Deleting a key
|
||||
|
||||
The cloud RSA key is no longer needed, so we need to delete it from the Key Vault.
|
||||
|
||||
```cpp Snippet:KeysSample1DeleteKey
|
||||
DeleteKeyOperation operation = keyClient.StartDeleteKey(rsaKeyName);
|
||||
```
|
||||
|
||||
## Purging a deleted key
|
||||
|
||||
If the Azure Key Vault is soft delete-enabled and you want to permanently delete the key before its `ScheduledPurgeDate`,
|
||||
the deleted key needs to be purged. Before it can be purged, you need to wait until the key is fully deleted.
|
||||
|
||||
```cpp Snippet:KeysSample1PurgeKey
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
operation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
|
||||
keyClient.PurgeDeletedKey(rsaKeyName);
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
- sample1_hello_world.cpp
|
||||
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/README.md
|
||||
@ -0,0 +1,64 @@
|
||||
# Back up and restore a key
|
||||
|
||||
This sample demonstrates how to back up and restore a Key from Azure Key Vault.
|
||||
To get started, you'll need a URI to an Azure Key Vault. See the [README](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/keyvault/Azure.Security.KeyVault.Keys/README.md) for links and instructions.
|
||||
|
||||
## Creating a KeyClient
|
||||
|
||||
To create a new `KeyClient` to create, get, update, or delete keys, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Keys client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the tenant id, client id and client secret as environment variables.
|
||||
|
||||
```cpp Snippet:KeysSample1CreateCredential
|
||||
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);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:KeysSample1KeyClient
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a key
|
||||
|
||||
Let's create an RSA key valid for 1 year.
|
||||
If the key already exists in the Azure Key Vault, then a new version of the key is created.
|
||||
|
||||
```cpp Snippet:KeysSample1CreateKey
|
||||
auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
|
||||
rsaKey.KeySize = 2048;
|
||||
rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(rsaKey);
|
||||
```
|
||||
|
||||
## Backing up a key
|
||||
|
||||
You might make backups in case keys get accidentally deleted.
|
||||
For long term storage, it is ideal to write the backup to a file, disk, database, etc.
|
||||
For the purposes of this sample, we are storing the back up in a temporary memory area.
|
||||
|
||||
```cpp Snippet:KeysSample2BackupKey
|
||||
std::vector<uint8_t> backupKey(keyClient.BackupKey(rsaKeyName).ExtractValue());
|
||||
```
|
||||
|
||||
## Restoring a key
|
||||
|
||||
If the key is deleted for any reason, we can use the backup value to restore it in the Azure Key Vault.
|
||||
|
||||
```cpp Snippet:KeysSample2RestoreKey
|
||||
auto restoredKey = keyClient.RestoreKeyBackup(inMemoryBackup).ExtractValue();
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
To see the full example source, see:
|
||||
|
||||
- sample2_backup_and_restore.cpp
|
||||
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/README.md
|
||||
@ -0,0 +1,171 @@
|
||||
# Listing keys, key versions, and deleted keys
|
||||
|
||||
This sample demonstrates how to list keys and versions of a given key, and list deleted keys in a soft delete-enabled Key Vault.
|
||||
To get started, you'll need a URI to an Azure Key Vault. See the [README](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/keyvault/Azure.Security.KeyVault.Keys/README.md) for links and instructions.
|
||||
|
||||
## Creating a KeyClient
|
||||
|
||||
To create a new `KeyClient` to create, get, update, or delete keys, you need the endpoint to an Azure Key Vault and credentials.
|
||||
|
||||
Key Vault Keys client for C++ currently supports the `ClientSecretCredential` for authenticating.
|
||||
|
||||
In the sample below, you can create a credential by setting the tenant id, client id and client secret as environment variables.
|
||||
|
||||
```cpp Snippet:KeysSample1CreateCredential
|
||||
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);
|
||||
```
|
||||
|
||||
Then, in the sample below, you can set `keyVaultUrl` based on an environment variable, configuration setting, or any way that works for your application.
|
||||
|
||||
```cpp Snippet:KeysSample1KeyClient
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
```
|
||||
|
||||
## Creating a key
|
||||
|
||||
Let's create an RSA key valid for 1 year.
|
||||
If the key already exists in the Azure Key Vault, then a new version of the key is created.
|
||||
|
||||
```cpp Snippet:KeysSample1CreateKey
|
||||
std::string rsaKeyName("CloudRsaKey-" + Azure::Core::Uuid::CreateUuid().ToString());
|
||||
auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
|
||||
rsaKey.KeySize = 2048;
|
||||
rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
std::string ecKeyName("CloudEcKey-" + Azure::Core::Uuid::CreateUuid().ToString());
|
||||
auto ecKey = CreateEcKeyOptions(ecKeyName);
|
||||
ecKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
std::cout << "\t-Create Keys" << std::endl;
|
||||
keyClient.CreateRsaKey(rsaKey);
|
||||
keyClient.CreateEcKey(ecKey);
|
||||
```
|
||||
|
||||
## Listing keys
|
||||
|
||||
You need to check the type of keys that already exist in your Azure Key Vault.
|
||||
Let's list the keys and print their types. List operations don't return the actual key, but only properties of the key.
|
||||
So, for each returned key we call GetKey to get the actual key.
|
||||
|
||||
```cpp Snippet:KeysSample3ListKeys
|
||||
for (auto keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage().ExtractValue();;)
|
||||
{
|
||||
for (auto const& key : keysSinglePage.Items)
|
||||
{
|
||||
if (key.Managed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto keyWithType = keyClient.GetKey(key.Name).ExtractValue();
|
||||
std::cout << "Key is returned with name: " << keyWithType.Name()
|
||||
<< " and type: " << KeyType::KeyTypeToString(keyWithType.GetKeyType())
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (!keysSinglePage.ContinuationToken.HasValue())
|
||||
{
|
||||
// No more pages for the response, break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
GetPropertiesOfKeysSinglePageOptions options;
|
||||
options.ContinuationToken = keysSinglePage.ContinuationToken.GetValue();
|
||||
keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage(options).ExtractValue();
|
||||
}
|
||||
```
|
||||
|
||||
## Updating RSA key size
|
||||
|
||||
We need the cloud RSA key with bigger key size, so you want to update the key in Azure Key Vault to ensure it has the required size.
|
||||
Calling `CreateRsaKey` on an existing key creates a new version of the key in the Azure Key Vault with the new specified size.
|
||||
|
||||
```cpp Snippet:KeysSample3UpdateKey
|
||||
CreateRsaKeyOptions newRsaKey(rsaKeyName);
|
||||
newRsaKey.KeySize = 4096;
|
||||
newRsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(newRsaKey);
|
||||
```
|
||||
|
||||
## Listing key versions
|
||||
|
||||
You need to check all the different versions cloud RSA key had previously.
|
||||
Lets print all the versions of this key.
|
||||
|
||||
```cpp Snippet:KeysSample3ListKeyVersions
|
||||
for (auto keyVersionsSinglePage
|
||||
= keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName).ExtractValue();
|
||||
;)
|
||||
{
|
||||
for (auto const& key : keyVersionsSinglePage.Items)
|
||||
{
|
||||
std::cout << "Key's version: " << key.Version << " with name: " << key.Name << std::endl;
|
||||
}
|
||||
|
||||
if (!keyVersionsSinglePage.ContinuationToken.HasValue())
|
||||
{
|
||||
// No more pages for the response, break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
GetPropertiesOfKeyVersionsSinglePageOptions options;
|
||||
options.ContinuationToken = keyVersionsSinglePage.ContinuationToken.GetValue();
|
||||
keyVersionsSinglePage
|
||||
= keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName, options).ExtractValue();
|
||||
}
|
||||
```
|
||||
|
||||
## Deleting keys
|
||||
|
||||
The cloud RSA Key and the cloud EC keys are no longer needed.
|
||||
You need to delete them from the Azure Key Vault.
|
||||
|
||||
```cpp Snippet:KeysSample3DeletedKeys
|
||||
DeleteKeyOperation rsaOperation = keyClient.StartDeleteKey(rsaKeyName);
|
||||
DeleteKeyOperation ecOperation = keyClient.StartDeleteKey(ecKeyName);
|
||||
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
rsaOperation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
ecOperation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
```
|
||||
|
||||
## Listing deleted keys
|
||||
|
||||
You can list all the deleted and non-purged keys, assuming Azure Key Vault is soft delete-enabled.
|
||||
|
||||
```cpp Snippet:KeysSample3ListDeletedKeys
|
||||
nextPage = true;
|
||||
for (auto keysDeletedPage = keyClient.GetDeletedKeysSinglePage().ExtractValue();;)
|
||||
{
|
||||
for (auto const& key : keysDeletedPage.Items)
|
||||
{
|
||||
std::cout << "Deleted key's name: " << key.Name()
|
||||
<< ", recovery level: " << key.Properties.RecoveryLevel
|
||||
<< " and recovery Id: " << key.RecoveryId << std::endl;
|
||||
}
|
||||
|
||||
if (!keysDeletedPage.ContinuationToken.HasValue())
|
||||
{
|
||||
// No more pages for the response, break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
GetDeletedKeysSinglePageOptions options;
|
||||
options.ContinuationToken = keysDeletedPage.ContinuationToken.GetValue();
|
||||
keysDeletedPage = keyClient.GetDeletedKeysSinglePage(options).ExtractValue();
|
||||
}
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
To see the full example source, see:
|
||||
|
||||
- sample3_get_keys.cpp
|
||||
|
||||
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/README.md
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#include "azure/keyvault/keys/delete_key_operation.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
@ -38,7 +39,7 @@ Azure::Security::KeyVault::Keys::DeleteKeyOperation::PollInternal(Azure::Core::C
|
||||
m_status = CheckCompleted(*rawResponse);
|
||||
if (m_status == Azure::Core::OperationStatus::Succeeded)
|
||||
{
|
||||
m_value = _detail::DeletedKeyDeserialize(m_value.Name(), *rawResponse);
|
||||
m_value = _detail::DeletedKeySerializer::DeletedKeyDeserialize(m_value.Name(), *rawResponse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/keys/deleted_key.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
|
||||
#include <azure/keyvault/common/internal/unix_time_helper.hpp>
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include "azure/keyvault/keys/deleted_key.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using Azure::Security::KeyVault::Common::_internal::UnixTimeConverter;
|
||||
|
||||
DeletedKey _detail::DeletedKeyDeserialize(
|
||||
DeletedKey _detail::DeletedKeySerializer::DeletedKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
@ -21,16 +24,30 @@ DeletedKey _detail::DeletedKeyDeserialize(
|
||||
|
||||
// "Key"
|
||||
DeletedKey deletedKey(name);
|
||||
_detail::KeyVaultKeyDeserialize(deletedKey, rawResponse);
|
||||
_detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(deletedKey, rawResponse);
|
||||
|
||||
// recoveryId
|
||||
// deletedDate
|
||||
// scheduledPurgeDate
|
||||
deletedKey.RecoveryId = jsonParser[_detail::RecoveryIdPropertyName].get<std::string>();
|
||||
deletedKey.DeletedDate = UnixTimeConverter::UnixTimeToDatetime(
|
||||
jsonParser[_detail::DeletedOnPropertyName].get<uint64_t>());
|
||||
deletedKey.ScheduledPurgeDate = UnixTimeConverter::UnixTimeToDatetime(
|
||||
jsonParser[_detail::ScheduledPurgeDatePropertyName].get<uint64_t>());
|
||||
if (!jsonParser[_detail::RecoveryIdPropertyName].is_null())
|
||||
{
|
||||
deletedKey.RecoveryId = jsonParser[_detail::RecoveryIdPropertyName].get<std::string>();
|
||||
}
|
||||
if (!jsonParser[_detail::RecoveryLevelPropertyName].is_null())
|
||||
{
|
||||
deletedKey.Properties.RecoveryLevel
|
||||
= jsonParser[_detail::RecoveryLevelPropertyName].get<std::string>();
|
||||
}
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
deletedKey.DeletedDate,
|
||||
jsonParser,
|
||||
_detail::DeletedOnPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
deletedKey.ScheduledPurgeDate,
|
||||
jsonParser,
|
||||
_detail::ScheduledPurgeDatePropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
|
||||
return deletedKey;
|
||||
}
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
|
||||
#include <azure/keyvault/common/internal/unix_time_helper.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
#include "azure/keyvault/keys/import_key_options.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Security::KeyVault::Keys::_detail;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using namespace Azure::Security::KeyVault::Common::_internal;
|
||||
|
||||
std::string
|
||||
Azure::Security::KeyVault::Keys::_detail::ImportKeyOptionsSerializer::ImportKeyOptionsSerialize(
|
||||
ImportKeyOptions const& importKeyOptions)
|
||||
{
|
||||
|
||||
Azure::Core::Json::_internal::json payload;
|
||||
// key
|
||||
payload[_detail::KeyPropertyName] = importKeyOptions.Key;
|
||||
|
||||
// hsm
|
||||
SetFromNullable(importKeyOptions.HardwareProtected, payload, _detail::HsmPropertyName);
|
||||
|
||||
// attributes
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.CreatedOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::CreatedPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
SetFromNullable(
|
||||
importKeyOptions.Properties.Enabled,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::EnabledPropertyName);
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.ExpiresOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::ExpPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.NotBefore,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::NbfPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
SetFromNullable(
|
||||
importKeyOptions.Properties.RecoverableDays,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::RecoverableDaysPropertyName);
|
||||
|
||||
payload[_detail::RecoveryLevelPropertyName] = importKeyOptions.Properties.RecoveryLevel;
|
||||
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
importKeyOptions.Properties.UpdatedOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::UpdatedPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
|
||||
// tags
|
||||
for (auto& tag : importKeyOptions.Properties.Tags)
|
||||
{
|
||||
payload[_detail::TagsPropertyName][tag.first] = tag.second;
|
||||
}
|
||||
|
||||
// release_policy
|
||||
return payload.dump();
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/keyvault/common/internal/base64url.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/json_web_key.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using namespace Azure::Security::KeyVault::Common::_internal;
|
||||
|
||||
void Azure::Security::KeyVault::Keys::to_json(
|
||||
Azure::Core::Json::_internal::json& j,
|
||||
JsonWebKey const& p)
|
||||
{
|
||||
j[_detail::KeyTypePropertyName] = KeyType::KeyTypeToString(p.KeyType);
|
||||
j[_detail::NPropertyName] = Base64Url::Base64UrlEncode(p.N);
|
||||
j[_detail::EPropertyName] = Base64Url::Base64UrlEncode(p.E);
|
||||
j[_detail::DPropertyName] = Base64Url::Base64UrlEncode(p.D);
|
||||
j[_detail::DPPropertyName] = Base64Url::Base64UrlEncode(p.DP);
|
||||
j[_detail::DQPropertyName] = Base64Url::Base64UrlEncode(p.DQ);
|
||||
j[_detail::QIPropertyName] = Base64Url::Base64UrlEncode(p.QI);
|
||||
j[_detail::PPropertyName] = Base64Url::Base64UrlEncode(p.P);
|
||||
j[_detail::QPropertyName] = Base64Url::Base64UrlEncode(p.Q);
|
||||
}
|
||||
38
sdk/keyvault/azure-security-keyvault-keys/src/key_backup.cpp
Normal file
38
sdk/keyvault/azure-security-keyvault-keys/src/key_backup.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
|
||||
#include <azure/keyvault/common/internal/base64url.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_backup.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys::_detail;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using namespace Azure::Security::KeyVault::Common::_internal;
|
||||
|
||||
std::string KeyBackup::Serialize() const
|
||||
{
|
||||
Azure::Core::Json::_internal::json payload;
|
||||
|
||||
payload["value"] = Base64Url::Base64UrlEncode(Value);
|
||||
|
||||
// release_policy
|
||||
return payload.dump();
|
||||
}
|
||||
|
||||
KeyBackup KeyBackup::Deserialize(Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
auto const& body = rawResponse.GetBody();
|
||||
auto jsonParser = json::parse(body);
|
||||
KeyBackup keyBackup;
|
||||
JsonOptional::SetIfExists<std::string, std::vector<uint8_t>>(
|
||||
keyBackup.Value, jsonParser, "value", [](std::string const& value) {
|
||||
return Base64Url::Base64UrlDecode(value);
|
||||
});
|
||||
return keyBackup;
|
||||
}
|
||||
@ -5,8 +5,10 @@
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_backup.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_request_parameters.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
#include "azure/keyvault/keys/key_client.hpp"
|
||||
|
||||
#include <memory>
|
||||
@ -17,6 +19,41 @@ using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Http;
|
||||
using namespace Azure::Core::Http::Policies;
|
||||
|
||||
namespace {
|
||||
struct RequestWithContinuationToken
|
||||
{
|
||||
std::vector<std::string> Path;
|
||||
std::unique_ptr<std::map<std::string, std::string>> Query;
|
||||
};
|
||||
|
||||
static inline RequestWithContinuationToken BuildRequestFromContinuationToken(
|
||||
GetSinglePageOptions const& options,
|
||||
std::vector<std::string>&& defaultPath)
|
||||
{
|
||||
RequestWithContinuationToken request;
|
||||
request.Path = defaultPath;
|
||||
if (options.ContinuationToken)
|
||||
{
|
||||
// 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(options.ContinuationToken.GetValue());
|
||||
request.Query
|
||||
= std::make_unique<std::map<std::string, std::string>>(nextPageUrl.GetQueryParameters());
|
||||
request.Path.clear();
|
||||
request.Path.emplace_back(nextPageUrl.GetPath());
|
||||
}
|
||||
if (options.MaxResults)
|
||||
{
|
||||
if (request.Query == nullptr)
|
||||
{
|
||||
request.Query = std::make_unique<std::map<std::string, std::string>>();
|
||||
}
|
||||
request.Query->emplace("maxResults", std::to_string(options.MaxResults.GetValue()));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
KeyClient::KeyClient(
|
||||
std::string const& vaultUrl,
|
||||
std::shared_ptr<Core::Credentials::TokenCredential const> credential,
|
||||
@ -49,7 +86,7 @@ Azure::Response<KeyVaultKey> KeyClient::GetKey(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeyDeserialize(name, rawResponse);
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, name, options.Version});
|
||||
}
|
||||
@ -65,7 +102,7 @@ Azure::Response<KeyVaultKey> KeyClient::CreateKey(
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
_detail::KeyRequestParameters(keyType, options),
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeyDeserialize(name, rawResponse);
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, name, "create"});
|
||||
}
|
||||
@ -80,7 +117,7 @@ Azure::Response<KeyVaultKey> KeyClient::CreateEcKey(
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
_detail::KeyRequestParameters(ecKeyOptions),
|
||||
[&keyName](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeyDeserialize(keyName, rawResponse);
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, keyName, "create"});
|
||||
}
|
||||
@ -95,7 +132,7 @@ Azure::Response<KeyVaultKey> KeyClient::CreateRsaKey(
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
_detail::KeyRequestParameters(rsaKeyOptions),
|
||||
[&keyName](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeyDeserialize(keyName, rawResponse);
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, keyName, "create"});
|
||||
}
|
||||
@ -110,11 +147,45 @@ Azure::Response<KeyVaultKey> KeyClient::CreateOctKey(
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
_detail::KeyRequestParameters(octKeyOptions),
|
||||
[&keyName](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeyDeserialize(keyName, rawResponse);
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(keyName, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, keyName, "create"});
|
||||
}
|
||||
|
||||
Azure::Response<KeyPropertiesSinglePage> KeyClient::GetPropertiesOfKeysSinglePage(
|
||||
GetPropertiesOfKeysSinglePageOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto const request = BuildRequestFromContinuationToken(options, {_detail::KeysPath});
|
||||
return m_pipeline->SendRequest<KeyPropertiesSinglePage>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyPropertiesSinglePageSerializer::KeyPropertiesSinglePageDeserialize(
|
||||
rawResponse);
|
||||
},
|
||||
request.Path,
|
||||
request.Query);
|
||||
}
|
||||
|
||||
Azure::Response<KeyPropertiesSinglePage> KeyClient::GetPropertiesOfKeyVersionsSinglePage(
|
||||
std::string const& name,
|
||||
GetPropertiesOfKeyVersionsSinglePageOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto const request
|
||||
= BuildRequestFromContinuationToken(options, {_detail::KeysPath, name, "versions"});
|
||||
return m_pipeline->SendRequest<KeyPropertiesSinglePage>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyPropertiesSinglePageSerializer::KeyPropertiesSinglePageDeserialize(
|
||||
rawResponse);
|
||||
},
|
||||
request.Path,
|
||||
request.Query);
|
||||
}
|
||||
|
||||
Azure::Security::KeyVault::Keys::DeleteKeyOperation KeyClient::StartDeleteKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context) const
|
||||
@ -125,11 +196,26 @@ Azure::Security::KeyVault::Keys::DeleteKeyOperation KeyClient::StartDeleteKey(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Delete,
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::DeletedKeyDeserialize(name, rawResponse);
|
||||
return _detail::DeletedKeySerializer::DeletedKeyDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, name}));
|
||||
}
|
||||
|
||||
Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation KeyClient::StartRecoverDeletedKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation(
|
||||
m_pipeline,
|
||||
m_pipeline->SendRequest<Azure::Security::KeyVault::Keys::KeyVaultKey>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::DeletedKeysPath, name, "recover"}));
|
||||
}
|
||||
|
||||
Azure::Response<DeletedKey> KeyClient::GetDeletedKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context) const
|
||||
@ -138,7 +224,118 @@ Azure::Response<DeletedKey> KeyClient::GetDeletedKey(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::DeletedKeyDeserialize(name, rawResponse);
|
||||
return _detail::DeletedKeySerializer::DeletedKeyDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::DeletedKeysPath, name});
|
||||
}
|
||||
|
||||
Azure::Response<DeletedKeySinglePage> KeyClient::GetDeletedKeysSinglePage(
|
||||
GetDeletedKeysSinglePageOptions const& options,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
auto const request = BuildRequestFromContinuationToken(options, {_detail::DeletedKeysPath});
|
||||
return m_pipeline->SendRequest<DeletedKeySinglePage>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyPropertiesSinglePageSerializer::DeletedKeySinglePageDeserialize(
|
||||
rawResponse);
|
||||
},
|
||||
request.Path,
|
||||
request.Query);
|
||||
}
|
||||
|
||||
Azure::Response<PurgedKey> KeyClient::PurgeDeletedKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return m_pipeline->SendRequest<PurgedKey>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Delete,
|
||||
[](Azure::Core::Http::RawResponse const&) { return PurgedKey(); },
|
||||
{_detail::DeletedKeysPath, name});
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultKey> KeyClient::UpdateKeyProperties(
|
||||
KeyProperties const& properties,
|
||||
Azure::Nullable<std::list<KeyOperation>> const& keyOperations,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return m_pipeline->SendRequest<KeyVaultKey>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Patch,
|
||||
_detail::KeyRequestParameters(properties, keyOperations),
|
||||
[&properties](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(properties.Name, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, properties.Name, properties.Version});
|
||||
}
|
||||
|
||||
Azure::Response<std::vector<uint8_t>> KeyClient::BackupKey(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
// Use the internal model KeyBackup to parse from Json
|
||||
auto response = m_pipeline->SendRequest<_detail::KeyBackup>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyBackup::Deserialize(rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, name, "backup"});
|
||||
|
||||
// Convert the internal KeyBackup model to a raw vector<uint8_t>.
|
||||
return Azure::Response<std::vector<uint8_t>>(
|
||||
response.ExtractValue().Value, response.ExtractRawResponse());
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultKey> KeyClient::RestoreKeyBackup(
|
||||
std::vector<uint8_t> const& backup,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
_detail::KeyBackup backupModel;
|
||||
backupModel.Value = backup;
|
||||
return m_pipeline->SendRequest<KeyVaultKey>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
backupModel,
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, "restore"});
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultKey> KeyClient::ImportKey(
|
||||
std::string const& name,
|
||||
JsonWebKey const& keyMaterial,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
ImportKeyOptions const importKeyOptions(name, keyMaterial);
|
||||
return m_pipeline->SendRequest<KeyVaultKey>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Put,
|
||||
[&importKeyOptions]() {
|
||||
return _detail::ImportKeyOptionsSerializer::ImportKeyOptionsSerialize(importKeyOptions);
|
||||
},
|
||||
[&name](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(name, rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, name});
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultKey> KeyClient::ImportKey(
|
||||
ImportKeyOptions const& importKeyOptions,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return m_pipeline->SendRequest<KeyVaultKey>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Put,
|
||||
[&importKeyOptions]() {
|
||||
return _detail::ImportKeyOptionsSerializer::ImportKeyOptionsSerialize(importKeyOptions);
|
||||
},
|
||||
[&importKeyOptions](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
importKeyOptions.Name(), rawResponse);
|
||||
},
|
||||
{_detail::KeysPath, importKeyOptions.Name()});
|
||||
}
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
|
||||
#include <azure/keyvault/common/internal/unix_time_helper.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_request_parameters.hpp"
|
||||
@ -9,14 +12,22 @@
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys::_detail;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using namespace Azure::Security::KeyVault::Common::_internal;
|
||||
|
||||
std::string KeyRequestParameters::Serialize() const
|
||||
{
|
||||
|
||||
Azure::Core::Json::_internal::json payload;
|
||||
/* Mandatory */
|
||||
// kty
|
||||
payload[_detail::KeyTypePropertyName] = KeyTypeToString(m_keyType);
|
||||
SetFromNullable<JsonWebKeyType, std::string>(
|
||||
m_keyType, payload, _detail::KeyTypePropertyName, [](JsonWebKeyType type) {
|
||||
return KeyType::KeyTypeToString(type);
|
||||
});
|
||||
|
||||
// attributes
|
||||
SetFromNullable(
|
||||
m_options.Enabled, payload[_detail::AttributesPropertyName], _detail::EnabledPropertyName);
|
||||
|
||||
/* Optional */
|
||||
// key_size
|
||||
@ -28,6 +39,18 @@ std::string KeyRequestParameters::Serialize() const
|
||||
}
|
||||
|
||||
// attributes
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
m_options.ExpiresOn,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::ExpPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
|
||||
SetFromNullable<Azure::DateTime, uint64_t>(
|
||||
m_options.NotBefore,
|
||||
payload[_detail::AttributesPropertyName],
|
||||
_detail::NbfPropertyName,
|
||||
UnixTimeConverter::DatetimeToUnixTime);
|
||||
|
||||
// tags
|
||||
for (auto tag : m_options.Tags)
|
||||
{
|
||||
|
||||
@ -8,60 +8,60 @@
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
JsonWebKeyType _detail::KeyTypeFromString(std::string const& name)
|
||||
JsonWebKeyType KeyType::KeyTypeFromString(std::string const& name)
|
||||
{
|
||||
if (name == EcValue)
|
||||
if (name == _detail::EcValue)
|
||||
{
|
||||
return JsonWebKeyType::Ec;
|
||||
}
|
||||
if (name == EcHsmValue)
|
||||
if (name == _detail::EcHsmValue)
|
||||
{
|
||||
return JsonWebKeyType::EcHsm;
|
||||
}
|
||||
if (name == OctValue)
|
||||
if (name == _detail::OctValue)
|
||||
{
|
||||
return JsonWebKeyType::Oct;
|
||||
}
|
||||
if (name == OctHsmValue)
|
||||
if (name == _detail::OctHsmValue)
|
||||
{
|
||||
return JsonWebKeyType::OctHsm;
|
||||
}
|
||||
if (name == RsaValue)
|
||||
if (name == _detail::RsaValue)
|
||||
{
|
||||
return JsonWebKeyType::Rsa;
|
||||
}
|
||||
if (name == RsaHsmValue)
|
||||
if (name == _detail::RsaHsmValue)
|
||||
{
|
||||
return JsonWebKeyType::RsaHsm;
|
||||
}
|
||||
throw std::runtime_error("cannot convert " + name + " to key type (kty)");
|
||||
}
|
||||
|
||||
std::string _detail::KeyTypeToString(JsonWebKeyType kty)
|
||||
std::string KeyType::KeyTypeToString(JsonWebKeyType kty)
|
||||
{
|
||||
if (kty == JsonWebKeyType::Ec)
|
||||
{
|
||||
return EcValue;
|
||||
return _detail::EcValue;
|
||||
}
|
||||
if (kty == JsonWebKeyType::EcHsm)
|
||||
{
|
||||
return EcHsmValue;
|
||||
return _detail::EcHsmValue;
|
||||
}
|
||||
if (kty == JsonWebKeyType::Oct)
|
||||
{
|
||||
return OctValue;
|
||||
return _detail::OctValue;
|
||||
}
|
||||
if (kty == JsonWebKeyType::OctHsm)
|
||||
{
|
||||
return OctHsmValue;
|
||||
return _detail::OctHsmValue;
|
||||
}
|
||||
if (kty == JsonWebKeyType::Rsa)
|
||||
{
|
||||
return RsaValue;
|
||||
return _detail::RsaValue;
|
||||
}
|
||||
if (kty == JsonWebKeyType::RsaHsm)
|
||||
{
|
||||
return RsaHsmValue;
|
||||
return _detail::RsaHsmValue;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/key_curve_name.hpp"
|
||||
|
||||
#include <azure/keyvault/common/internal/unix_time_helper.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/core/url.hpp>
|
||||
|
||||
#include <azure/keyvault/common/internal/unix_time_helper.hpp>
|
||||
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
#include "azure/keyvault/keys/key_curve_name.hpp"
|
||||
#include "azure/keyvault/keys/key_vault_key.hpp"
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
@ -27,22 +29,36 @@ void ParseStringOperationsToKeyOperations(
|
||||
}
|
||||
} // namespace
|
||||
|
||||
KeyVaultKey _detail::KeyVaultKeyDeserialize(
|
||||
KeyVaultKey _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
std::string const& name,
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
KeyVaultKey key(name);
|
||||
_detail::KeyVaultKeyDeserialize(key, rawResponse);
|
||||
_detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(key, rawResponse);
|
||||
return key;
|
||||
}
|
||||
|
||||
void _detail::KeyVaultKeyDeserialize(
|
||||
KeyVaultKey _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
KeyVaultKey key;
|
||||
_detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(key, rawResponse);
|
||||
return key;
|
||||
}
|
||||
|
||||
void _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
KeyVaultKey& key,
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
auto body = rawResponse.GetBody();
|
||||
auto const& body = rawResponse.GetBody();
|
||||
auto jsonParser = json::parse(body);
|
||||
_detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(key, jsonParser);
|
||||
}
|
||||
|
||||
void _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(
|
||||
KeyVaultKey& key,
|
||||
Azure::Core::Json::_internal::json const& jsonParser)
|
||||
{
|
||||
// "Key"
|
||||
if (jsonParser.contains(_detail::KeyPropertyName))
|
||||
{
|
||||
@ -57,7 +73,7 @@ void _detail::KeyVaultKeyDeserialize(
|
||||
}
|
||||
key.Key.Id = jsonKey[_detail::KeyIdPropertyName].get<std::string>();
|
||||
key.Key.KeyType
|
||||
= _detail::KeyTypeFromString(jsonKey[_detail::KeyTypePropertyName].get<std::string>());
|
||||
= KeyType::KeyTypeFromString(jsonKey[_detail::KeyTypePropertyName].get<std::string>());
|
||||
|
||||
JsonOptional::SetIfExists<std::string, KeyCurveName>(
|
||||
key.Key.CurveName, jsonKey, _detail::CurveNamePropertyName, [](std::string const& keyName) {
|
||||
@ -65,20 +81,36 @@ void _detail::KeyVaultKeyDeserialize(
|
||||
});
|
||||
}
|
||||
|
||||
// Parse URL for the vaultUri, keyVersion
|
||||
_detail::KeyVaultKeySerializer::ParseKeyUrl(key.Properties, key.Key.Id);
|
||||
|
||||
// "Attributes"
|
||||
if (jsonParser.contains(_detail::AttributesPropertyName))
|
||||
{
|
||||
auto attributes = jsonParser[_detail::AttributesPropertyName];
|
||||
|
||||
JsonOptional::SetIfExists(key.Properties.Enabled, attributes, "enabled");
|
||||
JsonOptional::SetIfExists(key.Properties.Enabled, attributes, _detail::EnabledPropertyName);
|
||||
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
key.Properties.NotBefore, attributes, "nbf", UnixTimeConverter::UnixTimeToDatetime);
|
||||
key.Properties.NotBefore,
|
||||
attributes,
|
||||
_detail::NbfPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
key.Properties.ExpiresOn, attributes, "exp", UnixTimeConverter::UnixTimeToDatetime);
|
||||
key.Properties.ExpiresOn,
|
||||
attributes,
|
||||
_detail::ExpPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
key.Properties.CreatedOn, attributes, "created", UnixTimeConverter::UnixTimeToDatetime);
|
||||
key.Properties.CreatedOn,
|
||||
attributes,
|
||||
_detail::CreatedPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
key.Properties.UpdatedOn, attributes, "updated", UnixTimeConverter::UnixTimeToDatetime);
|
||||
key.Properties.UpdatedOn,
|
||||
attributes,
|
||||
_detail::UpdatedPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
}
|
||||
|
||||
// "Tags"
|
||||
|
||||
@ -0,0 +1,127 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/keys/list_keys_single_page_result.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
|
||||
#include <azure/keyvault/common/internal/unix_time_helper.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/core/url.hpp>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using Azure::Security::KeyVault::Common::_internal::UnixTimeConverter;
|
||||
|
||||
KeyPropertiesSinglePage
|
||||
_detail::KeyPropertiesSinglePageSerializer::KeyPropertiesSinglePageDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
KeyPropertiesSinglePage result;
|
||||
auto const& body = rawResponse.GetBody();
|
||||
auto jsonParser = json::parse(body);
|
||||
|
||||
JsonOptional::SetIfExists(result.ContinuationToken, jsonParser, "nextLink");
|
||||
|
||||
// Key properties
|
||||
auto keyPropertiesJson = jsonParser["value"];
|
||||
for (auto const& key : keyPropertiesJson)
|
||||
{
|
||||
KeyProperties keyProperties;
|
||||
keyProperties.Id = key[_detail::KeyIdPropertyName].get<std::string>();
|
||||
_detail::KeyVaultKeySerializer::ParseKeyUrl(keyProperties, keyProperties.Id);
|
||||
// "Attributes"
|
||||
if (key.contains(_detail::AttributesPropertyName))
|
||||
{
|
||||
auto attributes = key[_detail::AttributesPropertyName];
|
||||
|
||||
JsonOptional::SetIfExists(keyProperties.Enabled, attributes, _detail::EnabledPropertyName);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
keyProperties.NotBefore,
|
||||
attributes,
|
||||
_detail::NbfPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
keyProperties.ExpiresOn,
|
||||
attributes,
|
||||
_detail::ExpPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
keyProperties.CreatedOn,
|
||||
attributes,
|
||||
_detail::CreatedPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
keyProperties.UpdatedOn,
|
||||
attributes,
|
||||
_detail::UpdatedPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
}
|
||||
|
||||
// "Tags"
|
||||
if (key.contains(_detail::TagsPropertyName))
|
||||
{
|
||||
auto const& tags = key[_detail::TagsPropertyName];
|
||||
for (auto tag = tags.begin(); tag != tags.end(); ++tag)
|
||||
{
|
||||
keyProperties.Tags.emplace(tag.key(), tag.value().get<std::string>());
|
||||
}
|
||||
}
|
||||
|
||||
// managed
|
||||
if (key.contains(_detail::ManagedPropertyName))
|
||||
{
|
||||
keyProperties.Managed = key[_detail::ManagedPropertyName].get<bool>();
|
||||
}
|
||||
|
||||
result.Items.emplace_back(keyProperties);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DeletedKeySinglePage _detail::KeyPropertiesSinglePageSerializer::DeletedKeySinglePageDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
auto const& body = rawResponse.GetBody();
|
||||
auto jsonParser = Azure::Core::Json::_internal::json::parse(body);
|
||||
|
||||
DeletedKeySinglePage deletedKeySinglePage;
|
||||
JsonOptional::SetIfExists(deletedKeySinglePage.ContinuationToken, jsonParser, "nextLink");
|
||||
|
||||
auto deletedKeys = jsonParser["value"];
|
||||
for (auto const& key : deletedKeys)
|
||||
{
|
||||
DeletedKey deletedKey;
|
||||
deletedKey.Properties.Id = key[_detail::KeyIdPropertyName].get<std::string>();
|
||||
_detail::KeyVaultKeySerializer::ParseKeyUrl(deletedKey.Properties, deletedKey.Properties.Id);
|
||||
|
||||
if (!key[_detail::RecoveryIdPropertyName].is_null())
|
||||
{
|
||||
deletedKey.RecoveryId = key[_detail::RecoveryIdPropertyName].get<std::string>();
|
||||
}
|
||||
if (!key[_detail::AttributesPropertyName][_detail::RecoveryLevelPropertyName].is_null())
|
||||
{
|
||||
deletedKey.Properties.RecoveryLevel
|
||||
= key[_detail::AttributesPropertyName][_detail::RecoveryLevelPropertyName]
|
||||
.get<std::string>();
|
||||
}
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
deletedKey.DeletedDate,
|
||||
key,
|
||||
_detail::DeletedOnPropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
JsonOptional::SetIfExists<uint64_t, Azure::DateTime>(
|
||||
deletedKey.ScheduledPurgeDate,
|
||||
key,
|
||||
_detail::ScheduledPurgeDatePropertyName,
|
||||
UnixTimeConverter::UnixTimeToDatetime);
|
||||
|
||||
deletedKeySinglePage.Items.emplace_back(deletedKey);
|
||||
}
|
||||
|
||||
return deletedKeySinglePage;
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/keys/recover_deleted_key_operation.hpp"
|
||||
#include "azure/keyvault/keys/details/key_constants.hpp"
|
||||
#include "azure/keyvault/keys/details/key_serializers.hpp"
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
namespace {
|
||||
|
||||
// For delete key, the LRO ends when we can retreive the Key from the deleted keys list from the
|
||||
// server.
|
||||
inline Azure::Core::OperationStatus CheckCompleted(Azure::Core::Http::RawResponse const& response)
|
||||
{
|
||||
auto const code = response.GetStatusCode();
|
||||
switch (code)
|
||||
{
|
||||
case Azure::Core::Http::HttpStatusCode::Ok:
|
||||
// Access denied but proof the key was deleted.
|
||||
case Azure::Core::Http::HttpStatusCode::Forbidden:
|
||||
return Azure::Core::OperationStatus::Succeeded;
|
||||
case Azure::Core::Http::HttpStatusCode::NotFound:
|
||||
return Azure::Core::OperationStatus::Running;
|
||||
default:
|
||||
throw Azure::Security::KeyVault::Common::KeyVaultException::CreateFromResponse(response);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse>
|
||||
Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation::PollInternal(
|
||||
Azure::Core::Context& context)
|
||||
{
|
||||
std::unique_ptr<Azure::Core::Http::RawResponse> rawResponse;
|
||||
if (!IsDone())
|
||||
{
|
||||
rawResponse = m_pipeline->Send(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
{_detail::KeysPath, m_value.Name(), m_value.Properties.Version});
|
||||
m_status = CheckCompleted(*rawResponse);
|
||||
if (m_status == Azure::Core::OperationStatus::Succeeded)
|
||||
{
|
||||
m_value
|
||||
= _detail::KeyVaultKeySerializer::KeyVaultKeyDeserialize(m_value.Name(), *rawResponse);
|
||||
}
|
||||
}
|
||||
|
||||
// To ensure the success of calling Poll multiple times, even after operation is completed, a
|
||||
// copy of the raw http response is returned instead of transfering the ownership of the raw
|
||||
// response inside the Operation.
|
||||
return rawResponse;
|
||||
}
|
||||
|
||||
Azure::Security::KeyVault::Keys::RecoverDeletedKeyOperation::RecoverDeletedKeyOperation(
|
||||
std::shared_ptr<Azure::Security::KeyVault::Common::_internal::KeyVaultPipeline>
|
||||
keyvaultPipeline,
|
||||
Azure::Response<Azure::Security::KeyVault::Keys::KeyVaultKey> response)
|
||||
: m_pipeline(keyvaultPipeline)
|
||||
{
|
||||
if (!response.HasValue())
|
||||
{
|
||||
throw Azure::Security::KeyVault::Common::KeyVaultException(
|
||||
"The response does not contain a value.");
|
||||
}
|
||||
// The response becomes useless and the value and rawResponse are now owned by the
|
||||
// DeleteKeyOperation. This is fine because the DeleteKeyOperation is what the delete key api
|
||||
// will return.
|
||||
m_value = response.ExtractValue();
|
||||
m_rawResponse = response.ExtractRawResponse();
|
||||
|
||||
// Build the full url for continuation token. It is only used in case customers wants to use
|
||||
// it on their own. The Operation uses the KeyVaultPipeline from the client which knows how to
|
||||
// build this url.
|
||||
m_continuationToken = m_pipeline->GetVaultUrl() + "/" + std::string(_detail::DeletedKeysPath)
|
||||
+ "/" + m_value.Name();
|
||||
}
|
||||
@ -3,4 +3,6 @@
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
add_subdirectory(get-key)
|
||||
add_subdirectory(sample1-hello-world)
|
||||
add_subdirectory(sample2-backup-and-restore)
|
||||
add_subdirectory(sample3-get-keys)
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample1-hello-world LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample1-hello-world
|
||||
sample1_hello_world.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample1-hello-world PRIVATE azure-security-keyvault-keys azure-identity)
|
||||
@ -0,0 +1,85 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault SDK client for C++
|
||||
* to create, get, update, delete and purge a key.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the KeyVault account url.
|
||||
* - AZURE_TENANT_ID: Tenant id for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The client id to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The secret id from the client id.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/core.hpp>
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
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);
|
||||
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
std::string rsaKeyName("CloudRsaKey" + Azure::Core::Uuid::CreateUuid().ToString());
|
||||
try
|
||||
{
|
||||
auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
|
||||
rsaKey.KeySize = 2048;
|
||||
rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(rsaKey);
|
||||
|
||||
KeyVaultKey cloudRsaKey = keyClient.GetKey(rsaKeyName).ExtractValue();
|
||||
std::cout << "Key is returned with name " << cloudRsaKey.Name() << " and type "
|
||||
<< KeyType::KeyTypeToString(cloudRsaKey.GetKeyType()) << std::endl;
|
||||
|
||||
cloudRsaKey.Properties.ExpiresOn
|
||||
= cloudRsaKey.Properties.ExpiresOn.GetValue() + std::chrono::hours(24 * 365);
|
||||
KeyVaultKey updatedKey = keyClient.UpdateKeyProperties(cloudRsaKey.Properties).ExtractValue();
|
||||
std::cout << "Key's updated expiry time is " << updatedKey.Properties.ExpiresOn->ToString()
|
||||
<< std::endl;
|
||||
|
||||
CreateRsaKeyOptions newRsaKey(rsaKeyName);
|
||||
newRsaKey.KeySize = 4096;
|
||||
newRsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(newRsaKey);
|
||||
|
||||
DeleteKeyOperation operation = keyClient.StartDeleteKey(rsaKeyName);
|
||||
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
operation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
|
||||
keyClient.PurgeDeletedKey(rsaKeyName);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Security::KeyVault::Common::KeyVaultException const& e)
|
||||
{
|
||||
std::cout << "KeyVault Client Exception happened:" << std::endl << e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample2-backup-and-restore LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample2-backup-and-restore
|
||||
sample2_backup_and_restore.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample2-backup-and-restore PRIVATE azure-security-keyvault-keys azure-identity)
|
||||
@ -0,0 +1,143 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault SDK client for C++
|
||||
* to back up and restore a key.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the KeyVault account url.
|
||||
* - AZURE_TENANT_ID: Tenant id for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The client id to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The secret id from the client id.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/core.hpp>
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include <assert.h>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
static void AssertKeysEqual(KeyProperties const& expected, KeyProperties const& actual);
|
||||
|
||||
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);
|
||||
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
std::string rsaKeyName("CloudRsaKey" + Azure::Core::Uuid::CreateUuid().ToString());
|
||||
try
|
||||
{
|
||||
auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
|
||||
rsaKey.KeySize = 2048;
|
||||
rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
std::cout << "\t-Create Key" << std::endl;
|
||||
auto storedKey = keyClient.CreateRsaKey(rsaKey).ExtractValue();
|
||||
size_t backUpSize = 0;
|
||||
{
|
||||
std::cout << "\t-Backup Key" << std::endl;
|
||||
std::vector<uint8_t> backupKey(keyClient.BackupKey(rsaKeyName).ExtractValue());
|
||||
backUpSize = backupKey.size();
|
||||
|
||||
// save data to file
|
||||
std::cout << "\t-Save to file" << std::endl;
|
||||
std::ofstream savedFile;
|
||||
savedFile.open("backup.dat");
|
||||
for (auto const& data : backupKey)
|
||||
{
|
||||
savedFile << data;
|
||||
}
|
||||
savedFile.close();
|
||||
}
|
||||
// backup key is destroy at this point as it is out of the scope.
|
||||
// The storage account key is no longer in use, so you delete it.
|
||||
std::cout << "\t-Delete and purge key" << std::endl;
|
||||
DeleteKeyOperation operation = keyClient.StartDeleteKey(rsaKeyName);
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
operation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
keyClient.PurgeDeletedKey(rsaKeyName);
|
||||
// let's wait for one minute so we know the key was purged.
|
||||
std::this_thread::sleep_for(std::chrono::seconds(60));
|
||||
|
||||
// Restore the key from the file backup
|
||||
std::cout << "\t-Read from file." << std::endl;
|
||||
std::ifstream inFile;
|
||||
inFile.open("backup.dat");
|
||||
std::vector<uint8_t> inMemoryBackup(backUpSize);
|
||||
inFile >> inMemoryBackup.data();
|
||||
inFile.close();
|
||||
|
||||
std::cout << "\t-Restore Key" << std::endl;
|
||||
auto restoredKey = keyClient.RestoreKeyBackup(inMemoryBackup).ExtractValue();
|
||||
|
||||
AssertKeysEqual(storedKey.Properties, restoredKey.Properties);
|
||||
|
||||
operation = keyClient.StartDeleteKey(rsaKeyName);
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
operation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
keyClient.PurgeDeletedKey(rsaKeyName);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Security::KeyVault::Common::KeyVaultException const& e)
|
||||
{
|
||||
std::cout << "KeyVault Client Exception happened:" << std::endl << e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline bool CompareNullableT(Azure::Nullable<T> const& left, Azure::Nullable<T> const& right)
|
||||
{
|
||||
if (!left.HasValue() && !right.HasValue())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (left.HasValue() && !right.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!left.HasValue() && right.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return left.GetValue() == right.GetValue();
|
||||
}
|
||||
|
||||
void AssertKeysEqual(KeyProperties const& expected, KeyProperties const& actual)
|
||||
{
|
||||
#if defined(NDEBUG)
|
||||
// Use (void) to silent unused warnings.
|
||||
(void)expected;
|
||||
(void)actual;
|
||||
#endif
|
||||
assert(expected.Name == actual.Name);
|
||||
assert(expected.Version == actual.Version);
|
||||
assert(expected.Managed == actual.Managed);
|
||||
assert(expected.RecoveryLevel == actual.RecoveryLevel);
|
||||
assert(CompareNullableT(expected.ExpiresOn, actual.ExpiresOn));
|
||||
assert(CompareNullableT(expected.NotBefore, actual.NotBefore));
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required (VERSION 3.13)
|
||||
|
||||
project (sample3-get-keys LANGUAGES CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
add_executable (
|
||||
sample3-get-keys
|
||||
sample3_get_keys.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(sample3-get-keys PRIVATE azure-security-keyvault-keys azure-identity)
|
||||
@ -0,0 +1,183 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @brief This sample provides the code implementation to use the Key Vault SDK client for C++
|
||||
* to list keys and versions of a given key, and list deleted keys in a soft-delete enabled Key
|
||||
* Vault.
|
||||
*
|
||||
* @remark The following environment variables must be set before running the sample.
|
||||
* - AZURE_KEYVAULT_URL: To the KeyVault account url.
|
||||
* - AZURE_TENANT_ID: Tenant id for the Azure account.
|
||||
* - AZURE_CLIENT_ID: The client id to authenticate the request.
|
||||
* - AZURE_CLIENT_SECRET: The secret id from the client id.
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <azure/core.hpp>
|
||||
#include <azure/identity.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
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);
|
||||
|
||||
KeyClient keyClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
|
||||
try
|
||||
{
|
||||
std::string rsaKeyName("CloudRsaKey-" + Azure::Core::Uuid::CreateUuid().ToString());
|
||||
auto rsaKey = CreateRsaKeyOptions(rsaKeyName);
|
||||
rsaKey.KeySize = 2048;
|
||||
rsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
std::string ecKeyName("CloudEcKey-" + Azure::Core::Uuid::CreateUuid().ToString());
|
||||
auto ecKey = CreateEcKeyOptions(ecKeyName);
|
||||
ecKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
std::cout << "\t-Create Keys" << std::endl;
|
||||
keyClient.CreateRsaKey(rsaKey);
|
||||
keyClient.CreateEcKey(ecKey);
|
||||
|
||||
std::cout << "\t-List Keys" << std::endl;
|
||||
for (auto keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage().ExtractValue();;)
|
||||
{
|
||||
for (auto const& key : keysSinglePage.Items)
|
||||
{
|
||||
if (key.Managed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto keyWithType = keyClient.GetKey(key.Name).ExtractValue();
|
||||
std::cout << "Key is returned with name: " << keyWithType.Name()
|
||||
<< " and type: " << KeyType::KeyTypeToString(keyWithType.GetKeyType())
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (!keysSinglePage.ContinuationToken.HasValue())
|
||||
{
|
||||
// No more pages for the response, break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
GetPropertiesOfKeysSinglePageOptions options;
|
||||
options.ContinuationToken = keysSinglePage.ContinuationToken.GetValue();
|
||||
keysSinglePage = keyClient.GetPropertiesOfKeysSinglePage(options).ExtractValue();
|
||||
}
|
||||
|
||||
// update key
|
||||
CreateRsaKeyOptions newRsaKey(rsaKeyName);
|
||||
newRsaKey.KeySize = 4096;
|
||||
newRsaKey.ExpiresOn = std::chrono::system_clock::now() + std::chrono::hours(24 * 365);
|
||||
|
||||
keyClient.CreateRsaKey(newRsaKey);
|
||||
|
||||
// List key versions
|
||||
std::cout << "\t-List Key versions" << std::endl;
|
||||
for (auto keyVersionsSinglePage
|
||||
= keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName).ExtractValue();
|
||||
;)
|
||||
{
|
||||
for (auto const& key : keyVersionsSinglePage.Items)
|
||||
{
|
||||
std::cout << "Key's version: " << key.Version << " with name: " << key.Name << std::endl;
|
||||
}
|
||||
|
||||
if (!keyVersionsSinglePage.ContinuationToken.HasValue())
|
||||
{
|
||||
// No more pages for the response, break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
GetPropertiesOfKeyVersionsSinglePageOptions options;
|
||||
options.ContinuationToken = keyVersionsSinglePage.ContinuationToken.GetValue();
|
||||
keyVersionsSinglePage
|
||||
= keyClient.GetPropertiesOfKeyVersionsSinglePage(rsaKeyName, options).ExtractValue();
|
||||
}
|
||||
|
||||
std::cout << "\t-Delete Keys" << std::endl;
|
||||
DeleteKeyOperation rsaOperation = keyClient.StartDeleteKey(rsaKeyName);
|
||||
DeleteKeyOperation ecOperation = keyClient.StartDeleteKey(ecKeyName);
|
||||
|
||||
// You only need to wait for completion if you want to purge or recover the key.
|
||||
rsaOperation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
ecOperation.PollUntilDone(std::chrono::milliseconds(2000));
|
||||
|
||||
std::cout << "\t-List Deleted Keys" << std::endl;
|
||||
|
||||
// Start getting the first page.
|
||||
for (auto keysDeletedPage = keyClient.GetDeletedKeysSinglePage().ExtractValue();;)
|
||||
{
|
||||
for (auto const& key : keysDeletedPage.Items)
|
||||
{
|
||||
std::cout << "Deleted key's name: " << key.Name()
|
||||
<< ", recovery level: " << key.Properties.RecoveryLevel
|
||||
<< " and recovery Id: " << key.RecoveryId << std::endl;
|
||||
}
|
||||
|
||||
if (!keysDeletedPage.ContinuationToken.HasValue())
|
||||
{
|
||||
// No more pages for the response, break the loop
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
GetDeletedKeysSinglePageOptions options;
|
||||
options.ContinuationToken = keysDeletedPage.ContinuationToken.GetValue();
|
||||
keysDeletedPage = keyClient.GetDeletedKeysSinglePage(options).ExtractValue();
|
||||
}
|
||||
|
||||
// If the keyvault is soft-delete enabled, then for permanent deletion, deleted keys needs to be
|
||||
// purged.
|
||||
keyClient.PurgeDeletedKey(rsaKeyName);
|
||||
keyClient.PurgeDeletedKey(ecKeyName);
|
||||
}
|
||||
catch (Azure::Core::Credentials::AuthenticationException const& e)
|
||||
{
|
||||
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch (Azure::Security::KeyVault::Common::KeyVaultException const& e)
|
||||
{
|
||||
std::cout << "KeyVault Client Exception happened:" << std::endl << e.Message << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline bool CompareNullableT(Azure::Nullable<T> const& left, Azure::Nullable<T> const& right)
|
||||
{
|
||||
if (!left.HasValue() && !right.HasValue())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (left.HasValue() && !right.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!left.HasValue() && right.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return left.GetValue() == right.GetValue();
|
||||
}
|
||||
@ -37,9 +37,12 @@ gtest_discover_tests(azure-security-keyvault-keys-test
|
||||
################## Live Tests ##########################
|
||||
add_executable (
|
||||
azure-security-keyvault-keys-test-live
|
||||
key_client_backup_test_live.cpp
|
||||
key_client_create_test_live.cpp
|
||||
key_client_delete_test_live.cpp
|
||||
key_client_get_test_live.cpp
|
||||
key_client_import_test_live.cpp
|
||||
key_client_update_test_live.cpp
|
||||
main.cpp
|
||||
key_client_base_test.hpp
|
||||
)
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "key_client_base_test.hpp"
|
||||
|
||||
#include <azure/core/base64.hpp>
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
#include <azure/keyvault/keys/details/key_constants.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys::Test;
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
|
||||
TEST_F(KeyVaultClientTest, BackupKey)
|
||||
{
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName = GetUniqueName();
|
||||
|
||||
std::cout
|
||||
<< std::endl
|
||||
<< "Backup key test takes more than 2 minutes since it needs to wait for purge to complete.";
|
||||
|
||||
{
|
||||
std::cout << std::endl << "- Create key";
|
||||
auto response = keyClient.CreateKey(keyName, JsonWebKeyType::Ec);
|
||||
CheckValidResponse(response);
|
||||
}
|
||||
|
||||
// backup
|
||||
std::cout << std::endl << "- Backup key";
|
||||
auto backUpResponse = keyClient.BackupKey(keyName);
|
||||
CheckValidResponse(backUpResponse);
|
||||
{
|
||||
// Delete
|
||||
std::cout << std::endl << "- Delete key";
|
||||
auto response = keyClient.StartDeleteKey(keyName);
|
||||
response.PollUntilDone(std::chrono::milliseconds(1000));
|
||||
}
|
||||
{
|
||||
// Purge
|
||||
std::cout << std::endl << "- Purge key";
|
||||
auto response = keyClient.PurgeDeletedKey(keyName);
|
||||
CheckValidResponse(response, Azure::Core::Http::HttpStatusCode::NoContent);
|
||||
// Purge can take up to 2 min
|
||||
std::this_thread::sleep_for(std::chrono::minutes(2));
|
||||
}
|
||||
{ // Check key is gone
|
||||
EXPECT_THROW(keyClient.GetKey(keyName), Azure::Security::KeyVault::Common::KeyVaultException);
|
||||
}
|
||||
{
|
||||
// Restore
|
||||
std::cout << std::endl << "- Restore key";
|
||||
auto respone = keyClient.RestoreKeyBackup(*backUpResponse);
|
||||
CheckValidResponse(backUpResponse);
|
||||
}
|
||||
{
|
||||
// Check key is restored
|
||||
auto response = keyClient.GetKey(keyName);
|
||||
CheckValidResponse(response);
|
||||
EXPECT_EQ(keyName, response->Name());
|
||||
}
|
||||
{
|
||||
// Delete
|
||||
std::cout << std::endl << "- Clean";
|
||||
auto response = keyClient.StartDeleteKey(keyName);
|
||||
response.PollUntilDone(std::chrono::milliseconds(1000));
|
||||
}
|
||||
{
|
||||
// Purge
|
||||
auto response = keyClient.PurgeDeletedKey(keyName);
|
||||
CheckValidResponse(response, Azure::Core::Http::HttpStatusCode::NoContent);
|
||||
}
|
||||
}
|
||||
@ -10,10 +10,12 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <azure/core/context.hpp>
|
||||
#include <azure/core/uuid.hpp>
|
||||
#include <azure/identity/client_secret_credential.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace Test {
|
||||
|
||||
@ -43,13 +45,80 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys { nam
|
||||
Azure::Response<T>& response,
|
||||
Azure::Core::Http::HttpStatusCode expectedCode = Azure::Core::Http::HttpStatusCode::Ok)
|
||||
{
|
||||
auto rawResponse = response.ExtractRawResponse();
|
||||
auto const& rawResponse = response.GetRawResponse();
|
||||
EXPECT_EQ(
|
||||
static_cast<typename std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
rawResponse->GetStatusCode()),
|
||||
rawResponse.GetStatusCode()),
|
||||
static_cast<typename std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
expectedCode));
|
||||
}
|
||||
|
||||
static inline std::string GetUniqueName() { return Azure::Core::Uuid::CreateUuid().ToString(); }
|
||||
|
||||
static inline void CleanUpKeyVault(KeyClient const& keyClient)
|
||||
{
|
||||
std::vector<DeletedKey> deletedKeys;
|
||||
GetDeletedKeysSinglePageOptions options;
|
||||
while (true)
|
||||
{
|
||||
auto keyResponse = keyClient.GetDeletedKeysSinglePage(options);
|
||||
for (auto& key : keyResponse->Items)
|
||||
{
|
||||
deletedKeys.emplace_back(key);
|
||||
}
|
||||
if (!keyResponse->ContinuationToken)
|
||||
{
|
||||
break;
|
||||
}
|
||||
options.ContinuationToken = keyResponse->ContinuationToken;
|
||||
}
|
||||
if (deletedKeys.size() > 0)
|
||||
{
|
||||
for (auto& deletedKey : deletedKeys)
|
||||
{
|
||||
keyClient.PurgeDeletedKey(deletedKey.Name());
|
||||
}
|
||||
// Wait for purge is completed
|
||||
std::this_thread::sleep_for(std::chrono::minutes(1));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void RemoveAllKeysFromVault(KeyClient const& keyClient, bool waitForPurge = true)
|
||||
{
|
||||
std::vector<DeleteKeyOperation> deletedKeys;
|
||||
GetPropertiesOfKeysSinglePageOptions options;
|
||||
while (true)
|
||||
{
|
||||
auto keyResponse = keyClient.GetPropertiesOfKeysSinglePage(options);
|
||||
for (auto& key : keyResponse->Items)
|
||||
{
|
||||
deletedKeys.emplace_back(keyClient.StartDeleteKey(key.Name));
|
||||
}
|
||||
if (!keyResponse->ContinuationToken)
|
||||
{
|
||||
break;
|
||||
}
|
||||
options.ContinuationToken = keyResponse->ContinuationToken;
|
||||
}
|
||||
if (deletedKeys.size() > 0)
|
||||
{
|
||||
std::cout << std::endl
|
||||
<< "Cleaning vault. " << deletedKeys.size()
|
||||
<< " Will be deleted and purged now...";
|
||||
for (auto& deletedKey : deletedKeys)
|
||||
{
|
||||
auto readyToPurgeKey = deletedKey.PollUntilDone(std::chrono::milliseconds(1000));
|
||||
keyClient.PurgeDeletedKey(readyToPurgeKey->Name());
|
||||
std::cout << std::endl << "Deleted and purged key: " + readyToPurgeKey->Name();
|
||||
}
|
||||
std::cout << std::endl << "Complete purge operation.";
|
||||
// Wait for purge is completed
|
||||
if (waitForPurge)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::minutes(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}}}}} // namespace Azure::Security::KeyVault::Keys::Test
|
||||
|
||||
@ -19,7 +19,7 @@ using namespace Azure::Security::KeyVault::Keys::Test;
|
||||
TEST_F(KeyVaultClientTest, CreateKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("createKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -40,7 +40,7 @@ TEST_F(KeyVaultClientTest, CreateKey)
|
||||
TEST_F(KeyVaultClientTest, CreateKeyWithOptions)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("createKeyWithOptions");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
Azure::Security::KeyVault::Keys::CreateKeyOptions options;
|
||||
options.KeyOperations.push_back(Azure::Security::KeyVault::Keys::KeyOperation::Sign());
|
||||
@ -75,7 +75,7 @@ TEST_F(KeyVaultClientTest, CreateKeyWithOptions)
|
||||
TEST_F(KeyVaultClientTest, CreateKeyWithTags)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("myKeyWithOptionsTags");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
Azure::Security::KeyVault::Keys::CreateKeyOptions options;
|
||||
options.Tags.emplace("one", "value=1");
|
||||
@ -102,7 +102,7 @@ TEST_F(KeyVaultClientTest, CreateKeyWithTags)
|
||||
TEST_F(KeyVaultClientTest, CreateEcKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("createEcKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto ecKey = Azure::Security::KeyVault::Keys::CreateEcKeyOptions(keyName);
|
||||
@ -123,7 +123,7 @@ TEST_F(KeyVaultClientTest, CreateEcKey)
|
||||
TEST_F(KeyVaultClientTest, CreateEcKeyWithCurve)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("createEcKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto ecKey = Azure::Security::KeyVault::Keys::CreateEcKeyOptions(keyName);
|
||||
@ -150,7 +150,7 @@ TEST_F(KeyVaultClientTest, CreateEcKeyWithCurve)
|
||||
TEST_F(KeyVaultClientTest, CreateRsaKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("createRsaKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto rsaKey = Azure::Security::KeyVault::Keys::CreateRsaKeyOptions(keyName, false);
|
||||
@ -173,7 +173,7 @@ TEST_F(KeyVaultClientTest, CreateRsaKey)
|
||||
TEST_F(KeyVaultClientTest, CreateEcHsmKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultHsmUrl, m_credential);
|
||||
std::string keyName("createEcHsmKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto ecHsmKey = Azure::Security::KeyVault::Keys::CreateEcKeyOptions(keyName, true);
|
||||
@ -202,7 +202,7 @@ TEST_F(KeyVaultClientTest, CreateEcHsmKey)
|
||||
TEST_F(KeyVaultClientTest, CreateRsaHsmKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultHsmUrl, m_credential);
|
||||
std::string keyName("createRsaHsmKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto rsaHsmKey = Azure::Security::KeyVault::Keys::CreateRsaKeyOptions(keyName, true);
|
||||
|
||||
@ -44,7 +44,7 @@ using namespace Azure::Security::KeyVault::Keys::Test;
|
||||
TEST_F(KeyVaultClientTest, DeleteKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("deleteThisKey");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -69,12 +69,26 @@ TEST_F(KeyVaultClientTest, DeleteKey)
|
||||
// Will throw and fail test if test takes more than 3 minutes (token cancelled)
|
||||
auto keyResponse = keyResponseLRO.PollUntilDone(std::chrono::milliseconds(1000), cancelToken);
|
||||
}
|
||||
{
|
||||
// recover
|
||||
auto recoverOperation = keyClient.StartRecoverDeletedKey(keyName);
|
||||
auto keyResponse = recoverOperation.PollUntilDone(std::chrono::milliseconds(500));
|
||||
auto key = keyResponse.ExtractValue();
|
||||
// Delete again for purging
|
||||
auto deleteOp = keyClient.StartDeleteKey(key.Name());
|
||||
deleteOp.PollUntilDone(std::chrono::milliseconds(200));
|
||||
}
|
||||
{
|
||||
// Purge
|
||||
auto response = keyClient.PurgeDeletedKey(keyName);
|
||||
CheckValidResponse(response, Azure::Core::Http::HttpStatusCode::NoContent);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(KeyVaultClientTest, DeleteKeyOperationPoll)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("deleteThisKeyPoll");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -98,7 +112,7 @@ TEST_F(KeyVaultClientTest, DeleteKeyOperationPoll)
|
||||
TEST_F(KeyVaultClientTest, DeleteInvalidKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("thisKeyDoesNotExists");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
auto wasThrown = false;
|
||||
try
|
||||
@ -125,7 +139,7 @@ TEST_F(KeyVaultClientTest, DeleteInvalidKey)
|
||||
TEST_F(KeyVaultClientTest, DoubleDelete)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("DeleteMeTwoTimes");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -163,7 +177,7 @@ TEST_F(KeyVaultClientTest, DoubleDelete)
|
||||
TEST_F(KeyVaultClientTest, DoubleDeleteBeforePollComplete)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("DeleteMeBeforePollComplete1");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -199,7 +213,7 @@ TEST_F(KeyVaultClientTest, DoubleDeleteBeforePollComplete)
|
||||
TEST_F(KeyVaultClientTest, CreateDeletedKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("YouCanCreateMeAfterYouDeletedMe");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -239,7 +253,7 @@ TEST_F(KeyVaultClientTest, CreateDeletedKey)
|
||||
TEST_F(KeyVaultClientTest, CreateDeletedKeyBeforePollComplete)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("YouCanCreateMeAfterYouDeletedMeEvenBeforePollComplete");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -276,7 +290,7 @@ TEST_F(KeyVaultClientTest, CreateDeletedKeyBeforePollComplete)
|
||||
TEST_F(KeyVaultClientTest, GetDeletedKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
std::string keyName("deleteThisKeyAndGetItFromDeleteKeys1wwxx3x4");
|
||||
auto keyName = GetUniqueName();
|
||||
|
||||
{
|
||||
auto keyResponse
|
||||
@ -302,7 +316,7 @@ TEST_F(KeyVaultClientTest, GetDeletedKey)
|
||||
EXPECT_EQ(deletedKey.Name(), keyName);
|
||||
auto expectedType = Azure::Security::KeyVault::Keys::JsonWebKeyType::Ec;
|
||||
EXPECT_EQ(
|
||||
Azure::Security::KeyVault::Keys::_detail::KeyTypeToString(expectedType),
|
||||
Azure::Security::KeyVault::Keys::_detail::KeyTypeToString(deletedKey.Key.KeyType));
|
||||
Azure::Security::KeyVault::Keys::KeyType::KeyTypeToString(expectedType),
|
||||
Azure::Security::KeyVault::Keys::KeyType::KeyTypeToString(deletedKey.Key.KeyType));
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,17 +15,167 @@
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys::Test;
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
TEST_F(KeyVaultClientTest, GetKey)
|
||||
TEST_F(KeyVaultClientTest, GetSingleKey)
|
||||
{
|
||||
Azure::Security::KeyVault::Keys::KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
// Assuming and RS Key exists in the KeyVault Account.
|
||||
std::string keyName("testKey");
|
||||
std::string keyName(GetUniqueName());
|
||||
|
||||
auto createKeyResponse = keyClient.CreateEcKey(CreateEcKeyOptions(keyName));
|
||||
CheckValidResponse(createKeyResponse);
|
||||
auto keyResponse = keyClient.GetKey(keyName);
|
||||
CheckValidResponse(keyResponse);
|
||||
auto key = keyResponse.ExtractValue();
|
||||
|
||||
EXPECT_EQ(key.Name(), keyName);
|
||||
EXPECT_EQ(key.GetKeyType(), Azure::Security::KeyVault::Keys::JsonWebKeyType::Rsa);
|
||||
EXPECT_EQ(key.GetKeyType(), JsonWebKeyType::Ec);
|
||||
}
|
||||
|
||||
TEST_F(KeyVaultClientTest, GetPropertiesOfKeysOnePage)
|
||||
{
|
||||
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
// Delete and purge anything before starting the test to ensure test will work
|
||||
RemoveAllKeysFromVault(keyClient);
|
||||
|
||||
// Create 5 keys
|
||||
std::vector<std::string> keyNames;
|
||||
for (int counter = 0; counter < 5; counter++)
|
||||
{
|
||||
auto name = GetUniqueName();
|
||||
CreateEcKeyOptions options(name);
|
||||
keyNames.emplace_back(name);
|
||||
auto response = keyClient.CreateEcKey(options);
|
||||
CheckValidResponse(response);
|
||||
}
|
||||
// Get Key properties
|
||||
std::vector<KeyProperties> keyPropertiesList;
|
||||
GetPropertiesOfKeysSinglePageOptions options;
|
||||
while (true)
|
||||
{
|
||||
auto keyResponse = keyClient.GetPropertiesOfKeysSinglePage(options);
|
||||
for (auto& key : keyResponse->Items)
|
||||
{
|
||||
keyPropertiesList.emplace_back(key);
|
||||
}
|
||||
if (!keyResponse->ContinuationToken)
|
||||
{
|
||||
break;
|
||||
}
|
||||
options.ContinuationToken = keyResponse->ContinuationToken;
|
||||
}
|
||||
|
||||
EXPECT_EQ(keyNames.size(), keyPropertiesList.size());
|
||||
for (auto const& keyProperties : keyPropertiesList)
|
||||
{
|
||||
// Check names are in the keyNames list
|
||||
auto findKeyName = std::find(keyNames.begin(), keyNames.end(), keyProperties.Name);
|
||||
EXPECT_NE(findKeyName, keyNames.end());
|
||||
}
|
||||
|
||||
// Clean vault
|
||||
RemoveAllKeysFromVault(keyClient, false);
|
||||
}
|
||||
|
||||
TEST_F(KeyVaultClientTest, GetKeysVersionsOnePage)
|
||||
{
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
|
||||
// Create 5 key versions
|
||||
std::string keyName(GetUniqueName());
|
||||
size_t expectedVersions = 5;
|
||||
CreateEcKeyOptions createKeyOptions(keyName);
|
||||
for (size_t counter = 0; counter < expectedVersions; counter++)
|
||||
{
|
||||
auto response = keyClient.CreateEcKey(createKeyOptions);
|
||||
CheckValidResponse(response);
|
||||
}
|
||||
// Get Key versions
|
||||
std::vector<KeyProperties> keyPropertiesList;
|
||||
GetPropertiesOfKeyVersionsSinglePageOptions getKeyOptions;
|
||||
while (true)
|
||||
{
|
||||
auto keyResponse = keyClient.GetPropertiesOfKeyVersionsSinglePage(keyName, getKeyOptions);
|
||||
for (auto& key : keyResponse->Items)
|
||||
{
|
||||
keyPropertiesList.emplace_back(key);
|
||||
}
|
||||
if (!keyResponse->ContinuationToken)
|
||||
{
|
||||
break;
|
||||
}
|
||||
getKeyOptions.ContinuationToken = keyResponse->ContinuationToken;
|
||||
}
|
||||
|
||||
EXPECT_EQ(expectedVersions, keyPropertiesList.size());
|
||||
for (auto const& keyProperties : keyPropertiesList)
|
||||
{
|
||||
EXPECT_EQ(keyName, keyProperties.Name);
|
||||
}
|
||||
|
||||
// Clean vault
|
||||
RemoveAllKeysFromVault(keyClient, false);
|
||||
}
|
||||
|
||||
TEST_F(KeyVaultClientTest, GetDeletedKeysOnePage)
|
||||
{
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
|
||||
// Delete and purge anything before starting the test to ensure test will work
|
||||
CleanUpKeyVault(keyClient);
|
||||
|
||||
// Create 5 keys
|
||||
std::vector<std::string> keyNames;
|
||||
for (int counter = 0; counter < 5; counter++)
|
||||
{
|
||||
auto name = GetUniqueName();
|
||||
CreateEcKeyOptions options(name);
|
||||
keyNames.emplace_back(name);
|
||||
auto response = keyClient.CreateEcKey(options);
|
||||
CheckValidResponse(response);
|
||||
}
|
||||
// Delete keys
|
||||
std::vector<DeleteKeyOperation> operations;
|
||||
for (auto const& keyName : keyNames)
|
||||
{
|
||||
operations.emplace_back(keyClient.StartDeleteKey(keyName));
|
||||
}
|
||||
// wait for all of the delete operations to complete
|
||||
for (auto& operation : operations)
|
||||
{
|
||||
operation.PollUntilDone(std::chrono::milliseconds(1000));
|
||||
}
|
||||
|
||||
// Get all deleted Keys
|
||||
std::vector<DeletedKey> deletedKeys;
|
||||
GetDeletedKeysSinglePageOptions options;
|
||||
while (true)
|
||||
{
|
||||
auto keyResponse = keyClient.GetDeletedKeysSinglePage(options);
|
||||
for (auto& key : keyResponse->Items)
|
||||
{
|
||||
deletedKeys.emplace_back(key);
|
||||
}
|
||||
if (!keyResponse->ContinuationToken)
|
||||
{
|
||||
break;
|
||||
}
|
||||
options.ContinuationToken = keyResponse->ContinuationToken;
|
||||
}
|
||||
|
||||
EXPECT_EQ(keyNames.size(), deletedKeys.size());
|
||||
for (auto const& deletedKey : deletedKeys)
|
||||
{
|
||||
// Check names are in the keyNames list
|
||||
auto findKeyName = std::find(keyNames.begin(), keyNames.end(), deletedKey.Name());
|
||||
EXPECT_NE(findKeyName, keyNames.end());
|
||||
}
|
||||
|
||||
// Purge
|
||||
for (auto const& keyName : keyNames)
|
||||
{
|
||||
keyClient.PurgeDeletedKey(keyName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <azure/keyvault/common/internal/base64url.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
|
||||
#include "key_client_base_test.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys::Test;
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
using namespace Azure::Security::KeyVault::Common::_internal;
|
||||
|
||||
TEST_F(KeyVaultClientTest, ImportKey)
|
||||
{
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
JsonWebKey key;
|
||||
key.KeyType = JsonWebKeyType::Rsa;
|
||||
// Values from https://docs.microsoft.com/en-us/rest/api/keyvault/importkey/importkey
|
||||
key.N = Base64Url::Base64UrlDecode(
|
||||
"nKAwarTrOpzd1hhH4cQNdVTgRF-b0ubPD8ZNVf0UXjb62QuAk3Dn68ESThcF7SoDYRx2QVcfoMC9WCcuQUQDieJF-"
|
||||
"lvJTSer1TwH72NBovwKlHvrXqEI0a6_uVYY5n-"
|
||||
"soGt7qFZNbwQLdWWA6PrbqTLIkv6r01dcuhTiQQAn6OWEa0JbFvWfF1kILQIaSBBBaaQ4R7hZs7-"
|
||||
"VQTHGD7J1xGteof4gw2VTiwNdcE8p5UG5b6S9KQwAeET4yB4KFPwQ3TDdzxJQ89mwYVi_"
|
||||
"sgAIggN54hTq4oEKYJHBOMtFGIN0_HQ60ZSUnpOi87xNC-8VFqnv4rfTQ7nkK6XMvjMVfw");
|
||||
key.E = Base64Url::Base64UrlDecode("AQAB");
|
||||
key.D = Base64Url::Base64UrlDecode("GeT1_D5LAZa7qlC7WZ0DKJnOth8kcPrN0urTEFtWCbmHQWkAad_px_"
|
||||
"VUpGp0BWDDzENbXbQcu4QCCdf4crve5eXt8dVI86OSah");
|
||||
key.DP = Base64Url::Base64UrlDecode(
|
||||
"ZGnmWx-Nca71z9a9vvT4g02iv3S-"
|
||||
"3kSgmhl8JST09YQwK8tfiK7nXnNMtXJi2K4dLKKnLicGtCzB6W3mXdLcP2SUOWDOeStoBt8HEBT"
|
||||
"4MrI1psCKqnBum78WkHju90rBFj99amkP6UeQy5EASAzgmKQu2nUaUnRV0lYP8LHMCkE");
|
||||
key.DQ = Base64Url::Base64UrlDecode(
|
||||
"dtpke0foFs04hPS6XYLA5lc7-1MAHfZKN4CkMAofwDqPmRQzCxpDJUk0gMWGJEdU_"
|
||||
"Lqfbg22Py44cci0dczH36NW3UU5BL86T2_SPPDOuyX7kDscrIJCdowxQCGJHGRBEozM_"
|
||||
"uTL46wu6UnUIv7m7cuGgodJyZBcdwpo6ziFink");
|
||||
key.QI = Base64Url::Base64UrlDecode(
|
||||
"Y9KD5GaHkAYmAqpOfAQUMr71QuAAaBb0APzMuUvoEYw39PD3_vJeh9HZ15QmJ8zCX10-"
|
||||
"nlzUB-bWwvK-rGcJXbK4pArilr5MiaYv7e8h5eW2zs2_itDJ6Oebi-"
|
||||
"wVbMhg7DvUTBbkCvPhhIedE4UlDQmMYP7RhzVVs7SfmkGs_DQ");
|
||||
key.P = Base64Url::Base64UrlDecode(
|
||||
"v1jeCPnuJQM2PW2690Q9KJk0Ulok8VFGjkcHUHVi3orKdy7y_"
|
||||
"TCIWM6ZGvgFzI6abinzYbTEPKV4wFdMAwvOWmawXj5YrsoeB44_HXJ0ak_5_"
|
||||
"iP6XXR8MLGXbd0ZqsxvAZyzMj9vyle7EN2cBod6aenI2QZoRDucPvjPwZsZotk");
|
||||
key.Q = Base64Url::Base64UrlDecode(
|
||||
"0Yv-Dj6qnvx_LL70lUnKA6MgHE_bUC4drl5ZNDDsUdUUYfxIK4G1rGU45kHGtp-Qg-"
|
||||
"Uyf9s52ywLylhcVE3jfbjOgEozlSwKyhqfXkLpMLWHqOKj9fcfYd4PWKPOgpzWsqjA6fJbBUM"
|
||||
"Yo0CU2G9cWCtVodO7sBJVSIZunWrAlBc");
|
||||
std::string keyName(GetUniqueName());
|
||||
auto response = keyClient.ImportKey(keyName, key);
|
||||
CheckValidResponse(response);
|
||||
|
||||
{
|
||||
// delete + purge
|
||||
auto op = keyClient.StartDeleteKey(keyName);
|
||||
op.PollUntilDone(std::chrono::milliseconds(1000));
|
||||
keyClient.PurgeDeletedKey(keyName);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "key_client_base_test.hpp"
|
||||
|
||||
#include <azure/core/datetime.hpp>
|
||||
#include <azure/keyvault/key_vault.hpp>
|
||||
#include <azure/keyvault/keys/details/key_constants.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Keys::Test;
|
||||
using namespace Azure;
|
||||
using namespace Azure::Security::KeyVault::Keys;
|
||||
|
||||
TEST_F(KeyVaultClientTest, UpdateProperties)
|
||||
{
|
||||
KeyClient keyClient(m_keyVaultUrl, m_credential);
|
||||
auto keyName = GetUniqueName();
|
||||
auto updateTo = DateTime::Parse("20301031T00:00:00Z", DateTime::DateFormat::Rfc3339);
|
||||
{
|
||||
auto keyResponse = keyClient.CreateKey(keyName, JsonWebKeyType::Ec);
|
||||
CheckValidResponse(keyResponse);
|
||||
auto keyVaultKey = keyResponse.ExtractValue();
|
||||
EXPECT_EQ(keyVaultKey.Name(), keyName);
|
||||
EXPECT_TRUE(keyVaultKey.Properties.Enabled);
|
||||
EXPECT_TRUE(keyVaultKey.Properties.Enabled.GetValue());
|
||||
|
||||
// Update Key
|
||||
keyVaultKey.Properties.Enabled = false;
|
||||
keyVaultKey.Properties.ExpiresOn = updateTo;
|
||||
auto updatedResponse = keyClient.UpdateKeyProperties(keyVaultKey.Properties);
|
||||
CheckValidResponse(updatedResponse);
|
||||
}
|
||||
{
|
||||
// Get updated key to check values
|
||||
auto updatedKey = keyClient.GetKey(keyName);
|
||||
CheckValidResponse(updatedKey);
|
||||
auto key = updatedKey.ExtractValue();
|
||||
EXPECT_TRUE(key.Properties.Enabled);
|
||||
EXPECT_FALSE(key.Properties.Enabled.GetValue());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user