Paged requests (#2711)

* now we need to deserialize

* GETs+tests

* Delete+tests

* new line

* build issues

* size_t

* comments

* file format

* PR comments

* format
This commit is contained in:
George Arama 2021-08-09 13:24:54 -07:00 committed by GitHub
parent 4e1cdb985d
commit b91dce9deb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 903 additions and 3 deletions

View File

@ -34,6 +34,7 @@ set(
inc/azure/keyvault/secrets/secret_client.hpp
inc/azure/keyvault/keyvault_secrets.hpp
inc/azure/keyvault/secrets/keyvault_deleted_secret.hpp
inc/azure/keyvault/secrets/keyvault_secret_paged_response.hpp
inc/azure/keyvault/secrets/keyvault_backup_secret.hpp
inc/azure/keyvault/secrets/keyvault_operations.hpp
inc/azure/keyvault/secrets/keyvault_options.hpp
@ -49,6 +50,7 @@ set(
src/secret_client.cpp
src/secret_serializers.cpp
src/keyvault_operations.cpp
src/keyvault_secret_paged_response.cpp
)
add_library(azure-security-keyvault-secrets ${AZURE_SECURITY_KEYVAULT_SECRETS_HEADER} ${AZURE_SECURITY_KEYVAULT_SECRETS_SOURCE})

View File

@ -87,4 +87,34 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
*/
std::string Version;
};
/**
* @brief The options for calling an operation #GetPropertiesOfSecrets.
*
*/
struct GetPropertiesOfSecretsOptions final
{
Azure::Nullable<size_t> MaxResults;
Azure::Nullable<std::string> NextPageToken;
};
/**
* @brief The options for calling an operation #GetPropertiesOfSecretVersions.
*
*/
struct GetPropertiesOfSecretVersionsOptions final
{
Azure::Nullable<size_t> MaxResults;
Azure::Nullable<std::string> NextPageToken;
};
/**
* @brief The options for calling an operation #GetDeletedSecrets.
*
*/
struct GetDeletedSecretsOptions final
{
Azure::Nullable<size_t> MaxResults;
Azure::Nullable<std::string> NextPageToken;
};
}}}} // namespace Azure::Security::KeyVault::Secrets

View File

@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief Defines the Key Vault Secret paged responses.
*
*/
#pragma once
#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp"
#include "azure/keyvault/secrets/keyvault_secret_properties.hpp"
#include <azure/core/paged_response.hpp>
#include <memory>
#include <vector>
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
// forward definition
class SecretClient;
/**
* @brief Define a single page to list the secrets from the Key Vault.
*
*/
class KeyVaultSecretPropertiesPagedResponse final
: public Azure::Core::PagedResponse<KeyvaultSecretProperties> {
private:
friend class SecretClient;
friend class Azure::Core::PagedResponse<KeyvaultSecretProperties>;
std::string m_secretName;
std::shared_ptr<SecretClient> m_secretClient;
void OnNextPage(const Azure::Core::Context& context);
KeyVaultSecretPropertiesPagedResponse(
KeyVaultSecretPropertiesPagedResponse&& secretProperties,
std::unique_ptr<Azure::Core::Http::RawResponse> rawResponse,
std::shared_ptr<SecretClient> secretClient,
std::string const& secretName = std::string())
: PagedResponse(std::move(secretProperties)), m_secretName(secretName),
m_secretClient(secretClient), Items(std::move(secretProperties.Items))
{
RawResponse = std::move(rawResponse);
}
public:
/**
* @brief Construct a new KeyVaultSecretPropertiesPagedResponse object.
*
*/
KeyVaultSecretPropertiesPagedResponse() = default;
/**
* @brief Each #KeyvaultSecretProperties represent a Secret in the Key Vault.
*
*/
std::vector<KeyvaultSecretProperties> Items;
};
/**
* @brief Define a single page containing the deleted keys from the Key Vault.
*
*/
class KeyvaultSecretDeletedSecretPagedResponse final
: public Azure::Core::PagedResponse<KeyvaultSecretDeletedSecretPagedResponse> {
private:
friend class SecretClient;
friend class Azure::Core::PagedResponse<KeyvaultSecretDeletedSecretPagedResponse>;
std::shared_ptr<SecretClient> m_secretClient;
void OnNextPage(const Azure::Core::Context& context);
KeyvaultSecretDeletedSecretPagedResponse(
KeyvaultSecretDeletedSecretPagedResponse&& deletedKeyProperties,
std::unique_ptr<Azure::Core::Http::RawResponse> rawResponse,
std::shared_ptr<SecretClient> secretClient)
: PagedResponse(std::move(deletedKeyProperties)), m_secretClient(secretClient),
Items(std::move(deletedKeyProperties.Items))
{
RawResponse = std::move(rawResponse);
}
public:
/**
* @brief Construct a new Deleted Key Single Page object
*
*/
KeyvaultSecretDeletedSecretPagedResponse() = default;
/**
* @brief Each #DeletedKey represent a deleted key in the Key Vault.
*
*/
std::vector<KeyVaultDeletedSecret> Items;
};
}}}} // namespace Azure::Security::KeyVault::Secrets

