Backup / Restore secret (#2683)
* fix doc warnings * get rid of bad merge * fix doc warnings * get rid of bad merge * fix doc warnings * get rid of bad merge * code complete * fix doc warnings * get rid of bad merge * fix doc warnings * get rid of bad merge * fix doc warnings * get rid of bad merge * test * also restore * new line * fix doc warnings * get rid of bad merge * fix doc warnings * get rid of bad merge * fix doc warnings * get rid of bad merge * fixes for PR and build issues * add header for linux build * fix UT for mac * remove offending issues * rename from data to response * added overload * response -> result * remove overload
This commit is contained in:
parent
79143d4a1a
commit
d830de4afc
@ -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_backup_secret.hpp
|
||||
)
|
||||
|
||||
set(
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "azure/keyvault/secrets/dll_import_export.hpp"
|
||||
#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_properties.hpp"
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Keyvault BackupSecretData definition
|
||||
*/
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
/**
|
||||
* @brief Represents a backed up secret.
|
||||
*
|
||||
*/
|
||||
struct BackupSecretResult final
|
||||
{
|
||||
/**
|
||||
* @brief The backed up secret.
|
||||
*
|
||||
*/
|
||||
std::vector<uint8_t> Secret;
|
||||
};
|
||||
}}}} // namespace Azure::Security::KeyVault::Secrets
|
||||
@ -8,14 +8,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dll_import_export.hpp"
|
||||
|
||||
#include "azure/keyvault/secrets/keyvault_backup_secret.hpp"
|
||||
#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp"
|
||||
#include "azure/keyvault/secrets/keyvault_secret.hpp"
|
||||
#include "dll_import_export.hpp"
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/internal/http/pipeline.hpp>
|
||||
#include <azure/core/response.hpp>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace Azure { namespace Security { namespace KeyVault { namespace _detail {
|
||||
@ -235,6 +236,35 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
std::string const& version,
|
||||
KeyvaultSecretProperties const& properties,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Back up the specified secret.
|
||||
* Requests that a backup of the specified secret be downloaded to the client.
|
||||
* All versions of the secret will be downloaded.
|
||||
* This operation requires the secrets/backup permission.
|
||||
*
|
||||
* @param name The name of the secret<span class="x x-first x-last">.</span>
|
||||
* @param context The context for the operation can be used for request cancellation.
|
||||
*
|
||||
* @return The The backup blob containing the backed up secret.
|
||||
*/
|
||||
Azure::Response<BackupSecretResult> BackupSecret(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
|
||||
/**
|
||||
* @brief Restore a backed up secret to a vault.
|
||||
* Restores a backed up secret, and all its versions, to a vault.
|
||||
* This operation requires the secrets/restore permission.
|
||||
*
|
||||
* @param backup The backup payload as encoded vector of bytes.
|
||||
* @param context The context for the operation can be used for request cancellation.
|
||||
*
|
||||
* @return The Secret wrapped in the Response.
|
||||
*/
|
||||
Azure::Response<KeyVaultSecret> RestoreSecretBackup(
|
||||
std::vector<uint8_t> const& backup,
|
||||
Azure::Core::Context const& context = Azure::Core::Context()) const;
|
||||
};
|
||||
|
||||
}}}} // namespace Azure::Security::KeyVault::Secrets
|
||||
|
||||
@ -14,6 +14,8 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
/***************** KeyVault Secret *****************/
|
||||
constexpr static const char SecretPath[] = "secrets";
|
||||
static constexpr char const DeletedSecretPath[] = "deletedsecrets";
|
||||
static constexpr char const BackupSecretPath[] = "backup";
|
||||
static constexpr char const RestoreSecretPath[] = "restore";
|
||||
|
||||
/******************* Secret property names ***********/
|
||||
|
||||
|
||||
@ -8,10 +8,13 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#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/core/http/http.hpp>
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
|
||||
@ -103,4 +106,15 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Secrets {
|
||||
static std::string KeyVaultSecretPropertiesSerialize(
|
||||
KeyvaultSecretProperties const& properties);
|
||||
};
|
||||
|
||||
struct KeyvaultBackupSecretSerializer final
|
||||
{
|
||||
static BackupSecretResult KeyvaultBackupSecretDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse);
|
||||
};
|
||||
|
||||
struct KeyvaultRestoreSecretSerializer final
|
||||
{
|
||||
static std::string KeyvaultRestoreSecretSerialize(std::vector<uint8_t> const& backup);
|
||||
};
|
||||
}}}}} // namespace Azure::Security::KeyVault::Secrets::_detail
|
||||
|
||||
@ -27,6 +27,8 @@ namespace {
|
||||
constexpr static const char TelemetryName[] = "keyvault-secrets";
|
||||
}
|
||||
|
||||
const ServiceVersion ServiceVersion::V7_2("7.2");
|
||||
|
||||
SecretClient::SecretClient(
|
||||
std::string const& vaultUrl,
|
||||
std::shared_ptr<Core::Credentials::TokenCredential const> credential,
|
||||
@ -133,4 +135,32 @@ Azure::Response<KeyVaultSecret> SecretClient::UpdateSecretProperties(
|
||||
return UpdateSecretProperties(name, options, properties, context);
|
||||
}
|
||||
|
||||
const ServiceVersion ServiceVersion::V7_2("7.2");
|
||||
Azure::Response<BackupSecretResult> SecretClient::BackupSecret(
|
||||
std::string const& name,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return m_protocolClient->SendRequest<BackupSecretResult>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyvaultBackupSecretSerializer::KeyvaultBackupSecretDeserialize(
|
||||
rawResponse);
|
||||
},
|
||||
{_detail::SecretPath, name, _detail::BackupSecretPath});
|
||||
}
|
||||
|
||||
Azure::Response<KeyVaultSecret> SecretClient::RestoreSecretBackup(
|
||||
std::vector<uint8_t> const& backup,
|
||||
Azure::Core::Context const& context) const
|
||||
{
|
||||
return m_protocolClient->SendRequest<KeyVaultSecret>(
|
||||
context,
|
||||
Azure::Core::Http::HttpMethod::Post,
|
||||
[&backup]() {
|
||||
return _detail::KeyvaultRestoreSecretSerializer::KeyvaultRestoreSecretSerialize(backup);
|
||||
},
|
||||
[](Azure::Core::Http::RawResponse const& rawResponse) {
|
||||
return _detail::KeyVaultSecretSerializer::KeyVaultSecretDeserialize(rawResponse);
|
||||
},
|
||||
{_detail::SecretPath, _detail::RestoreSecretPath});
|
||||
}
|
||||
|
||||
@ -8,11 +8,12 @@
|
||||
|
||||
#include "private/secret_serializers.hpp"
|
||||
#include "private/secret_constants.hpp"
|
||||
|
||||
#include <azure/core/base64.hpp>
|
||||
#include <azure/core/internal/json/json.hpp>
|
||||
#include <azure/core/internal/json/json_optional.hpp>
|
||||
#include <azure/core/internal/json/json_serializable.hpp>
|
||||
|
||||
using namespace Azure::Core::_internal;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
using Azure::Core::_internal::PosixTimeConverter;
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
@ -157,41 +158,41 @@ void KeyVaultDeletedSecretSerializer::KeyVaultDeletedSecretDeserialize(
|
||||
std::string KeyVaultSecretSerializer::KeyVaultSecretSerialize(KeyVaultSecret const& parameters)
|
||||
{
|
||||
json payload;
|
||||
using namespace Azure::Security::KeyVault::Secrets::_detail;
|
||||
|
||||
// value is required
|
||||
payload[ValuePropertyName] = parameters.Value;
|
||||
|
||||
// all else is optional
|
||||
JsonOptional::SetFromNullable(
|
||||
parameters.Properties.ContentType, payload, ContentTypePropertyName);
|
||||
parameters.Properties.ContentType, payload, _detail::ContentTypePropertyName);
|
||||
|
||||
json attributes;
|
||||
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, int64_t>(
|
||||
parameters.Properties.CreatedOn,
|
||||
attributes,
|
||||
CreatedPropertyName,
|
||||
_detail::CreatedPropertyName,
|
||||
PosixTimeConverter::DateTimeToPosixTime);
|
||||
JsonOptional::SetFromNullable(parameters.Properties.Enabled, attributes, EnabledPropertyName);
|
||||
JsonOptional::SetFromNullable(
|
||||
parameters.Properties.Enabled, attributes, _detail::EnabledPropertyName);
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, int64_t>(
|
||||
parameters.Properties.ExpiresOn,
|
||||
attributes,
|
||||
ExpPropertyName,
|
||||
_detail::ExpPropertyName,
|
||||
PosixTimeConverter::DateTimeToPosixTime);
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, int64_t>(
|
||||
parameters.Properties.NotBefore,
|
||||
attributes,
|
||||
NbfPropertyName,
|
||||
_detail::NbfPropertyName,
|
||||
PosixTimeConverter::DateTimeToPosixTime);
|
||||
JsonOptional::SetFromNullable(
|
||||
parameters.Properties.RecoverableDays, attributes, RecoverableDaysPropertyName);
|
||||
parameters.Properties.RecoverableDays, attributes, _detail::RecoverableDaysPropertyName);
|
||||
JsonOptional::SetFromNullable(
|
||||
parameters.Properties.RecoveryLevel, attributes, RecoveryLevelPropertyName);
|
||||
parameters.Properties.RecoveryLevel, attributes, _detail::RecoveryLevelPropertyName);
|
||||
JsonOptional::SetFromNullable<Azure::DateTime, int64_t>(
|
||||
parameters.Properties.UpdatedOn,
|
||||
attributes,
|
||||
UpdatedPropertyName,
|
||||
_detail::UpdatedPropertyName,
|
||||
PosixTimeConverter::DateTimeToPosixTime);
|
||||
|
||||
// optional tags
|
||||
@ -236,3 +237,23 @@ std::string KeyVaultSecretPropertiesSerializer::KeyVaultSecretPropertiesSerializ
|
||||
|
||||
return payload.dump();
|
||||
}
|
||||
|
||||
BackupSecretResult KeyvaultBackupSecretSerializer::KeyvaultBackupSecretDeserialize(
|
||||
Azure::Core::Http::RawResponse const& rawResponse)
|
||||
{
|
||||
auto const& body = rawResponse.GetBody();
|
||||
auto jsonParser = json::parse(body);
|
||||
auto encodedResult = jsonParser[_detail::ValuePropertyName].get<std::string>();
|
||||
BackupSecretResult data;
|
||||
data.Secret = Base64Url::Base64UrlDecode(encodedResult);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string KeyvaultRestoreSecretSerializer::KeyvaultRestoreSecretSerialize(
|
||||
std::vector<uint8_t> const& backup)
|
||||
{
|
||||
json payload;
|
||||
payload[_detail::ValuePropertyName] = Base64Url::Base64UrlEncode(backup);
|
||||
return payload.dump();
|
||||
}
|
||||
|
||||
@ -19,14 +19,17 @@ int main()
|
||||
|
||||
SecretClient secretClient(std::getenv("AZURE_KEYVAULT_URL"), credential);
|
||||
// just a response, with a secret
|
||||
auto response = secretClient.GetSecret("testSecret");
|
||||
response.Value.Properties.ContentType = "weqeq";
|
||||
GetSecretOptions options;
|
||||
// auto response = secretClient.GetSecret("testSecret");
|
||||
// response.Value.Properties.ContentType = "weqeq";
|
||||
// GetSecretOptions options;
|
||||
|
||||
response = secretClient.UpdateSecretProperties(
|
||||
response.Value.Name, response.Value.Properties.Version, response.Value.Properties);
|
||||
// response = secretClient.UpdateSecretProperties(
|
||||
// response.Value.Name, response.Value.Properties.Version, response.Value.Properties);
|
||||
|
||||
// just a response, with a secret
|
||||
auto response3 = secretClient.GetDeletedSecret("someSecret");
|
||||
// auto response3 = secretClient.GetDeletedSecret("someSecret");
|
||||
|
||||
auto response4 = secretClient.BackupSecret("someSecret2");
|
||||
auto response5 = secretClient.RestoreSecretBackup(response4.Value.Secret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -17,7 +17,9 @@ add_executable (
|
||||
secret_get_client_deserialize_test.cpp
|
||||
secret_set_parameters_serializer_test.cpp
|
||||
secret_update_properties_test.cpp
|
||||
)
|
||||
secret_backup_deserialize_test.cpp
|
||||
secret_backup_deserialize_test.hpp
|
||||
)
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(azure-security-keyvault-secrets-test PUBLIC /wd6326 /wd26495 /wd26812)
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "secret_backup_deserialize_test.hpp"
|
||||
#include "../src/private/secret_serializers.hpp"
|
||||
#include "azure/keyvault/secrets/secret_client.hpp"
|
||||
|
||||
using namespace Azure::Security::KeyVault::Secrets;
|
||||
using namespace Azure::Security::KeyVault::Secrets::_test;
|
||||
using namespace Azure::Security::KeyVault::Secrets::_detail;
|
||||
using namespace Azure::Core::Json::_internal;
|
||||
TEST(KeyvaultBackupSecretSerializer, EmptyValue)
|
||||
{
|
||||
auto response = BackupHelpers::GetEmptyResponse();
|
||||
|
||||
auto secret = _detail::KeyvaultBackupSecretSerializer::KeyvaultBackupSecretDeserialize(response);
|
||||
|
||||
EXPECT_EQ(secret.Secret.size(), size_t(0));
|
||||
}
|
||||
|
||||
TEST(KeyvaultBackupSecretSerializer, FullValue)
|
||||
{
|
||||
auto response = BackupHelpers::GetFullResponse();
|
||||
|
||||
auto secret = _detail::KeyvaultBackupSecretSerializer::KeyvaultBackupSecretDeserialize(response);
|
||||
|
||||
EXPECT_EQ(secret.Secret.size(), size_t(10));
|
||||
std::string str(secret.Secret.begin(), secret.Secret.end());
|
||||
EXPECT_EQ(str, "my name is");
|
||||
}
|
||||
|
||||
TEST(KeyvaultRestoreSecretSerializer, EmptyValue)
|
||||
{
|
||||
std::string str = "";
|
||||
auto data = std::vector<uint8_t>(str.begin(), str.end());
|
||||
auto secret = _detail::KeyvaultRestoreSecretSerializer::KeyvaultRestoreSecretSerialize(data);
|
||||
auto jsonParser = json::parse(secret);
|
||||
|
||||
EXPECT_EQ(secret.size(), size_t(12));
|
||||
EXPECT_EQ(jsonParser["value"].get<std::string>().empty(), true);
|
||||
}
|
||||
|
||||
TEST(KeyvaultRestoreSecretSerializer, SomeValue)
|
||||
{
|
||||
std::string str = "my name is";
|
||||
|
||||
auto data = std::vector<uint8_t>(str.begin(), str.end());
|
||||
auto secret = _detail::KeyvaultRestoreSecretSerializer::KeyvaultRestoreSecretSerialize(data);
|
||||
auto jsonParser = json::parse(secret);
|
||||
|
||||
EXPECT_EQ(secret.size(), size_t(26));
|
||||
EXPECT_EQ(jsonParser["value"], "bXkgbmFtZSBpcw");
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp"
|
||||
#include "azure/keyvault/secrets/keyvault_secret.hpp"
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
#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 BackupHelpers
|
||||
{
|
||||
static Azure::Core::Http::RawResponse GetEmptyResponse()
|
||||
{
|
||||
auto response
|
||||
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
|
||||
|
||||
constexpr static const uint8_t responseBody[] = R"json({
|
||||
"value": ""
|
||||
}
|
||||
)json";
|
||||
|
||||
response.SetHeader(HttpShared::ContentType, "application/json");
|
||||
response.SetHeader(HttpShared::MsRequestId, "1");
|
||||
response.SetHeader(HttpShared::MsClientRequestId, "2");
|
||||
response.SetBody(std::vector<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 GetFullResponse()
|
||||
{
|
||||
auto response
|
||||
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
|
||||
|
||||
constexpr static const uint8_t responseBody[] = R"json({
|
||||
"value": "bXkgbmFtZSBpcw=="
|
||||
}
|
||||
)json";
|
||||
|
||||
response.SetHeader(HttpShared::ContentType, "application/json");
|
||||
response.SetHeader(HttpShared::MsRequestId, "1");
|
||||
response.SetHeader(HttpShared::MsClientRequestId, "2");
|
||||
response.SetBody(std::vector<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 GetIncorrectResponse()
|
||||
{
|
||||
auto response
|
||||
= Azure::Core::Http::RawResponse(1, 1, Azure::Core::Http::HttpStatusCode::Ok, "OK");
|
||||
|
||||
constexpr static const uint8_t responseBody[] = R"json({
|
||||
"value": "my name is"
|
||||
}
|
||||
)json";
|
||||
|
||||
response.SetHeader(HttpShared::ContentType, "application/json");
|
||||
response.SetHeader(HttpShared::MsRequestId, "1");
|
||||
response.SetHeader(HttpShared::MsClientRequestId, "2");
|
||||
response.SetBody(std::vector<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
|
||||
@ -1,10 +1,10 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "azure/core/http/http.hpp"
|
||||
#include "azure/core/http/policies/policy.hpp"
|
||||
#include "azure/keyvault/secrets/keyvault_deleted_secret.hpp"
|
||||
#include "azure/keyvault/secrets/keyvault_secret.hpp"
|
||||
#include <azure/core/http/http.hpp>
|
||||
#include <azure/core/http/policies/policy.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user