Create Extendable Enumeration base class (#3421)

* Created extendableenumeration class

* Convert attestation to use extendable enumeration; added test for extendable enumerations

Co-authored-by: Casey Carter <cartec69@gmail.com>
This commit is contained in:
Larry Osterman 2022-03-10 18:37:31 -08:00 committed by GitHub
parent 53f167dc37
commit 8672f985aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 157 additions and 48 deletions

View File

@ -12,6 +12,7 @@
#include "azure/attestation/dll_import_export.hpp"
#include <azure/core/context.hpp>
#include <azure/core/http/http.hpp>
#include <azure/core/internal/extendable_enumeration.hpp>
#include <azure/core/nullable.hpp>
#include <azure/core/paged_response.hpp>
#include <azure/core/response.hpp>
@ -29,34 +30,19 @@ namespace Azure { namespace Security { namespace Attestation { namespace Models
* the attestation service.
*
*/
class AttestationType final {
private:
std::string m_attestationType;
class AttestationType final
: public Azure::Core::_internal::ExtendableEnumeration<AttestationType> {
public:
/**
* @brief Construct a new AttestationType object
*
* @param attestationType The string attestationType used for the attestation policy operation.
*/
AttestationType(std::string attestationType) : m_attestationType(std::move(attestationType)) {}
/**
* @brief Enable comparing the ext enum.
*
* @param other Another #AttestationType to be compared.
*/
bool operator==(AttestationType const& other) const
explicit AttestationType(std::string attestationType)
: ExtendableEnumeration(std::move(attestationType))
{
return m_attestationType == other.m_attestationType;
}
/**
* @brief Return the #AttestationType string representation.
*
*/
std::string const& ToString() const { return m_attestationType; }
/**
* @brief Specifies that this should apply to SGX enclaves.
*
@ -427,10 +413,8 @@ namespace Azure { namespace Security { namespace Attestation { namespace Models
* policy modification.
*
*/
class PolicyModification final {
private:
std::string m_policyModification;
class PolicyModification final
: public Azure::Core::_internal::ExtendableEnumeration<PolicyModification> {
public:
/**
* @brief Construct a new PolicyResolution object
@ -438,23 +422,11 @@ namespace Azure { namespace Security { namespace Attestation { namespace Models
* @param modification The string resolution used for the result of an attestation policy
* operation.
*/
PolicyModification(std::string modification) : m_policyModification(std::move(modification)) {}
/**
* @brief Enable comparing the ext enum.
*
* @param other Another #PolicyModification to be compared.
*/
bool operator==(PolicyModification const& other) const
explicit PolicyModification(std::string modification)
: ExtendableEnumeration(std::move(modification))
{
return m_policyModification == other.m_policyModification;
}
/**
* @brief Return the #PolicyModification string representation.
*
*/
std::string const& ToString() const { return m_policyModification; }
PolicyModification() = default;
/**
* @brief Specifies that the policy object was updated.
@ -477,12 +449,12 @@ namespace Azure { namespace Security { namespace Attestation { namespace Models
/**
* @brief Result of a modification.
*/
Azure::Nullable<PolicyModification> PolicyResolution;
PolicyModification PolicyResolution;
/**
* @brief The SHA256 hash of the policy object which was received by the service.
*/
Azure::Nullable<std::vector<uint8_t>> PolicyTokenHash;
std::vector<uint8_t> PolicyTokenHash;
/**
* @brief A JSON Web Key containing the signer of the policy token. If not present, the token

View File

@ -87,7 +87,7 @@ authorizationrules
Azure::Response<AttestationToken<PolicyResult>> setResult
= adminClient.SetAttestationPolicy(AttestationType::SgxEnclave, policyToSet);
if (*setResult.Value.Body.PolicyResolution == PolicyModification::Updated)
if (setResult.Value.Body.PolicyResolution == PolicyModification::Updated)
{
std::cout << "Attestation policy was updated." << std::endl;
}
@ -108,7 +108,7 @@ authorizationrules
setPolicyToken.RawToken.size());
std::cout << "Expected token hash: " << Convert::Base64Encode(policyTokenHash) << std::endl;
std::cout << "Actual token hash: "
<< Convert::Base64Encode(*setResult.Value.Body.PolicyTokenHash) << std::endl;
<< Convert::Base64Encode(setResult.Value.Body.PolicyTokenHash) << std::endl;
}
int main()

View File

@ -97,10 +97,9 @@ namespace Azure { namespace Security { namespace Attestation { namespace Test {
EXPECT_EQ(result.RawResponse->GetStatusCode(), Azure::Core::Http::HttpStatusCode::Ok);
// SetPolicy responses should have updated or reset the policy value.
EXPECT_TRUE(result.Value.Body.PolicyResolution);
if (policyToValidate)
{
EXPECT_EQ(PolicyModification::Updated, *result.Value.Body.PolicyResolution);
EXPECT_EQ(PolicyModification::Updated, result.Value.Body.PolicyResolution);
// The attestation service only returns the PolicySigner and PolicySigningHash on
// SetPolicy calls, not ResetPolicy calls.
@ -128,8 +127,6 @@ namespace Azure { namespace Security { namespace Attestation { namespace Test {
EXPECT_FALSE(result.Value.Body.PolicySigner);
}
EXPECT_TRUE(result.Value.Body.PolicyTokenHash);
// The returned PolicyTokenHash value is the hash of the entire policy JWS that was sent
// to the service. In playback mode, the JWS which is calculated for the tests is
// different from the JWS which was recorded (because the signing certificate is
@ -145,12 +142,12 @@ namespace Azure { namespace Security { namespace Attestation { namespace Test {
std::vector<uint8_t> rawTokenHash = hasher.Final(
reinterpret_cast<const uint8_t*>(sentToken.RawToken.data()),
sentToken.RawToken.size());
EXPECT_EQ(*result.Value.Body.PolicyTokenHash, rawTokenHash);
EXPECT_EQ(result.Value.Body.PolicyTokenHash, rawTokenHash);
}
}
else
{
EXPECT_EQ(PolicyModification::Removed, *result.Value.Body.PolicyResolution);
EXPECT_EQ(PolicyModification::Removed, result.Value.Body.PolicyResolution);
}
return true;

View File

@ -71,6 +71,7 @@ set(
inc/azure/core/internal/cryptography/sha_hash.hpp
inc/azure/core/internal/diagnostics/log.hpp
inc/azure/core/internal/environment.hpp
inc/azure/core/internal/extendable_enumeration.hpp
inc/azure/core/internal/http/pipeline.hpp
inc/azure/core/internal/io/null_body_stream.hpp
inc/azure/core/internal/json/json_serializable.hpp

View File

@ -0,0 +1,81 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
/**
* @file
* @brief Internal utility functions for extendable enumerations.
*
*/
#include <string>
namespace Azure { namespace Core { namespace _internal {
/** @brief Template base class helper for implementing extendable enumerations.
*
* This template exists to simplify the experience of authoring ["extendable
* enumerations"](https://azure.github.io/azure-sdk/cpp_implementation.html#cpp-enums).
*
* An extendable enumeration derives publicly from the #ExtendableEnumeration base class passing
* in the extendable enumeration type as the template argument.
*
* Example:
*
* \code{.cpp}
* class MyEnumeration final : public ExtendableEnumeration<AttestationType> {
* public:
* explicit MyEnumeration(std::string attestationType) :
* ExtendableEnumeration(std::move(attestationType)) {}
* MyEnumeration() = default;
* static const MyEnumeration Enumerator1;
* static const MyEnumeration Enumerator2;
* static const MyEnumeration Enumerator3;
* };
* \endcode
*
*/
template <class T> class ExtendableEnumeration {
private:
std::string m_enumerationValue;
protected:
~ExtendableEnumeration() = default;
public:
/**
* @brief Construct a new extensable enumeration object
*
* @param enumerationValue The string enumerationValue used for the value.
*/
explicit ExtendableEnumeration(std::string enumerationValue)
: m_enumerationValue(std::move(enumerationValue))
{
}
/**
* @brief Construct a default extendable enumeration.
*/
ExtendableEnumeration() = default;
/**
* @brief Enable comparing the ext enum.
*
* @param other Another extendable enumeration to be compared.
*/
bool operator==(T const& other) const noexcept
{
return m_enumerationValue == other.m_enumerationValue;
}
/**
* @brief Enable comparing the ext enum.
*
* @param other Another extendable enumeration to be compared.
*/
bool operator!=(T const& other) const noexcept { return !operator==(other); }
/**
* @brief Return the ExtendableEnumeration string representation.
*
*/
std::string const& ToString() const { return m_enumerationValue; }
};
}}} // namespace Azure::Core::_internal

View File

@ -47,6 +47,7 @@ add_executable (
${CURL_SESSION_TESTS}
datetime_test.cpp
environment_log_level_listener_test.cpp
extendable_enumeration_test.cpp
etag_test.cpp
http_test.cpp
http_test.hpp

View File

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include <azure/core/internal/extendable_enumeration.hpp>
#include <gtest/gtest.h>
#include <string>
using namespace Azure::Core;
class MyEnum : public Azure::Core::_internal::ExtendableEnumeration<MyEnum> {
public:
MyEnum(std::string initialValue) : ExtendableEnumeration(std::move(initialValue)) {}
MyEnum() = default;
static const MyEnum Value1;
static const MyEnum Value2;
static const MyEnum Value3;
};
const MyEnum MyEnum::Value1("Value1");
const MyEnum MyEnum::Value2("Value2");
const MyEnum MyEnum::Value3("Value3");
TEST(ExtendableEnumeration, BasicTests)
{
{
MyEnum enum1 = MyEnum::Value1;
EXPECT_EQ(enum1, MyEnum::Value1);
}
{
MyEnum enumToTest(MyEnum::Value2);
EXPECT_NE(enumToTest, MyEnum::Value3);
}
{
MyEnum enumVal;
GTEST_LOG_(INFO) << enumVal.ToString();
}
{
MyEnum enumVal(MyEnum::Value3);
EXPECT_EQ(enumVal.ToString(), "Value3");
}
{
MyEnum enumVal(MyEnum::Value1);
MyEnum enumVal2(enumVal);
EXPECT_EQ(enumVal, enumVal2);
}
{
MyEnum enumVal(MyEnum::Value1);
MyEnum enumVal2;
EXPECT_EQ(enumVal, MyEnum::Value1);
enumVal2 = enumVal;
EXPECT_EQ(enumVal, enumVal2);
}
}