View File

@ -13,6 +13,7 @@
#include "azure/keyvault/secrets/keyvault_operations.hpp"
#include "azure/keyvault/secrets/keyvault_options.hpp"
#include "azure/keyvault/secrets/keyvault_secret.hpp"
#include "azure/keyvault/secrets/keyvault_secret_paged_response.hpp"
#include "dll_import_export.hpp"
#include <azure/core/http/http.hpp>
#include <azure/core/internal/http/pipeline.hpp>
@ -242,5 +243,55 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
StartRecoverDeletedSecret(
std::string const& name,
Azure::Core::Context const& context = Azure::Core::Context()) const;
/**
* @brief List secrets in a specified key vault.
* The Get Secrets operation is applicable to the entire vault.
* However, only the base secret identifier and its attributes are provided in the response.
* Individual secret versions are not listed in the response. This operation requires the
* secrets/list permission.
*
* @param options The optional parameters for this request
* @param context The context for the operation can be used for request cancellation.
*
* @return Response containing a list of secrets in the vault along with a link to the next page
* of secrets.
*/
KeyVaultSecretPropertiesPagedResponse GetPropertiesOfSecrets(
GetPropertiesOfSecretsOptions const& options = GetPropertiesOfSecretsOptions(),
Azure::Core::Context const& context = Azure::Core::Context()) const;
/**
* @brief List all versions of the specified secret.
* The full secret identifier and attributes are provided in the response. No values are
* returned for the secrets. This operations requires the secrets/list permission.
*
* @param name The name of the secret.
* @param options The optional parameters for this request
* @param context The context for the operation can be used for request cancellation.
*
* @return Response containing a list of secrets in the vault along with a link to the next page
* of secrets.
*/
KeyVaultSecretPropertiesPagedResponse GetPropertiesOfSecretsVersions(
std::string const& name,
GetPropertiesOfSecretVersionsOptions const& options
= GetPropertiesOfSecretVersionsOptions(),
Azure::Core::Context const& context = Azure::Core::Context()) const;
/**
* @brief Lists deleted secrets for the specified vault.
* The Get Deleted Secrets operation returns the secrets that have been deleted for a vault
* enabled for soft-delete. This operation requires the secrets/list permission.
*
* @param options The optional parameters for this request
* @param context The context for the operation can be used for request cancellation.
*
* @return Response containing a list of deleted secrets in the vault, along with a link to the
* next page of deleted secrets.
*/
KeyvaultSecretDeletedSecretPagedResponse GetDeletedSecrets(
GetDeletedSecretsOptions const& options = GetDeletedSecretsOptions(),
Azure::Core::Context const& context = Azure::Core::Context()) const;
};
}}}} // namespace Azure::Security::KeyVault::Secrets

View File

@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief Defines KeyVaultSecretPropertiesPagedResponse.
*
*/
#include "azure/keyvault/secrets/keyvault_secret_paged_response.hpp"
#include "azure/keyvault/secrets/secret_client.hpp"
using namespace Azure::Security::KeyVault::Secrets;
void KeyVaultSecretPropertiesPagedResponse::OnNextPage(const Azure::Core::Context& context)
{
// Before calling `OnNextPage` pagedResponse validates there is a next page, so we are sure
// NextPageToken is valid.
if (m_secretName.empty())
{
GetPropertiesOfSecretsOptions options;
options.NextPageToken = NextPageToken;
*this = m_secretClient->GetPropertiesOfSecrets(options, context);
CurrentPageToken = options.NextPageToken.Value();
}
else
{
GetPropertiesOfSecretVersionsOptions options;
options.NextPageToken = NextPageToken;
*this = m_secretClient->GetPropertiesOfSecretsVersions(m_secretName, options, context);
CurrentPageToken = options.NextPageToken.Value();
}
}
void KeyvaultSecretDeletedSecretPagedResponse::OnNextPage(const Azure::Core::Context& context)
{
// Before calling `OnNextPage` pagedResponse validates there is a next page, so we are sure
// NextPageToken is valid.
GetDeletedSecretsOptions options;
options.NextPageToken = NextPageToken;
*this = m_secretClient->GetDeletedSecrets(options, context);
CurrentPageToken = options.NextPageToken.Value();
}

