Make keyvault to expose telemetry options (#1661)

fixes: #1566
This commit is contained in:
Victor Vazquez 2021-02-10 18:16:54 -08:00 committed by GitHub
parent e141ad6de4
commit e423265180
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 2 deletions

View File

@ -27,6 +27,7 @@ namespace Azure { namespace Security { namespace KeyVault { namespace Keys {
ServiceVersion Version;
Azure::Core::Http::RetryOptions RetryOptions;
Azure::Core::Http::TransportPolicyOptions TransportPolicyOptions;
Azure::Core::Http::TelemetryPolicyOptions TelemetryPolicyOptions;
KeyClientOptions(ServiceVersion version = ServiceVersion::V7_2) : Version(version) {}

View File

@ -23,7 +23,8 @@ KeyClient::KeyClient(
// Base Pipeline
std::vector<std::unique_ptr<HttpPolicy>> policies;
policies.emplace_back(std::make_unique<TelemetryPolicy>("KeyVault", apiVersion));
policies.emplace_back(
std::make_unique<TelemetryPolicy>("KeyVault", apiVersion, options.TelemetryPolicyOptions));
policies.emplace_back(std::make_unique<RequestIdPolicy>());
policies.emplace_back(std::make_unique<RetryPolicy>(options.RetryOptions));

View File

@ -12,8 +12,10 @@ include(GoogleTest)
################## Unit Tests ##########################
add_executable (
azure-security-keyvault-keys-test
key_client_test.cpp
key_client_test.cpp
main.cpp
mocked_transport_adapter_test.hpp
telemetry_header_test.cpp
)
if (MSVC)
@ -33,6 +35,7 @@ add_executable (
azure-security-keyvault-keys-test-live
key_client_test_live.cpp
main.cpp
key_client_base_test.hpp
)
if (MSVC)

View File

@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief The base class to construct and init a Key Vault client.
*
*/
#include <gtest/gtest.h>
#include <azure/core.hpp>
#include <azure/keyvault/key_vault.hpp>
#include <cstdio>
namespace Azure { namespace Security { namespace KeyVault { namespace Keys { namespace Test {
namespace Details {
// Return a simple key as response so keyvault can parse it to create the T response
// Fake key from https://docs.microsoft.com/en-us/rest/api/keyvault/GetKey/GetKey#examples
constexpr static const char FakeKey[]
= "{ \"key\": { \"kid\": "
"\"https://myvault.vault.azure.net/keys/CreateSoftKeyTest/"
"78deebed173b48e48f55abf87ed4cf71\", \"kty\": \"RSA\", \"key_ops\": [ "
"\"encrypt\", \"decrypt\", \"sign\", \"verify\", \"wrapKey\", "
"\"unwrapKey\" ]}, \"attributes\": { \"enabled\": true, "
"\"created\": 1493942451, \"updated\": 1493942451, \"recoveryLevel\": "
"\"Recoverable+Purgeable\" }, \"tags\": { \"purpose\" "
": "
"\"unit test\", \"test name \" : \"CreateGetDeleteKeyTest\"}}";
} // namespace Details
// A transport adapter which only echo a request headers back as a response.
class MockedTransportAdapter : public Azure::Core::Http::HttpTransport {
std::unique_ptr<Azure::Core::Http::RawResponse> Send(
Azure::Core::Context const& context,
Azure::Core::Http::Request& request) override
{
(void)context;
auto response = std::make_unique<Azure::Core::Http::RawResponse>(
1, 1, Azure::Core::Http::HttpStatusCode::Ok, "Ok");
// Copy headers
for (auto header : request.GetHeaders())
{
response->AddHeader(header.first, header.second);
}
std::string bodyCount(Details::FakeKey);
response->SetBodyStream(std::make_unique<Azure::Core::Http::MemoryBodyStream>(
reinterpret_cast<const uint8_t*>(Details::FakeKey), bodyCount.size()));
return response;
} // namespace Azure
}; // namespace Test
// A derived class with no credential and authentication
class KeyClientWithNoAuthenticationPolicy : public Azure::Security::KeyVault::Keys::KeyClient {
public:
explicit KeyClientWithNoAuthenticationPolicy(
std::string const& vaultUrl,
KeyClientOptions options = KeyClientOptions())
: KeyClient(vaultUrl, nullptr, options)
{
auto apiVersion = options.GetVersionString();
// Base Pipeline
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
policies.emplace_back(std::make_unique<Azure::Core::Http::TelemetryPolicy>(
"KeyVault", apiVersion, options.TelemetryPolicyOptions));
policies.emplace_back(std::make_unique<Azure::Core::Http::RequestIdPolicy>());
policies.emplace_back(std::make_unique<Azure::Core::Http::RetryPolicy>(options.RetryOptions));
policies.emplace_back(std::make_unique<Azure::Core::Http::LoggingPolicy>());
policies.emplace_back(
std::make_unique<Azure::Core::Http::TransportPolicy>(options.TransportPolicyOptions));
Azure::Core::Http::Url url(vaultUrl);
m_pipeline = std::make_unique<Azure::Security::KeyVault::Common::Internal::KeyVaultPipeline>(
url, apiVersion, std::move(policies));
}
};
class MockedTransportAdapterTest : public ::testing::Test {
protected:
std::unique_ptr<KeyClientWithNoAuthenticationPolicy> m_client;
Azure::Security::KeyVault::Keys::KeyClientOptions m_clientOptions;
// Create
virtual void SetUp() override
{
m_clientOptions.TransportPolicyOptions.Transport = std::make_shared<MockedTransportAdapter>();
}
};
}}}}} // namespace Azure::Security::KeyVault::Keys::Test

View File

@ -0,0 +1,50 @@
// 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 "mocked_transport_adapter_test.hpp"
#include <azure/core/internal/strings.hpp>
#include <azure/keyvault/key_vault.hpp>
#include <string>
using namespace Azure::Security::KeyVault::Keys::Test;
TEST_F(MockedTransportAdapterTest, keyvaultTelemetryId)
{
std::string applicationId("ourApplicationId");
m_clientOptions.TelemetryPolicyOptions.ApplicationId = applicationId;
m_client = std::make_unique<
Azure::Security::KeyVault::Keys::Test::KeyClientWithNoAuthenticationPolicy>(
"url", m_clientOptions);
// The fake response from the mocked transport adapter is good for parsing a Key back
auto response = m_client->GetKey("name");
// The response is an echo of the sent headers. Let's find the telemetry id
auto foundHeader = false;
for (auto& header : response.GetRawResponse().GetHeaders())
{
if (Azure::Core::Internal::Strings::LocaleInvariantCaseInsensitiveEqual(
header.first, "User-Agent"))
{
foundHeader = true;
EXPECT_PRED2(
[](std::string const& received, std::string const& sent) {
auto telemetryInfoWithNoOSAndDate = received.substr(0, sent.size());
return Azure::Core::Internal::Strings::LocaleInvariantCaseInsensitiveEqual(
telemetryInfoWithNoOSAndDate, sent);
},
header.second,
applicationId);
break;
}
}
EXPECT_TRUE(foundHeader);
}