View File

@ -9,6 +9,8 @@
#pragma once
#include <cstddef>
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _detail {
/***************** KeyVault Secret *****************/
@ -42,4 +44,10 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
/**************** KeyVault QueryParameters *********/
static constexpr char const ApiVersion[] = "api-version";
/**************** KeyVault Secrets Paged *********/
static constexpr size_t PagedMaxResults = 25;
static constexpr char const PagedMaxResultsName[] = "maxresults";
static constexpr char const VersionsName[] = "versions";
}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail

View File

@ -11,6 +11,7 @@
#include "azure/keyvault/secrets/keyvault_backup_secret.hpp"
#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp"
#include "azure/keyvault/secrets/keyvault_secret.hpp"
#include "azure/keyvault/secrets/keyvault_secret_paged_response.hpp"
#include <azure/core/http/http.hpp>
#include <azure/core/internal/json/json.hpp>
#include <stdint.h>
@ -117,4 +118,17 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
{
static std::string KeyvaultRestoreSecretSerialize(std::vector<uint8_t> const& backup);
};
class KeyVaultSecretPropertiesPagedResultSerializer final {
public:
static KeyVaultSecretPropertiesPagedResponse KeyVaultSecretPropertiesPagedResponseDeserialize(
Azure::Core::Http::RawResponse const& rawResponse);
};
class KeyVaultSecretDeletedSecretPagedResultSerializer final {
public:
static KeyvaultSecretDeletedSecretPagedResponse
KeyVaultSecretDeletedSecretPagedResultDeserialize(
Azure::Core::Http::RawResponse const& rawResponse);
};
}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail

View File

@ -24,7 +24,33 @@ using namespace Azure::Core::Http::Policies::_internal;
namespace {
constexpr static const char TelemetryName[] = "keyvault-secrets";
struct RequestWithContinuationToken final
{
std::vector<std::string> Path;
std::unique_ptr<std::map<std::string, std::string>> Query;
};
static inline RequestWithContinuationToken BuildRequestFromContinuationToken(
const Azure::Nullable<std::string>& NextPageToken,
std::vector<std::string> defaultPath)
{
RequestWithContinuationToken request;
request.Path = std::move(defaultPath);
request.Query = std::make_unique<std::map<std::string, std::string>>();
if (NextPageToken)
{
// Using a continuation token requires to send the request to the continuation token URL instead
// of the default URL which is used only for the first page.
Azure::Core::Url nextPageUrl(NextPageToken.Value());
auto queryParameters = nextPageUrl.GetQueryParameters();
request.Query->insert(queryParameters.begin(), queryParameters.end());
request.Path.clear();
request.Path.emplace_back(nextPageUrl.GetPath());
}
return request;
}
} // namespace
const ServiceVersion ServiceVersion::V7_2("7.2");
@ -204,3 +230,95 @@ Azure::Security::KeyVault::Secrets::KeyVaultRestoreDeletedSecretOperation Secret
},
{_detail::DeletedSecretPath, name, _detail::RecoverDeletedSecretPath}));
}
KeyVaultSecretPropertiesPagedResponse SecretClient::GetPropertiesOfSecrets(
GetPropertiesOfSecretsOptions const& options,
Azure::Core::Context const& context) const
{
auto const request
= BuildRequestFromContinuationToken(options.NextPageToken, {_detail::SecretPath});
size_t maxResults = _detail::PagedMaxResults;
if (options.MaxResults.HasValue() && (options.MaxResults.Value() <= _detail::PagedMaxResults))
{
maxResults = options.MaxResults.Value();
}
request.Query->emplace(_detail::PagedMaxResultsName, std::to_string(maxResults));
auto response = m_protocolClient->SendRequest<KeyVaultSecretPropertiesPagedResponse>(
context,
Azure::Core::Http::HttpMethod::Get,
[](Azure::Core::Http::RawResponse const& rawResponse) {
return _detail::KeyVaultSecretPropertiesPagedResultSerializer::
KeyVaultSecretPropertiesPagedResponseDeserialize(rawResponse);
},
request.Path,
request.Query);
return KeyVaultSecretPropertiesPagedResponse(
std::move(response.Value),
std::move(response.RawResponse),
std::make_unique<SecretClient>(*this));
}
KeyVaultSecretPropertiesPagedResponse SecretClient::GetPropertiesOfSecretsVersions(
std::string const& name,
GetPropertiesOfSecretVersionsOptions const& options,
Azure::Core::Context const& context) const
{
auto const request = BuildRequestFromContinuationToken(
options.NextPageToken, {_detail::SecretPath, name, _detail::VersionsName});
size_t maxResults = _detail::PagedMaxResults;
if (options.MaxResults.HasValue() && (options.MaxResults.Value() <= _detail::PagedMaxResults))
{
maxResults = options.MaxResults.Value();
}
request.Query->emplace(_detail::PagedMaxResultsName, std::to_string(maxResults));
auto response = m_protocolClient->SendRequest<KeyVaultSecretPropertiesPagedResponse>(
context,
Azure::Core::Http::HttpMethod::Get,
[](Azure::Core::Http::RawResponse const& rawResponse) {
return _detail::KeyVaultSecretPropertiesPagedResultSerializer::
KeyVaultSecretPropertiesPagedResponseDeserialize(rawResponse);
},
request.Path,
request.Query);
return KeyVaultSecretPropertiesPagedResponse(
std::move(response.Value),
std::move(response.RawResponse),
std::make_unique<SecretClient>(*this),
name);
}
KeyvaultSecretDeletedSecretPagedResponse SecretClient::GetDeletedSecrets(
GetDeletedSecretsOptions const& options,
Azure::Core::Context const& context) const
{
auto const request
= BuildRequestFromContinuationToken(options.NextPageToken, {_detail::DeletedSecretPath});
size_t maxResults = _detail::PagedMaxResults;
if (options.MaxResults.HasValue() && (options.MaxResults.Value() <= _detail::PagedMaxResults))
{
maxResults = options.MaxResults.Value();
}
request.Query->emplace(_detail::PagedMaxResultsName, std::to_string(maxResults));
auto response = m_protocolClient->SendRequest<KeyvaultSecretDeletedSecretPagedResponse>(
context,
Azure::Core::Http::HttpMethod::Get,
[](Azure::Core::Http::RawResponse const& rawResponse) {
return _detail::KeyVaultSecretDeletedSecretPagedResultSerializer::
KeyVaultSecretDeletedSecretPagedResultDeserialize(rawResponse);
},
request.Path,
request.Query);
return KeyvaultSecretDeletedSecretPagedResponse(
std::move(response.Value),
std::move(response.RawResponse),
std::make_unique<SecretClient>(*this));
}

View File

@ -257,3 +257,167 @@ std::string KeyvaultRestoreSecretSerializer::KeyvaultRestoreSecretSerialize(
payload[_detail::ValuePropertyName] = Base64Url::Base64UrlEncode(backup);
return payload.dump();
}
KeyVaultSecretPropertiesPagedResponse
KeyVaultSecretPropertiesPagedResultSerializer::KeyVaultSecretPropertiesPagedResponseDeserialize(
Azure::Core::Http::RawResponse const& rawResponse)
{
KeyVaultSecretPropertiesPagedResponse result;
auto const& body = rawResponse.GetBody();
auto jsonParser = json::parse(body);
JsonOptional::SetIfExists(result.NextPageToken, jsonParser, "nextLink");
// Key properties
auto secretsPropertiesJson = jsonParser["value"];
for (auto const& secretProperties : secretsPropertiesJson)
{
KeyvaultSecretProperties item;
item.Id = secretProperties[_detail::IdPropertyName].get<std::string>();
_detail::KeyVaultSecretSerializer::ParseIDUrl(item, item.Id);
// Parse URL for the various attributes
if (secretProperties.contains(_detail::AttributesPropertyName))
{
auto attributes = secretProperties[_detail::AttributesPropertyName];
JsonOptional::SetIfExists(item.Enabled, attributes, _detail::EnabledPropertyName);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.NotBefore,
attributes,
_detail::NbfPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.ExpiresOn,
attributes,
_detail::ExpPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.CreatedOn,
attributes,
_detail::CreatedPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.UpdatedOn,
attributes,
_detail::UpdatedPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<std::string>(
item.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName);
JsonOptional::SetIfExists<int64_t>(
item.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName);
}
// "Tags"
if (secretProperties.contains(_detail::TagsPropertyName))
{
auto const& tags = secretProperties[_detail::TagsPropertyName];
{
for (auto tag = tags.begin(); tag != tags.end(); ++tag)
{
item.Tags.emplace(tag.key(), tag.value().get<std::string>());
}
}
}
// managed
if (secretProperties.contains(_detail::ManagedPropertyName))
{
item.Managed = secretProperties[_detail::ManagedPropertyName].get<bool>();
}
// content type
JsonOptional::SetIfExists<std::string>(
item.ContentType, secretProperties, _detail::ContentTypePropertyName);
result.Items.emplace_back(item);
}
return result;
}
KeyvaultSecretDeletedSecretPagedResponse
KeyVaultSecretDeletedSecretPagedResultSerializer::KeyVaultSecretDeletedSecretPagedResultDeserialize(
Azure::Core::Http::RawResponse const& rawResponse)
{
KeyvaultSecretDeletedSecretPagedResponse result;
auto const& body = rawResponse.GetBody();
auto jsonParser = json::parse(body);
auto string = jsonParser.dump();
JsonOptional::SetIfExists(result.NextPageToken, jsonParser, "nextLink");
// Key properties
auto secretsPropertiesJson = jsonParser["value"];
for (auto const& secretProperties : secretsPropertiesJson)
{
KeyVaultDeletedSecret item;
item.Id = secretProperties[_detail::IdPropertyName].get<std::string>();
_detail::KeyVaultSecretSerializer::ParseIDUrl(item.Properties, item.Id);
// Parse URL for the various attributes
if (secretProperties.contains(_detail::AttributesPropertyName))
{
auto attributes = secretProperties[_detail::AttributesPropertyName];
JsonOptional::SetIfExists(item.Properties.Enabled, attributes, _detail::EnabledPropertyName);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.Properties.NotBefore,
attributes,
_detail::NbfPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.Properties.ExpiresOn,
attributes,
_detail::ExpPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.Properties.CreatedOn,
attributes,
_detail::CreatedPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<int64_t, Azure::DateTime>(
item.Properties.UpdatedOn,
attributes,
_detail::UpdatedPropertyName,
PosixTimeConverter::PosixTimeToDateTime);
JsonOptional::SetIfExists<std::string>(
item.Properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName);
JsonOptional::SetIfExists<int64_t>(
item.Properties.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName);
}
// "Tags"
if (secretProperties.contains(_detail::TagsPropertyName))
{
auto const& tags = secretProperties[_detail::TagsPropertyName];
{
for (auto tag = tags.begin(); tag != tags.end(); ++tag)
{
item.Properties.Tags.emplace(tag.key(), tag.value().get<std::string>());
}
}
}
// managed
if (secretProperties.contains(_detail::ManagedPropertyName))
{
item.Properties.Managed = secretProperties[_detail::ManagedPropertyName].get<bool>();
}
// content type
JsonOptional::SetIfExists<std::string>(
item.Properties.ContentType, secretProperties, _detail::ContentTypePropertyName);
item.RecoveryId = secretProperties[_detail::RecoveryIdPropertyName];
item.ScheduledPurgeDate = PosixTimeConverter::PosixTimeToDateTime(
secretProperties[_detail::ScheduledPurgeDatePropertyName]);
item.DeletedDate = PosixTimeConverter::PosixTimeToDateTime(
secretProperties[_detail::DeletedDatePropertyName]);
result.Items.emplace_back(item);
}
return result;
}

View File

@ -4,8 +4,8 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "azure/keyvault/keyvault_secrets.hpp"
#include <azure/identity.hpp>
#include <azure/keyvault/keyvault_secrets.hpp>
using namespace Azure::Security::KeyVault::Secrets;
@ -32,7 +32,7 @@ int main()
// auto response4 = secretClient.BackupSecret("someSecret2");
// auto response5 = secretClient.RestoreSecretBackup(response4.Value.Secret);
auto response = secretClient.PurgeDeletedSecret("someSecret3");
// auto response = secretClient.PurgeDeletedSecret("someSecret3");
// auto response4 = secretClient.BackupSecret("someSecret2");
// auto response5 = secretClient.RestoreSecretBackup(response4.Value.Secret);
@ -44,5 +44,13 @@ int main()
auto response7 = response6.CreateFromResumeToken(resumeToken, secretClient);
auto reasponse8 = response7.Poll();
}
// auto response4 = secretClient.BackupSecret("someSecret2");
// auto response5 = secretClient.RestoreSecretBackup(response4.Value.Secret);
// GetPropertiesOfSecretsOptions options;
// options.MaxResults = 1;
// auto r1 = secretClient.GetPropertiesOfSecrets(options);
// auto r2 = secretClient.GetPropertiesOfSecretsVersions(r1.Items[0].Name);
auto r3 = secretClient.GetDeletedSecrets();
// r1.MoveToNextPage();
return 0;
}

View File

@ -19,7 +19,7 @@ add_executable (
secret_update_properties_test.cpp
secret_backup_deserialize_test.cpp
secret_backup_deserialize_test.hpp
)
"secret_paged_deserialize_test.cpp" "secret_paged_deserialize_test.hpp")
if (MSVC)
target_compile_options(azure-security-keyvault-secrets-test PUBLIC /wd6326 /wd26495 /wd26812)

View File

@ -0,0 +1,144 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "secret_paged_deserialize_test.hpp"
using namespace Azure::Security::KeyVault::Secrets;
using namespace Azure::Security::KeyVault::Secrets::_test;
using namespace Azure::Security::KeyVault::Secrets::_detail;
using namespace Azure::Core::Json::_internal;
TEST(KeyVaultSecretPropertiesPagedResponse, SingleWithNext)
{
auto response = _test::PagedHelpers::GetFirstResponse();
auto result = _detail::KeyVaultSecretPropertiesPagedResultSerializer::
KeyVaultSecretPropertiesPagedResponseDeserialize(response);
EXPECT_EQ(result.Items.size(), size_t(1));
EXPECT_EQ(
result.NextPageToken.Value(),
"https://gearama-test2.vault.azure.net:443/"
"secrets?api-version=7.2&$skiptoken="
"eyJOZXh0TWFya2VyIjoiMiE4NCFNREF3TURFM0lYTmxZM0psZEM5VFQwMUZVMFZEVWtWVUlUQXdNREF5T0NFNU9UazVM"
"VEV5TFRNeFZESXpPalU1T2pVNUxqazVPVGs1T1RsYUlRLS0iLCJUYXJnZXRMb2NhdGlvbiI6MH0&maxresults=1");
auto item = result.Items[0];
EXPECT_EQ(item.Enabled.Value(), true);
EXPECT_EQ(item.RecoverableDays.Value(), 90);
EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/gdfgfd");
}
TEST(KeyVaultSecretPropertiesPagedResponse, MultipleNoNext)
{
auto response = _test::PagedHelpers::GetMultipleResponse();
auto result = _detail::KeyVaultSecretPropertiesPagedResultSerializer::
KeyVaultSecretPropertiesPagedResponseDeserialize(response);
EXPECT_EQ(result.Items.size(), size_t(3));
EXPECT_EQ(result.NextPageToken.HasValue(), false);
auto item = result.Items[0];
EXPECT_EQ(item.Enabled.Value(), true);
EXPECT_EQ(item.RecoverableDays.Value(), 90);
EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(
item.Id,
"https://gearama-test2.vault.azure.net/secrets/gdfgfd/5a0fdd819481420eac6f3282ce722461");
EXPECT_EQ(item.Name, "gdfgfd");
EXPECT_EQ(item.Version, "5a0fdd819481420eac6f3282ce722461");
item = result.Items[1];
EXPECT_EQ(item.Enabled.Value(), true);
EXPECT_EQ(item.RecoverableDays.Value(), 90);
EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(
item.Id,
"https://gearama-test2.vault.azure.net/secrets/gdfgfd/8faafbb99216484dbbd75f9dd6bcaadf");
EXPECT_EQ(item.Name, "gdfgfd");
EXPECT_EQ(item.Version, "8faafbb99216484dbbd75f9dd6bcaadf");
item = result.Items[2];
EXPECT_EQ(item.Enabled.Value(), true);
EXPECT_EQ(item.RecoverableDays.Value(), 90);
EXPECT_EQ(item.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(
item.Id,
"https://gearama-test2.vault.azure.net/secrets/gdfgfd/d75080822f03400ab4d658bd0e988ac5");
EXPECT_EQ(item.Name, "gdfgfd");
EXPECT_EQ(item.Version, "d75080822f03400ab4d658bd0e988ac5");
}
TEST(KeyVaultSecretPropertiesPagedResponse, NoneNoNext)
{
auto response = _test::PagedHelpers::GetEmptyResponse();
auto result = _detail::KeyVaultSecretPropertiesPagedResultSerializer::
KeyVaultSecretPropertiesPagedResponseDeserialize(response);
EXPECT_EQ(result.Items.size(), size_t(0));
EXPECT_EQ(result.NextPageToken.HasValue(), false);
}
TEST(KeyVaultSecretDeletedSecretPagedResultSerializer, SingleWithNext)
{
auto response = _test::PagedHelpers::GetDeletedFirstResponse();
auto result = _detail::KeyVaultSecretDeletedSecretPagedResultSerializer::
KeyVaultSecretDeletedSecretPagedResultDeserialize(response);
EXPECT_EQ(result.Items.size(), size_t(1));
EXPECT_EQ(result.NextPageToken.Value(), "nextLink");
auto item = result.Items[0];
EXPECT_EQ(item.Properties.Enabled.Value(), true);
EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90);
EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/eqwewq");
EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq");
}
TEST(KeyVaultSecretDeletedSecretPagedResultSerializer, MultipleNoNext)
{
auto response = _test::PagedHelpers::GetDeletedMultipleResponse();
auto result = _detail::KeyVaultSecretDeletedSecretPagedResultSerializer::
KeyVaultSecretDeletedSecretPagedResultDeserialize(response);
EXPECT_EQ(result.Items.size(), size_t(3));
EXPECT_FALSE(result.NextPageToken.HasValue());
auto item = result.Items[0];
EXPECT_EQ(item.Properties.Enabled.Value(), true);
EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90);
EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/eqwewq");
EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq");
item = result.Items[1];
EXPECT_EQ(item.Properties.Enabled.Value(), true);
EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90);
EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/someSecret");
EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/secrets/someSecret");
item = result.Items[2];
EXPECT_EQ(item.Properties.Enabled.Value(), true);
EXPECT_EQ(item.Properties.RecoverableDays.Value(), 90);
EXPECT_EQ(item.Properties.RecoveryLevel.Value(), "Recoverable+Purgeable");
EXPECT_EQ(item.Id, "https://gearama-test2.vault.azure.net/secrets/someSecret2");
EXPECT_EQ(item.RecoveryId, "https://gearama-test2.vault.azure.net/deletedsecrets/someSecret2");
}
TEST(KeyVaultSecretDeletedSecretPagedResultSerializer, NoneNoNext)
{
auto response = _test::PagedHelpers::GetEmptyResponse();
auto result = _detail::KeyVaultSecretDeletedSecretPagedResultSerializer::
KeyVaultSecretDeletedSecretPagedResultDeserialize(response);
EXPECT_EQ(result.Items.size(), size_t(0));
EXPECT_EQ(result.NextPageToken.HasValue(), false);
}

View File

@ -0,0 +1,221 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "private/secret_constants.hpp"
#include "private/secret_serializers.hpp"
#include "../src/private/secret_serializers.hpp"
#include "azure/keyvault/secrets/secret_client.hpp"
#include <azure/core/internal/json/json.hpp>
#include <azure/core/internal/json/json_optional.hpp>
#include <azure/core/internal/json/json_serializable.hpp>
#include "azure/keyvault/secrets/keyvault_secret_paged_response.hpp"
#include <azure/core/http/http.hpp>
#include <azure/core/http/policies/policy.hpp>
#include <cstddef>
#include <gtest/gtest.h>
#include <string>
using namespace Azure::Security::KeyVault::Secrets;
using namespace Azure::Core::Http::_internal;
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets { namespace _test {
struct PagedHelpers
{
static Azure::Core::Http::RawResponse GetFirstResponse()
{
auto response
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
constexpr static const uint8_t responseBody[] = R"json({
"nextLink": "https://gearama-test2.vault.azure.net:443/secrets?api-version=7.2&$skiptoken=eyJOZXh0TWFya2VyIjoiMiE4NCFNREF3TURFM0lYTmxZM0psZEM5VFQwMUZVMFZEVWtWVUlUQXdNREF5T0NFNU9UazVMVEV5TFRNeFZESXpPalU1T2pVNUxqazVPVGs1T1RsYUlRLS0iLCJUYXJnZXRMb2NhdGlvbiI6MH0&maxresults=1",
"value": [{
"attributes": {
"created": 1627404049,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1627404049
},
"id": "https://gearama-test2.vault.azure.net/secrets/gdfgfd"
}]
}
)json";
response.SetHeader(HttpShared::ContentType, "application/json");
response.SetHeader(HttpShared::MsRequestId, "1");
response.SetHeader(HttpShared::MsClientRequestId, "2");
response.SetBody(std::vector<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
response.SetBodyStream(std::make_unique<Azure::Core::IO::MemoryBodyStream>(
responseBody, sizeof(responseBody) - 1));
return response;
}
static Azure::Core::Http::RawResponse GetMultipleResponse()
{
auto response
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
constexpr static const uint8_t responseBody[] = R"json({
"nextLink": null,
"value": [{
"attributes": {
"created": 1628101925,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1628101925
},
"contentType": "fdsfdsfs",
"id": "https://gearama-test2.vault.azure.net/secrets/gdfgfd/5a0fdd819481420eac6f3282ce722461",
"tags": {}
}, {
"attributes": {
"created": 1627404049,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1627404049
},
"id": "https://gearama-test2.vault.azure.net/secrets/gdfgfd/8faafbb99216484dbbd75f9dd6bcaadf"
}, {
"attributes": {
"created": 1628101911,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1628101911
},
"id": "https://gearama-test2.vault.azure.net/secrets/gdfgfd/d75080822f03400ab4d658bd0e988ac5",
"tags": {}
}]
}
)json";
response.SetHeader(HttpShared::ContentType, "application/json");
response.SetHeader(HttpShared::MsRequestId, "1");
response.SetHeader(HttpShared::MsClientRequestId, "2");
response.SetBody(std::vector<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
response.SetBodyStream(std::make_unique<Azure::Core::IO::MemoryBodyStream>(
responseBody, sizeof(responseBody) - 1));
return response;
}
static Azure::Core::Http::RawResponse GetEmptyResponse()
{
auto response
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
constexpr static const uint8_t responseBody[] = R"json({
"nextLink": null,
"value": []
}
)json";
response.SetHeader(HttpShared::ContentType, "application/json");
response.SetHeader(HttpShared::MsRequestId, "1");
response.SetHeader(HttpShared::MsClientRequestId, "2");
response.SetBody(std::vector<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
response.SetBodyStream(std::make_unique<Azure::Core::IO::MemoryBodyStream>(
responseBody, sizeof(responseBody) - 1));
return response;
}
static Azure::Core::Http::RawResponse GetDeletedFirstResponse()
{
auto response
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
constexpr static const uint8_t responseBody[] = R"json({
"nextLink": "nextLink",
"value": [{
"attributes": {
"created": 1628110306,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1628110306
},
"deletedDate": 1628110318,
"id": "https://gearama-test2.vault.azure.net/secrets/eqwewq",
"recoveryId": "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq",
"scheduledPurgeDate": 1635886318,
"tags": {}
}]
}
)json";
response.SetHeader(HttpShared::ContentType, "application/json");
response.SetHeader(HttpShared::MsRequestId, "1");
response.SetHeader(HttpShared::MsClientRequestId, "2");
response.SetBody(std::vector<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
response.SetBodyStream(std::make_unique<Azure::Core::IO::MemoryBodyStream>(
responseBody, sizeof(responseBody) - 1));
return response;
}
static Azure::Core::Http::RawResponse GetDeletedMultipleResponse()
{
auto response
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
constexpr static const uint8_t responseBody[] = R"json({
"nextLink": null,
"value": [{
"attributes": {
"created": 1628110306,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1628110306
},
"deletedDate": 1628110318,
"id": "https://gearama-test2.vault.azure.net/secrets/eqwewq",
"recoveryId": "https://gearama-test2.vault.azure.net/deletedsecrets/eqwewq",
"scheduledPurgeDate": 1635886318,
"tags": {}
}, {
"attributes": {
"created": 1626967532,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1626967532
},
"deletedDate": 1628110252,
"id": "https://gearama-test2.vault.azure.net/secrets/someSecret",
"recoveryId": "https://gearama-test2.vault.azure.net/secrets/someSecret",
"scheduledPurgeDate": 1635886252
}, {
"attributes": {
"created": 1627101774,
"enabled": true,
"recoverableDays": 90,
"recoveryLevel": "Recoverable+Purgeable",
"updated": 1627101774
},
"deletedDate": 1628110259,
"id": "https://gearama-test2.vault.azure.net/secrets/someSecret2",
"recoveryId": "https://gearama-test2.vault.azure.net/deletedsecrets/someSecret2",
"scheduledPurgeDate": 1635886259
}]
}
)json";
response.SetHeader(HttpShared::ContentType, "application/json");
response.SetHeader(HttpShared::MsRequestId, "1");
response.SetHeader(HttpShared::MsClientRequestId, "2");
response.SetBody(std::vector<uint8_t>(responseBody, responseBody + sizeof(responseBody)));
response.SetBodyStream(std::make_unique<Azure::Core::IO::MemoryBodyStream>(
responseBody, sizeof(responseBody) - 1));
return response;
}
};
}}}}} // namespace Azure::Security::KeyVault::Secrets::_test