Add GetCredentialName() (#4428)
* Add GetCredentialName() * Update * Undo accidental change * Clang-format * Call GetCredentialName() instead of using constant; Return in-place constructed name; Explicit tests for GetCredentialName() * PR feedback * constructor parameter + non-virtual GetCredentialName() * Update sdk/core/azure-core/CMakeLists.txt * Update sdk/identity/azure-identity/test/ut/client_secret_credential_test.cpp * Update sdk/identity/azure-identity/test/ut/client_certificate_credential_test.cpp * GCC and Clang warnings * Promote ThrowIfNotSafeCmdLineInput() to private member; avoid copies when calling GetCredentialName() * Spelling * Fix deprecated usage * Fix iteration * Clang-format --------- Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
This commit is contained in:
Родитель
f0a26fd4ad
Коммит
ef24dfda2e
|
@ -31,6 +31,8 @@ namespace Azure { namespace Core { namespace Test {
|
||||||
|
|
||||||
class TestNonExpiringCredential final : public Core::Credentials::TokenCredential {
|
class TestNonExpiringCredential final : public Core::Credentials::TokenCredential {
|
||||||
public:
|
public:
|
||||||
|
TestNonExpiringCredential() : TokenCredential("TestNonExpiringCredential") {}
|
||||||
|
|
||||||
Core::Credentials::AccessToken GetToken(
|
Core::Credentials::AccessToken GetToken(
|
||||||
Core::Credentials::TokenRequestContext const& tokenRequestContext,
|
Core::Credentials::TokenRequestContext const& tokenRequestContext,
|
||||||
Core::Context const& context) const override
|
Core::Context const& context) const override
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
- Added the ability to ignore invalid certificate common name for TLS connections in WinHTTP transport.
|
- Added the ability to ignore invalid certificate common name for TLS connections in WinHTTP transport.
|
||||||
- Added `DisableTlsCertificateValidation` in `TransportOptions`.
|
- Added `DisableTlsCertificateValidation` in `TransportOptions`.
|
||||||
|
- Added `TokenCredential::GetCredentialName()` to be utilized in diagnostic messages. If you have any custom implementations of `TokenCredential`, it is recommended to pass the name of your credential to `TokenCredential` constructor. The old parameterless constructor is deprecated.
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,9 @@ namespace Azure { namespace Core { namespace Credentials {
|
||||||
* @brief A base type of credential that uses Azure::Core::AccessToken to authenticate requests.
|
* @brief A base type of credential that uses Azure::Core::AccessToken to authenticate requests.
|
||||||
*/
|
*/
|
||||||
class TokenCredential {
|
class TokenCredential {
|
||||||
|
private:
|
||||||
|
std::string m_credentialName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Gets an authentication token.
|
* @brief Gets an authentication token.
|
||||||
|
@ -75,6 +78,12 @@ namespace Azure { namespace Core { namespace Credentials {
|
||||||
TokenRequestContext const& tokenRequestContext,
|
TokenRequestContext const& tokenRequestContext,
|
||||||
Context const& context) const = 0;
|
Context const& context) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the name of the credential.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
std::string const& GetCredentialName() const { return m_credentialName; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructs `%TokenCredential`.
|
* @brief Destructs `%TokenCredential`.
|
||||||
*
|
*
|
||||||
|
@ -82,11 +91,25 @@ namespace Azure { namespace Core { namespace Credentials {
|
||||||
virtual ~TokenCredential() = default;
|
virtual ~TokenCredential() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief Constructs an instance of `%TokenCredential`.
|
||||||
|
*
|
||||||
|
* @param credentialName Name of the credential for diagnostic messages.
|
||||||
|
*/
|
||||||
|
TokenCredential(std::string const& credentialName)
|
||||||
|
: m_credentialName(credentialName.empty() ? "Custom Credential" : credentialName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructs a default instance of `%TokenCredential`.
|
* @brief Constructs a default instance of `%TokenCredential`.
|
||||||
*
|
*
|
||||||
|
* @deprecated Use the constructor with parameter.
|
||||||
*/
|
*/
|
||||||
TokenCredential() {}
|
[[deprecated("Use the constructor with parameter.")]] TokenCredential()
|
||||||
|
: TokenCredential(std::string{})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,7 +16,7 @@ private:
|
||||||
public:
|
public:
|
||||||
explicit TestTokenCredential(
|
explicit TestTokenCredential(
|
||||||
std::shared_ptr<Azure::Core::Credentials::AccessToken const> accessToken)
|
std::shared_ptr<Azure::Core::Credentials::AccessToken const> accessToken)
|
||||||
: m_accessToken(accessToken)
|
: TokenCredential("TestTokenCredential"), m_accessToken(accessToken)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
### Other Changes
|
### Other Changes
|
||||||
|
|
||||||
|
- Improved diagnostics to utilize `Azure::Core::Credentials::TokenCredential::GetCredentialName()`.
|
||||||
|
|
||||||
## 1.5.0-beta.1 (2023-03-07)
|
## 1.5.0-beta.1 (2023-03-07)
|
||||||
|
|
||||||
### Features Added
|
### Features Added
|
||||||
|
|
|
@ -58,6 +58,8 @@ namespace Azure { namespace Identity {
|
||||||
DateTime::duration cliProcessTimeout,
|
DateTime::duration cliProcessTimeout,
|
||||||
Core::Credentials::TokenCredentialOptions const& options);
|
Core::Credentials::TokenCredentialOptions const& options);
|
||||||
|
|
||||||
|
void ThrowIfNotSafeCmdLineInput(std::string const& input, std::string const& description) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructs an Azure CLI Credential.
|
* @brief Constructs an Azure CLI Credential.
|
||||||
|
|
|
@ -62,13 +62,9 @@ namespace Azure { namespace Identity {
|
||||||
Core::Context const& context) const override;
|
Core::Context const& context) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit ChainedTokenCredential(
|
explicit ChainedTokenCredential(Sources sources, std::string const& enclosingCredential);
|
||||||
Sources sources,
|
|
||||||
std::string const& enclosingCredential,
|
|
||||||
std::vector<std::string> sourcesFriendlyNames);
|
|
||||||
|
|
||||||
Sources m_sources;
|
Sources m_sources;
|
||||||
std::vector<std::string> m_sourcesFriendlyNames;
|
|
||||||
std::string m_logPrefix;
|
std::string m_logPrefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,12 @@ using Azure::Identity::_detail::TokenCache;
|
||||||
using Azure::Identity::_detail::TokenCredentialImpl;
|
using Azure::Identity::_detail::TokenCredentialImpl;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string const MsgPrefix = "Identity: AzureCliCredential";
|
constexpr auto IdentityPrefix = "Identity: ";
|
||||||
|
}
|
||||||
|
|
||||||
void ThrowIfNotSafeCmdLineInput(std::string const& input, std::string const& description)
|
void AzureCliCredential::ThrowIfNotSafeCmdLineInput(
|
||||||
|
std::string const& input,
|
||||||
|
std::string const& description) const
|
||||||
{
|
{
|
||||||
for (auto const c : input)
|
for (auto const c : input)
|
||||||
{
|
{
|
||||||
|
@ -71,20 +74,21 @@ void ThrowIfNotSafeCmdLineInput(std::string const& input, std::string const& des
|
||||||
if (!std::isalnum(c, std::locale::classic()))
|
if (!std::isalnum(c, std::locale::classic()))
|
||||||
{
|
{
|
||||||
throw AuthenticationException(
|
throw AuthenticationException(
|
||||||
MsgPrefix + ": Unsafe command line input found in " + description + ": " + input);
|
IdentityPrefix + GetCredentialName() + ": Unsafe command line input found in "
|
||||||
|
+ description + ": " + input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
|
||||||
|
|
||||||
AzureCliCredential::AzureCliCredential(
|
AzureCliCredential::AzureCliCredential(
|
||||||
std::string tenantId,
|
std::string tenantId,
|
||||||
DateTime::duration cliProcessTimeout,
|
DateTime::duration cliProcessTimeout,
|
||||||
Core::Credentials::TokenCredentialOptions const& options)
|
Core::Credentials::TokenCredentialOptions const& options)
|
||||||
: m_tenantId(std::move(tenantId)), m_cliProcessTimeout(std::move(cliProcessTimeout))
|
: TokenCredential("AzureCliCredential"), m_tenantId(std::move(tenantId)),
|
||||||
|
m_cliProcessTimeout(std::move(cliProcessTimeout))
|
||||||
{
|
{
|
||||||
static_cast<void>(options);
|
static_cast<void>(options);
|
||||||
|
|
||||||
ThrowIfNotSafeCmdLineInput(m_tenantId, "TenantID");
|
ThrowIfNotSafeCmdLineInput(m_tenantId, "TenantID");
|
||||||
|
|
||||||
auto const logLevel = Logger::Level::Informational;
|
auto const logLevel = Logger::Level::Informational;
|
||||||
|
@ -92,7 +96,7 @@ AzureCliCredential::AzureCliCredential(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
MsgPrefix
|
IdentityPrefix + GetCredentialName()
|
||||||
+ " created.\n"
|
+ " created.\n"
|
||||||
"Successful creation does not guarantee further successful token retrieval.");
|
"Successful creation does not guarantee further successful token retrieval.");
|
||||||
}
|
}
|
||||||
|
@ -161,7 +165,8 @@ AccessToken AzureCliCredential::GetToken(
|
||||||
}
|
}
|
||||||
catch (std::exception const& e)
|
catch (std::exception const& e)
|
||||||
{
|
{
|
||||||
auto const errorMsg = MsgPrefix + " didn't get the token: \"" + e.what() + '\"';
|
auto const errorMsg
|
||||||
|
= IdentityPrefix + GetCredentialName() + " didn't get the token: \"" + e.what() + '\"';
|
||||||
|
|
||||||
auto const logLevel = Logger::Level::Warning;
|
auto const logLevel = Logger::Level::Warning;
|
||||||
if (Log::ShouldWrite(logLevel))
|
if (Log::ShouldWrite(logLevel))
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include "azure/identity/chained_token_credential.hpp"
|
#include "azure/identity/chained_token_credential.hpp"
|
||||||
|
|
||||||
#include "azure/core/internal/diagnostics/log.hpp"
|
#include "azure/core/internal/diagnostics/log.hpp"
|
||||||
#include <azure/core/azure_assert.hpp>
|
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -15,63 +14,53 @@ using Azure::Core::Diagnostics::Logger;
|
||||||
using Azure::Core::Diagnostics::_internal::Log;
|
using Azure::Core::Diagnostics::_internal::Log;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string const IdentityPrefix = "Identity: ";
|
constexpr auto IdentityPrefix = "Identity: ";
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
ChainedTokenCredential::ChainedTokenCredential(ChainedTokenCredential::Sources sources)
|
ChainedTokenCredential::ChainedTokenCredential(ChainedTokenCredential::Sources sources)
|
||||||
: ChainedTokenCredential(sources, {}, {})
|
: ChainedTokenCredential(sources, {})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ChainedTokenCredential::ChainedTokenCredential(
|
ChainedTokenCredential::ChainedTokenCredential(
|
||||||
ChainedTokenCredential::Sources sources,
|
ChainedTokenCredential::Sources sources,
|
||||||
std::string const& enclosingCredential,
|
std::string const& enclosingCredential)
|
||||||
std::vector<std::string> sourcesFriendlyNames)
|
: TokenCredential("ChainedTokenCredential"), m_sources(std::move(sources))
|
||||||
: m_sources(std::move(sources)), m_sourcesFriendlyNames(std::move(sourcesFriendlyNames))
|
|
||||||
{
|
{
|
||||||
// LCOV_EXCL_START
|
m_logPrefix = IdentityPrefix
|
||||||
AZURE_ASSERT(m_sourcesFriendlyNames.empty() || m_sourcesFriendlyNames.size() == m_sources.size());
|
+ (enclosingCredential.empty() ? GetCredentialName()
|
||||||
// LCOV_EXCL_STOP
|
: (enclosingCredential + " -> " + GetCredentialName()))
|
||||||
|
+ ": ";
|
||||||
|
|
||||||
auto const logLevel = m_sources.empty() ? Logger::Level::Warning : Logger::Level::Informational;
|
auto const logLevel = m_sources.empty() ? Logger::Level::Warning : Logger::Level::Informational;
|
||||||
if (Log::ShouldWrite(logLevel))
|
if (Log::ShouldWrite(logLevel))
|
||||||
{
|
{
|
||||||
std::string credentialsList;
|
std::string credSourceDetails = " with EMPTY chain of credentials.";
|
||||||
if (!m_sourcesFriendlyNames.empty())
|
if (!m_sources.empty())
|
||||||
{
|
{
|
||||||
auto const sourceDescriptionsSize = m_sourcesFriendlyNames.size();
|
credSourceDetails = " with the following credentials: ";
|
||||||
for (size_t i = 0; i < (sourceDescriptionsSize - 1); ++i)
|
|
||||||
|
auto const sourcesSize = m_sources.size();
|
||||||
|
for (size_t i = 0; i < sourcesSize; ++i)
|
||||||
{
|
{
|
||||||
credentialsList += m_sourcesFriendlyNames[i] + ", ";
|
if (i != 0)
|
||||||
|
{
|
||||||
|
credSourceDetails += ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
credSourceDetails += m_sources[i]->GetCredentialName();
|
||||||
}
|
}
|
||||||
|
|
||||||
credentialsList += m_sourcesFriendlyNames.back();
|
credSourceDetails += '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
IdentityPrefix
|
IdentityPrefix
|
||||||
+ (enclosingCredential.empty()
|
+ (enclosingCredential.empty()
|
||||||
? "ChainedTokenCredential: Created"
|
? (GetCredentialName() + ": Created")
|
||||||
: (enclosingCredential + ": Created ChainedTokenCredential"))
|
: (enclosingCredential + ": Created " + GetCredentialName()))
|
||||||
+ " with "
|
+ credSourceDetails);
|
||||||
+ (m_sourcesFriendlyNames.empty()
|
|
||||||
? (std::to_string(m_sources.size()) + " credentials.")
|
|
||||||
: (std::string("the following credentials: ") + credentialsList + '.')));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_logPrefix = IdentityPrefix
|
|
||||||
+ (enclosingCredential.empty() ? "ChainedTokenCredential"
|
|
||||||
: (enclosingCredential + " -> ChainedTokenCredential"))
|
|
||||||
+ ": ";
|
|
||||||
|
|
||||||
if (m_sourcesFriendlyNames.empty())
|
|
||||||
{
|
|
||||||
auto const sourcesSize = m_sources.size();
|
|
||||||
for (size_t i = 1; i <= sourcesSize; ++i)
|
|
||||||
{
|
|
||||||
m_sourcesFriendlyNames.push_back(std::string("credential #") + std::to_string(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +95,8 @@ AccessToken ChainedTokenCredential::GetToken(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
m_logPrefix + "Successfully got token from " + m_sourcesFriendlyNames[i] + '.');
|
m_logPrefix + "Successfully got token from " + m_sources[i]->GetCredentialName()
|
||||||
|
+ '.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +110,7 @@ AccessToken ChainedTokenCredential::GetToken(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
m_logPrefix + "Failed to get token from " + m_sourcesFriendlyNames[i] + ": "
|
m_logPrefix + "Failed to get token from " + m_sources[i]->GetCredentialName() + ": "
|
||||||
+ e.what());
|
+ e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,5 +129,5 @@ AccessToken ChainedTokenCredential::GetToken(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw AuthenticationException("Failed to get token from ChainedTokenCredential.");
|
throw AuthenticationException("Failed to get token from " + GetCredentialName() + '.');
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,8 @@ ClientCertificateCredential::ClientCertificateCredential(
|
||||||
std::string const& clientCertificatePath,
|
std::string const& clientCertificatePath,
|
||||||
std::string const& authorityHost,
|
std::string const& authorityHost,
|
||||||
TokenCredentialOptions const& options)
|
TokenCredentialOptions const& options)
|
||||||
: m_clientCredentialCore(tenantId, authorityHost),
|
: TokenCredential("ClientCertificateCredential"),
|
||||||
|
m_clientCredentialCore(tenantId, authorityHost),
|
||||||
m_tokenCredentialImpl(std::make_unique<TokenCredentialImpl>(options)),
|
m_tokenCredentialImpl(std::make_unique<TokenCredentialImpl>(options)),
|
||||||
m_requestBody(
|
m_requestBody(
|
||||||
std::string(
|
std::string(
|
||||||
|
|
|
@ -21,7 +21,7 @@ ClientSecretCredential::ClientSecretCredential(
|
||||||
std::string const& clientSecret,
|
std::string const& clientSecret,
|
||||||
std::string const& authorityHost,
|
std::string const& authorityHost,
|
||||||
TokenCredentialOptions const& options)
|
TokenCredentialOptions const& options)
|
||||||
: m_clientCredentialCore(tenantId, authorityHost),
|
: TokenCredential("ClientSecretCredential"), m_clientCredentialCore(tenantId, authorityHost),
|
||||||
m_tokenCredentialImpl(std::make_unique<TokenCredentialImpl>(options)),
|
m_tokenCredentialImpl(std::make_unique<TokenCredentialImpl>(options)),
|
||||||
m_requestBody(
|
m_requestBody(
|
||||||
std::string("grant_type=client_credentials&client_id=") + Url::Encode(clientId)
|
std::string("grant_type=client_credentials&client_id=") + Url::Encode(clientId)
|
||||||
|
|
|
@ -17,10 +17,11 @@ using Azure::Core::Diagnostics::Logger;
|
||||||
using Azure::Core::Diagnostics::_internal::Log;
|
using Azure::Core::Diagnostics::_internal::Log;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string const IdentityPrefix = "Identity: ";
|
constexpr auto IdentityPrefix = "Identity: ";
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
DefaultAzureCredential::DefaultAzureCredential(TokenCredentialOptions const& options)
|
DefaultAzureCredential::DefaultAzureCredential(TokenCredentialOptions const& options)
|
||||||
|
: TokenCredential("DefaultAzureCredential")
|
||||||
{
|
{
|
||||||
// Initializing m_credential below and not in the member initializer list to have a specific order
|
// Initializing m_credential below and not in the member initializer list to have a specific order
|
||||||
// of log messages.
|
// of log messages.
|
||||||
|
@ -29,13 +30,16 @@ DefaultAzureCredential::DefaultAzureCredential(TokenCredentialOptions const& opt
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
IdentityPrefix
|
std::string(IdentityPrefix) + "Creating " + GetCredentialName()
|
||||||
+ "Creating DefaultAzureCredential which combines mutiple parameterless credentials "
|
+ " which combines mutiple parameterless credentials "
|
||||||
"into a single one (by using ChainedTokenCredential)."
|
"into a single one (by using ChainedTokenCredential).\n"
|
||||||
"\nDefaultAzureCredential is only recommended for the early stages of development, "
|
+ GetCredentialName()
|
||||||
|
+ " is only recommended for the early stages of development, "
|
||||||
"and not for usage in production environment."
|
"and not for usage in production environment."
|
||||||
"\nOnce the developer focuses on the Credentials and Authentication aspects of their "
|
"\nOnce the developer focuses on the Credentials and Authentication aspects "
|
||||||
"application, DefaultAzureCredential needs to be replaced with the credential that "
|
"of their application, "
|
||||||
|
+ GetCredentialName()
|
||||||
|
+ " needs to be replaced with the credential that "
|
||||||
"is the better fit for the application.");
|
"is the better fit for the application.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,9 +51,7 @@ DefaultAzureCredential::DefaultAzureCredential(TokenCredentialOptions const& opt
|
||||||
// Using the ChainedTokenCredential's private constructor for more detailed log messages.
|
// Using the ChainedTokenCredential's private constructor for more detailed log messages.
|
||||||
m_credentials.reset(new ChainedTokenCredential(
|
m_credentials.reset(new ChainedTokenCredential(
|
||||||
ChainedTokenCredential::Sources{envCred, azCliCred, managedIdentityCred},
|
ChainedTokenCredential::Sources{envCred, azCliCred, managedIdentityCred},
|
||||||
"DefaultAzureCredential", // extra args for the ChainedTokenCredential's private constructor.
|
GetCredentialName())); // extra arg for the ChainedTokenCredential's private constructor.
|
||||||
std::vector<std::string>{
|
|
||||||
"EnvironmentCredential", "AzureCliCredential", "ManagedIdentityCredential"}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultAzureCredential::~DefaultAzureCredential() = default;
|
DefaultAzureCredential::~DefaultAzureCredential() = default;
|
||||||
|
@ -64,9 +66,10 @@ AccessToken DefaultAzureCredential::GetToken(
|
||||||
}
|
}
|
||||||
catch (AuthenticationException const&)
|
catch (AuthenticationException const&)
|
||||||
{
|
{
|
||||||
throw AuthenticationException("Failed to get token from DefaultAzureCredential."
|
throw AuthenticationException(
|
||||||
"\nSee Azure::Core::Diagnostics::Logger for details "
|
"Failed to get token from " + GetCredentialName()
|
||||||
"(https://github.com/Azure/azure-sdk-for-cpp/tree/main/sdk/"
|
+ ".\nSee Azure::Core::Diagnostics::Logger for details "
|
||||||
"identity/azure-identity#troubleshooting).");
|
"(https://github.com/Azure/azure-sdk-for-cpp/tree/main/sdk/"
|
||||||
|
"identity/azure-identity#troubleshooting).");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,19 @@ constexpr auto AzureClientSecretEnvVarName = "AZURE_CLIENT_SECRET";
|
||||||
constexpr auto AzureAuthorityHostEnvVarName = "AZURE_AUTHORITY_HOST";
|
constexpr auto AzureAuthorityHostEnvVarName = "AZURE_AUTHORITY_HOST";
|
||||||
constexpr auto AzureClientCertificatePathEnvVarName = "AZURE_CLIENT_CERTIFICATE_PATH";
|
constexpr auto AzureClientCertificatePathEnvVarName = "AZURE_CLIENT_CERTIFICATE_PATH";
|
||||||
|
|
||||||
std::string const LogMsgPrefix = "Identity: EnvironmentCredential";
|
constexpr auto IdentityPrefix = "Identity: ";
|
||||||
|
|
||||||
void PrintCredentialCreationLogMessage(
|
void PrintCredentialCreationLogMessage(
|
||||||
|
std::string const& logMsgPrefix,
|
||||||
std::vector<std::pair<char const*, char const*>> const& envVarsToParams,
|
std::vector<std::pair<char const*, char const*>> const& envVarsToParams,
|
||||||
char const* credThatGetsCreated);
|
char const* credThatGetsCreated);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
||||||
|
: TokenCredential("EnvironmentCredential")
|
||||||
{
|
{
|
||||||
|
auto const logMsgPrefix = IdentityPrefix + GetCredentialName();
|
||||||
|
|
||||||
auto tenantId = Environment::GetVariable(AzureTenantIdEnvVarName);
|
auto tenantId = Environment::GetVariable(AzureTenantIdEnvVarName);
|
||||||
auto clientId = Environment::GetVariable(AzureClientIdEnvVarName);
|
auto clientId = Environment::GetVariable(AzureClientIdEnvVarName);
|
||||||
|
|
||||||
|
@ -54,6 +58,7 @@ EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
||||||
if (!authority.empty())
|
if (!authority.empty())
|
||||||
{
|
{
|
||||||
PrintCredentialCreationLogMessage(
|
PrintCredentialCreationLogMessage(
|
||||||
|
logMsgPrefix,
|
||||||
{
|
{
|
||||||
{AzureTenantIdEnvVarName, "tenantId"},
|
{AzureTenantIdEnvVarName, "tenantId"},
|
||||||
{AzureClientIdEnvVarName, "clientId"},
|
{AzureClientIdEnvVarName, "clientId"},
|
||||||
|
@ -72,6 +77,7 @@ EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PrintCredentialCreationLogMessage(
|
PrintCredentialCreationLogMessage(
|
||||||
|
logMsgPrefix,
|
||||||
{
|
{
|
||||||
{AzureTenantIdEnvVarName, "tenantId"},
|
{AzureTenantIdEnvVarName, "tenantId"},
|
||||||
{AzureClientIdEnvVarName, "clientId"},
|
{AzureClientIdEnvVarName, "clientId"},
|
||||||
|
@ -88,6 +94,7 @@ EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
||||||
if (!authority.empty())
|
if (!authority.empty())
|
||||||
{
|
{
|
||||||
PrintCredentialCreationLogMessage(
|
PrintCredentialCreationLogMessage(
|
||||||
|
logMsgPrefix,
|
||||||
{
|
{
|
||||||
{AzureTenantIdEnvVarName, "tenantId"},
|
{AzureTenantIdEnvVarName, "tenantId"},
|
||||||
{AzureClientIdEnvVarName, "clientId"},
|
{AzureClientIdEnvVarName, "clientId"},
|
||||||
|
@ -106,6 +113,7 @@ EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PrintCredentialCreationLogMessage(
|
PrintCredentialCreationLogMessage(
|
||||||
|
logMsgPrefix,
|
||||||
{
|
{
|
||||||
{AzureTenantIdEnvVarName, "tenantId"},
|
{AzureTenantIdEnvVarName, "tenantId"},
|
||||||
{AzureClientIdEnvVarName, "clientId"},
|
{AzureClientIdEnvVarName, "clientId"},
|
||||||
|
@ -124,7 +132,7 @@ EnvironmentCredential::EnvironmentCredential(TokenCredentialOptions options)
|
||||||
auto const logLevel = Logger::Level::Warning;
|
auto const logLevel = Logger::Level::Warning;
|
||||||
if (Log::ShouldWrite(logLevel))
|
if (Log::ShouldWrite(logLevel))
|
||||||
{
|
{
|
||||||
auto const basicMessage = LogMsgPrefix + " was not initialized with underlying credential";
|
auto const basicMessage = logMsgPrefix + " was not initialized with underlying credential";
|
||||||
|
|
||||||
if (!Log::ShouldWrite(Logger::Level::Verbose))
|
if (!Log::ShouldWrite(Logger::Level::Verbose))
|
||||||
{
|
{
|
||||||
|
@ -163,7 +171,8 @@ AccessToken EnvironmentCredential::GetToken(
|
||||||
{
|
{
|
||||||
if (!m_credentialImpl)
|
if (!m_credentialImpl)
|
||||||
{
|
{
|
||||||
auto const AuthUnavailable = LogMsgPrefix + " authentication unavailable. ";
|
auto const AuthUnavailable
|
||||||
|
= IdentityPrefix + GetCredentialName() + " authentication unavailable. ";
|
||||||
|
|
||||||
{
|
{
|
||||||
auto const logLevel = Logger::Level::Warning;
|
auto const logLevel = Logger::Level::Warning;
|
||||||
|
@ -171,7 +180,7 @@ AccessToken EnvironmentCredential::GetToken(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
AuthUnavailable + "See earlier EnvironmentCredential log messages for details.");
|
AuthUnavailable + "See earlier " + GetCredentialName() + " log messages for details.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +193,7 @@ AccessToken EnvironmentCredential::GetToken(
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void PrintCredentialCreationLogMessage(
|
void PrintCredentialCreationLogMessage(
|
||||||
|
std::string const& logMsgPrefix,
|
||||||
std::vector<std::pair<char const*, char const*>> const& envVarsToParams,
|
std::vector<std::pair<char const*, char const*>> const& envVarsToParams,
|
||||||
char const* credThatGetsCreated)
|
char const* credThatGetsCreated)
|
||||||
{
|
{
|
||||||
|
@ -193,7 +203,7 @@ void PrintCredentialCreationLogMessage(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
Logger::Level::Informational,
|
Logger::Level::Informational,
|
||||||
LogMsgPrefix + " gets created with " + credThatGetsCreated + '.');
|
logMsgPrefix + " gets created with " + credThatGetsCreated + '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -224,7 +234,7 @@ void PrintCredentialCreationLogMessage(
|
||||||
|
|
||||||
Log::Write(
|
Log::Write(
|
||||||
Logger::Level::Verbose,
|
Logger::Level::Verbose,
|
||||||
LogMsgPrefix + ": " + envVars + " environment variables are set, so " + credThatGetsCreated
|
logMsgPrefix + ": " + envVars + " environment variables are set, so " + credThatGetsCreated
|
||||||
+ " with corresponding " + credParams + " gets created.");
|
+ " with corresponding " + credParams + " gets created.");
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -8,13 +8,16 @@ using namespace Azure::Identity;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
||||||
|
std::string const& credentialName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||||
{
|
{
|
||||||
using namespace Azure::Core::Credentials;
|
using namespace Azure::Core::Credentials;
|
||||||
using namespace Azure::Identity::_detail;
|
using namespace Azure::Identity::_detail;
|
||||||
static std::unique_ptr<ManagedIdentitySource> (*managedIdentitySourceCreate[])(
|
static std::unique_ptr<ManagedIdentitySource> (*managedIdentitySourceCreate[])(
|
||||||
std::string const& clientId, TokenCredentialOptions const& options)
|
std::string const& credName,
|
||||||
|
std::string const& clientId,
|
||||||
|
TokenCredentialOptions const& options)
|
||||||
= {AppServiceV2019ManagedIdentitySource::Create,
|
= {AppServiceV2019ManagedIdentitySource::Create,
|
||||||
AppServiceV2017ManagedIdentitySource::Create,
|
AppServiceV2017ManagedIdentitySource::Create,
|
||||||
CloudShellManagedIdentitySource::Create,
|
CloudShellManagedIdentitySource::Create,
|
||||||
|
@ -25,7 +28,7 @@ std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
||||||
// For that reason, it is not possible to cover that execution branch in tests.
|
// For that reason, it is not possible to cover that execution branch in tests.
|
||||||
for (auto create : managedIdentitySourceCreate) // LCOV_EXCL_LINE
|
for (auto create : managedIdentitySourceCreate) // LCOV_EXCL_LINE
|
||||||
{
|
{
|
||||||
if (auto source = create(clientId, options))
|
if (auto source = create(credentialName, clientId, options))
|
||||||
{
|
{
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +36,7 @@ std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
throw AuthenticationException(
|
throw AuthenticationException(
|
||||||
"ManagedIdentityCredential authentication unavailable. No Managed Identity endpoint found.");
|
credentialName + " authentication unavailable. No Managed Identity endpoint found.");
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -43,8 +46,9 @@ ManagedIdentityCredential::~ManagedIdentityCredential() = default;
|
||||||
ManagedIdentityCredential::ManagedIdentityCredential(
|
ManagedIdentityCredential::ManagedIdentityCredential(
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||||
: m_managedIdentitySource(CreateManagedIdentitySource(clientId, options))
|
: TokenCredential("ManagedIdentityCredential")
|
||||||
{
|
{
|
||||||
|
m_managedIdentitySource = CreateManagedIdentitySource(GetCredentialName(), clientId, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
ManagedIdentityCredential::ManagedIdentityCredential(
|
ManagedIdentityCredential::ManagedIdentityCredential(
|
||||||
|
|
|
@ -19,28 +19,28 @@ using Azure::Core::Diagnostics::Logger;
|
||||||
using Azure::Core::Diagnostics::_internal::Log;
|
using Azure::Core::Diagnostics::_internal::Log;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string const IdentityPrefix = "Identity: ";
|
constexpr auto IdentityPrefix = "Identity: ";
|
||||||
constexpr auto CredPrefix = "ManagedIdentityCredential";
|
|
||||||
|
|
||||||
std::string WithSourceMessage(std::string const& credSource)
|
std::string WithSourceMessage(std::string const& credSource)
|
||||||
{
|
{
|
||||||
return " with " + credSource + " source";
|
return " with " + credSource + " source";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintEnvNotSetUpMessage(std::string const& credSource)
|
void PrintEnvNotSetUpMessage(std::string const& credName, std::string const& credSource)
|
||||||
{
|
{
|
||||||
auto const logLevel = Logger::Level::Verbose;
|
auto const logLevel = Logger::Level::Verbose;
|
||||||
if (Log::ShouldWrite(logLevel))
|
if (Log::ShouldWrite(logLevel))
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
IdentityPrefix + CredPrefix + ": Environment is not set up for the credential to be created"
|
IdentityPrefix + credName + ": Environment is not set up for the credential to be created"
|
||||||
+ WithSourceMessage(credSource) + '.');
|
+ WithSourceMessage(credSource) + '.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& url,
|
std::string const& url,
|
||||||
char const* envVarName,
|
char const* envVarName,
|
||||||
std::string const& credSource)
|
std::string const& credSource)
|
||||||
|
@ -57,7 +57,7 @@ Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
IdentityPrefix + CredPrefix + " will be created" + WithSourceMessage(credSource) + '.');
|
IdentityPrefix + credName + " will be created" + WithSourceMessage(credSource) + '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpointUrl;
|
return endpointUrl;
|
||||||
|
@ -69,7 +69,7 @@ Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const errorMessage = CredPrefix + WithSourceMessage(credSource)
|
auto const errorMessage = credName + WithSourceMessage(credSource)
|
||||||
+ ": Failed to create: The environment variable \'" + envVarName
|
+ ": Failed to create: The environment variable \'" + envVarName
|
||||||
+ "\' contains an invalid URL.";
|
+ "\' contains an invalid URL.";
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Azure::Core::Credentials::TokenCredentialOptions const& options,
|
Azure::Core::Credentials::TokenCredentialOptions const& options,
|
||||||
char const* endpointVarName,
|
char const* endpointVarName,
|
||||||
|
@ -98,10 +99,13 @@ std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
||||||
if (!msiEndpoint.empty() && !msiSecret.empty())
|
if (!msiEndpoint.empty() && !msiSecret.empty())
|
||||||
{
|
{
|
||||||
return std::unique_ptr<ManagedIdentitySource>(new T(
|
return std::unique_ptr<ManagedIdentitySource>(new T(
|
||||||
clientId, options, ParseEndpointUrl(msiEndpoint, endpointVarName, credSource), msiSecret));
|
clientId,
|
||||||
|
options,
|
||||||
|
ParseEndpointUrl(credName, msiEndpoint, endpointVarName, credSource),
|
||||||
|
msiSecret));
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintEnvNotSetUpMessage(credSource);
|
PrintEnvNotSetUpMessage(credName, credSource);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,22 +167,25 @@ Azure::Core::Credentials::AccessToken AppServiceManagedIdentitySource::GetToken(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ManagedIdentitySource> AppServiceV2017ManagedIdentitySource::Create(
|
std::unique_ptr<ManagedIdentitySource> AppServiceV2017ManagedIdentitySource::Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options)
|
Core::Credentials::TokenCredentialOptions const& options)
|
||||||
{
|
{
|
||||||
return AppServiceManagedIdentitySource::Create<AppServiceV2017ManagedIdentitySource>(
|
return AppServiceManagedIdentitySource::Create<AppServiceV2017ManagedIdentitySource>(
|
||||||
clientId, options, "MSI_ENDPOINT", "MSI_SECRET", "2017");
|
credName, clientId, options, "MSI_ENDPOINT", "MSI_SECRET", "2017");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ManagedIdentitySource> AppServiceV2019ManagedIdentitySource::Create(
|
std::unique_ptr<ManagedIdentitySource> AppServiceV2019ManagedIdentitySource::Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options)
|
Core::Credentials::TokenCredentialOptions const& options)
|
||||||
{
|
{
|
||||||
return AppServiceManagedIdentitySource::Create<AppServiceV2019ManagedIdentitySource>(
|
return AppServiceManagedIdentitySource::Create<AppServiceV2019ManagedIdentitySource>(
|
||||||
clientId, options, "IDENTITY_ENDPOINT", "IDENTITY_HEADER", "2019");
|
credName, clientId, options, "IDENTITY_ENDPOINT", "IDENTITY_HEADER", "2019");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ManagedIdentitySource> CloudShellManagedIdentitySource::Create(
|
std::unique_ptr<ManagedIdentitySource> CloudShellManagedIdentitySource::Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||||
{
|
{
|
||||||
|
@ -190,10 +197,10 @@ std::unique_ptr<ManagedIdentitySource> CloudShellManagedIdentitySource::Create(
|
||||||
if (!msiEndpoint.empty())
|
if (!msiEndpoint.empty())
|
||||||
{
|
{
|
||||||
return std::unique_ptr<ManagedIdentitySource>(new CloudShellManagedIdentitySource(
|
return std::unique_ptr<ManagedIdentitySource>(new CloudShellManagedIdentitySource(
|
||||||
clientId, options, ParseEndpointUrl(msiEndpoint, EndpointVarName, CredSource)));
|
clientId, options, ParseEndpointUrl(credName, msiEndpoint, EndpointVarName, CredSource)));
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintEnvNotSetUpMessage(CredSource);
|
PrintEnvNotSetUpMessage(credName, CredSource);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +259,7 @@ Azure::Core::Credentials::AccessToken CloudShellManagedIdentitySource::GetToken(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||||
{
|
{
|
||||||
|
@ -264,7 +272,7 @@ std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
||||||
|
|
||||||
if (identityEndpoint.empty() || Environment::GetVariable("IMDS_ENDPOINT").empty())
|
if (identityEndpoint.empty() || Environment::GetVariable("IMDS_ENDPOINT").empty())
|
||||||
{
|
{
|
||||||
PrintEnvNotSetUpMessage(credSource);
|
PrintEnvNotSetUpMessage(credName, credSource);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +285,7 @@ std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::unique_ptr<ManagedIdentitySource>(new AzureArcManagedIdentitySource(
|
return std::unique_ptr<ManagedIdentitySource>(new AzureArcManagedIdentitySource(
|
||||||
options, ParseEndpointUrl(identityEndpoint, EndpointVarName, credSource)));
|
options, ParseEndpointUrl(credName, identityEndpoint, EndpointVarName, credSource)));
|
||||||
}
|
}
|
||||||
|
|
||||||
AzureArcManagedIdentitySource::AzureArcManagedIdentitySource(
|
AzureArcManagedIdentitySource::AzureArcManagedIdentitySource(
|
||||||
|
@ -373,6 +381,7 @@ Azure::Core::Credentials::AccessToken AzureArcManagedIdentitySource::GetToken(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ManagedIdentitySource> ImdsManagedIdentitySource::Create(
|
std::unique_ptr<ManagedIdentitySource> ImdsManagedIdentitySource::Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||||
{
|
{
|
||||||
|
@ -381,7 +390,7 @@ std::unique_ptr<ManagedIdentitySource> ImdsManagedIdentitySource::Create(
|
||||||
{
|
{
|
||||||
Log::Write(
|
Log::Write(
|
||||||
logLevel,
|
logLevel,
|
||||||
IdentityPrefix + CredPrefix + " will be created"
|
IdentityPrefix + credName + " will be created"
|
||||||
+ WithSourceMessage("Azure Instance Metadata Service")
|
+ WithSourceMessage("Azure Instance Metadata Service")
|
||||||
+ ".\nSuccessful creation does not guarantee further successful token retrieval.");
|
+ ".\nSuccessful creation does not guarantee further successful token retrieval.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
_detail::TokenCache m_tokenCache;
|
_detail::TokenCache m_tokenCache;
|
||||||
|
|
||||||
static Core::Url ParseEndpointUrl(
|
static Core::Url ParseEndpointUrl(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& url,
|
std::string const& url,
|
||||||
char const* envVarName,
|
char const* envVarName,
|
||||||
std::string const& credSource);
|
std::string const& credSource);
|
||||||
|
@ -63,6 +64,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options,
|
Core::Credentials::TokenCredentialOptions const& options,
|
||||||
char const* endpointVarName,
|
char const* endpointVarName,
|
||||||
|
@ -97,6 +99,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options);
|
Core::Credentials::TokenCredentialOptions const& options);
|
||||||
};
|
};
|
||||||
|
@ -123,6 +126,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options);
|
Core::Credentials::TokenCredentialOptions const& options);
|
||||||
};
|
};
|
||||||
|
@ -139,6 +143,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options);
|
Core::Credentials::TokenCredentialOptions const& options);
|
||||||
|
|
||||||
|
@ -157,6 +162,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options);
|
Core::Credentials::TokenCredentialOptions const& options);
|
||||||
|
|
||||||
|
@ -175,6 +181,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||||
|
std::string const& credName,
|
||||||
std::string const& clientId,
|
std::string const& clientId,
|
||||||
Core::Credentials::TokenCredentialOptions const& options);
|
Core::Credentials::TokenCredentialOptions const& options);
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,12 @@ TEST(AzureCliCredential, Error)
|
||||||
Logger::SetListener(nullptr);
|
Logger::SetListener(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(AzureCliCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
AzureCliTestCredential const cred(EmptyOutputCommand);
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "AzureCliCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(AzureCliCredential, EmptyOutput)
|
TEST(AzureCliCredential, EmptyOutput)
|
||||||
{
|
{
|
||||||
AzureCliTestCredential const azCliCred(EmptyOutputCommand);
|
AzureCliTestCredential const azCliCred(EmptyOutputCommand);
|
||||||
|
|
|
@ -25,7 +25,7 @@ private:
|
||||||
std::string m_token;
|
std::string m_token;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TestCredential(std::string token = "") : m_token(token) {}
|
TestCredential(std::string token = "") : TokenCredential("TestCredential"), m_token(token) {}
|
||||||
|
|
||||||
mutable bool WasInvoked = false;
|
mutable bool WasInvoked = false;
|
||||||
|
|
||||||
|
@ -45,6 +45,12 @@ public:
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST(ChainedTokenCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
ChainedTokenCredential const cred(ChainedTokenCredential::Sources{});
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "ChainedTokenCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ChainedTokenCredential, Success)
|
TEST(ChainedTokenCredential, Success)
|
||||||
{
|
{
|
||||||
auto c1 = std::make_shared<TestCredential>("Token1");
|
auto c1 = std::make_shared<TestCredential>("Token1");
|
||||||
|
@ -110,7 +116,9 @@ TEST(ChainedTokenCredential, Logging)
|
||||||
ChainedTokenCredential cred({});
|
ChainedTokenCredential cred({});
|
||||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
||||||
EXPECT_EQ(log[0].first, Logger::Level::Warning);
|
EXPECT_EQ(log[0].first, Logger::Level::Warning);
|
||||||
EXPECT_EQ(log[0].second, "Identity: ChainedTokenCredential: Created with 0 credentials.");
|
EXPECT_EQ(
|
||||||
|
log[0].second,
|
||||||
|
"Identity: ChainedTokenCredential: Created with EMPTY chain of credentials.");
|
||||||
|
|
||||||
log.clear();
|
log.clear();
|
||||||
EXPECT_THROW(static_cast<void>(cred.GetToken({}, {})), AuthenticationException);
|
EXPECT_THROW(static_cast<void>(cred.GetToken({}, {})), AuthenticationException);
|
||||||
|
@ -128,7 +136,10 @@ TEST(ChainedTokenCredential, Logging)
|
||||||
ChainedTokenCredential cred({c});
|
ChainedTokenCredential cred({c});
|
||||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
||||||
EXPECT_EQ(log[0].first, Logger::Level::Informational);
|
EXPECT_EQ(log[0].first, Logger::Level::Informational);
|
||||||
EXPECT_EQ(log[0].second, "Identity: ChainedTokenCredential: Created with 1 credentials.");
|
EXPECT_EQ(
|
||||||
|
log[0].second,
|
||||||
|
"Identity: ChainedTokenCredential: Created with the following credentials: "
|
||||||
|
"TestCredential.");
|
||||||
|
|
||||||
log.clear();
|
log.clear();
|
||||||
EXPECT_FALSE(c->WasInvoked);
|
EXPECT_FALSE(c->WasInvoked);
|
||||||
|
@ -141,7 +152,7 @@ TEST(ChainedTokenCredential, Logging)
|
||||||
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
log[0].second,
|
log[0].second,
|
||||||
"Identity: ChainedTokenCredential: Failed to get token from credential #1: "
|
"Identity: ChainedTokenCredential: Failed to get token from TestCredential: "
|
||||||
"Test Error");
|
"Test Error");
|
||||||
|
|
||||||
EXPECT_EQ(log[1].first, Logger::Level::Warning);
|
EXPECT_EQ(log[1].first, Logger::Level::Warning);
|
||||||
|
@ -158,7 +169,10 @@ TEST(ChainedTokenCredential, Logging)
|
||||||
ChainedTokenCredential cred({c1, c2});
|
ChainedTokenCredential cred({c1, c2});
|
||||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
||||||
EXPECT_EQ(log[0].first, Logger::Level::Informational);
|
EXPECT_EQ(log[0].first, Logger::Level::Informational);
|
||||||
EXPECT_EQ(log[0].second, "Identity: ChainedTokenCredential: Created with 2 credentials.");
|
EXPECT_EQ(
|
||||||
|
log[0].second,
|
||||||
|
"Identity: ChainedTokenCredential: Created with the following credentials: "
|
||||||
|
"TestCredential, TestCredential.");
|
||||||
|
|
||||||
log.clear();
|
log.clear();
|
||||||
EXPECT_FALSE(c1->WasInvoked);
|
EXPECT_FALSE(c1->WasInvoked);
|
||||||
|
@ -175,13 +189,13 @@ TEST(ChainedTokenCredential, Logging)
|
||||||
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
log[0].second,
|
log[0].second,
|
||||||
"Identity: ChainedTokenCredential: Failed to get token from credential #1: "
|
"Identity: ChainedTokenCredential: Failed to get token from TestCredential: "
|
||||||
"Test Error");
|
"Test Error");
|
||||||
|
|
||||||
EXPECT_EQ(log[1].first, Logger::Level::Informational);
|
EXPECT_EQ(log[1].first, Logger::Level::Informational);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
log[1].second,
|
log[1].second,
|
||||||
"Identity: ChainedTokenCredential: Successfully got token from credential #2.");
|
"Identity: ChainedTokenCredential: Successfully got token from TestCredential.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::SetListener(nullptr);
|
Logger::SetListener(nullptr);
|
||||||
|
|
|
@ -30,9 +30,20 @@ std::vector<std::string> SplitString(const std::string& s, char separator);
|
||||||
std::string ToString(std::vector<uint8_t> const& vec);
|
std::string ToString(std::vector<uint8_t> const& vec);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST(ClientCertificateCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
TempCertFile const tempCertFile;
|
||||||
|
ClientCertificateCredential const cred(
|
||||||
|
"01234567-89ab-cdef-fedc-ba8976543210",
|
||||||
|
"fedcba98-7654-3210-0123-456789abcdef",
|
||||||
|
TempCertFile::Path);
|
||||||
|
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "ClientCertificateCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ClientCertificateCredential, Regular)
|
TEST(ClientCertificateCredential, Regular)
|
||||||
{
|
{
|
||||||
TempCertFile tempCertFile;
|
TempCertFile const tempCertFile;
|
||||||
|
|
||||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||||
[](auto transport) {
|
[](auto transport) {
|
||||||
|
@ -167,7 +178,7 @@ TEST(ClientCertificateCredential, Regular)
|
||||||
|
|
||||||
TEST(ClientCertificateCredential, AzureStack)
|
TEST(ClientCertificateCredential, AzureStack)
|
||||||
{
|
{
|
||||||
TempCertFile tempCertFile;
|
TempCertFile const tempCertFile;
|
||||||
|
|
||||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||||
[](auto transport) {
|
[](auto transport) {
|
||||||
|
@ -294,7 +305,7 @@ TEST(ClientCertificateCredential, AzureStack)
|
||||||
|
|
||||||
TEST(ClientCertificateCredential, Authority)
|
TEST(ClientCertificateCredential, Authority)
|
||||||
{
|
{
|
||||||
TempCertFile tempCertFile;
|
TempCertFile const tempCertFile;
|
||||||
|
|
||||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||||
[](auto transport) {
|
[](auto transport) {
|
||||||
|
|
|
@ -12,6 +12,16 @@ using Azure::Identity::ClientSecretCredential;
|
||||||
using Azure::Identity::ClientSecretCredentialOptions;
|
using Azure::Identity::ClientSecretCredentialOptions;
|
||||||
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
||||||
|
|
||||||
|
TEST(ClientSecretCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
ClientSecretCredential const cred(
|
||||||
|
"01234567-89ab-cdef-fedc-ba8976543210",
|
||||||
|
"fedcba98-7654-3210-0123-456789abcdef",
|
||||||
|
"CLIENTSECRET");
|
||||||
|
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "ClientSecretCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ClientSecretCredential, Regular)
|
TEST(ClientSecretCredential, Regular)
|
||||||
{
|
{
|
||||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||||
|
|
|
@ -17,6 +17,28 @@ using Azure::Identity::Test::_detail::CredentialTestHelper;
|
||||||
namespace {
|
namespace {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST(DefaultAzureCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
CredentialTestHelper::EnvironmentOverride const env({
|
||||||
|
{"AZURE_TENANT_ID", "01234567-89ab-cdef-fedc-ba8976543210"},
|
||||||
|
{"AZURE_CLIENT_ID", "fedcba98-7654-3210-0123-456789abcdef"},
|
||||||
|
{"AZURE_CLIENT_SECRET", "CLIENTSECRET"},
|
||||||
|
{"AZURE_AUTHORITY_HOST", ""},
|
||||||
|
{"AZURE_USERNAME", ""},
|
||||||
|
{"AZURE_PASSWORD", ""},
|
||||||
|
{"AZURE_CLIENT_CERTIFICATE_PATH", ""},
|
||||||
|
{"MSI_ENDPOINT", ""},
|
||||||
|
{"MSI_SECRET", ""},
|
||||||
|
{"IDENTITY_ENDPOINT", "https://visualstudio.com/"},
|
||||||
|
{"IMDS_ENDPOINT", ""},
|
||||||
|
{"IDENTITY_HEADER", "CLIENTSECRET"},
|
||||||
|
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||||
|
});
|
||||||
|
|
||||||
|
DefaultAzureCredential const cred;
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "DefaultAzureCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(DefaultAzureCredential, LogMessages)
|
TEST(DefaultAzureCredential, LogMessages)
|
||||||
{
|
{
|
||||||
using LogMsgVec = std::vector<std::pair<Logger::Level, std::string>>;
|
using LogMsgVec = std::vector<std::pair<Logger::Level, std::string>>;
|
||||||
|
|
|
@ -13,6 +13,22 @@ using Azure::Core::Http::HttpMethod;
|
||||||
using Azure::Identity::EnvironmentCredential;
|
using Azure::Identity::EnvironmentCredential;
|
||||||
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
||||||
|
|
||||||
|
TEST(EnvironmentCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
CredentialTestHelper::EnvironmentOverride const env({
|
||||||
|
{"AZURE_TENANT_ID", "01234567-89ab-cdef-fedc-ba8976543210"},
|
||||||
|
{"AZURE_CLIENT_ID", "fedcba98-7654-3210-0123-456789abcdef"},
|
||||||
|
{"AZURE_CLIENT_SECRET", "CLIENTSECRET"},
|
||||||
|
{"AZURE_AUTHORITY_HOST", ""},
|
||||||
|
{"AZURE_USERNAME", ""},
|
||||||
|
{"AZURE_PASSWORD", ""},
|
||||||
|
{"AZURE_CLIENT_CERTIFICATE_PATH", ""},
|
||||||
|
});
|
||||||
|
|
||||||
|
EnvironmentCredential const cred;
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "EnvironmentCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(EnvironmentCredential, RegularClientSecretCredential)
|
TEST(EnvironmentCredential, RegularClientSecretCredential)
|
||||||
{
|
{
|
||||||
using Azure::Core::Diagnostics::Logger;
|
using Azure::Core::Diagnostics::Logger;
|
||||||
|
|
|
@ -16,6 +16,21 @@ using Azure::Core::Http::HttpStatusCode;
|
||||||
using Azure::Identity::ManagedIdentityCredential;
|
using Azure::Identity::ManagedIdentityCredential;
|
||||||
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
||||||
|
|
||||||
|
TEST(ManagedIdentityCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
CredentialTestHelper::EnvironmentOverride const env({
|
||||||
|
{"MSI_ENDPOINT", ""},
|
||||||
|
{"MSI_SECRET", ""},
|
||||||
|
{"IDENTITY_ENDPOINT", "https://visualstudio.com/"},
|
||||||
|
{"IMDS_ENDPOINT", ""},
|
||||||
|
{"IDENTITY_HEADER", "CLIENTSECRET"},
|
||||||
|
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||||
|
});
|
||||||
|
|
||||||
|
ManagedIdentityCredential const cred;
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "ManagedIdentityCredential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ManagedIdentityCredential, AppServiceV2019)
|
TEST(ManagedIdentityCredential, AppServiceV2019)
|
||||||
{
|
{
|
||||||
using Azure::Core::Diagnostics::Logger;
|
using Azure::Core::Diagnostics::Logger;
|
||||||
|
|
|
@ -34,15 +34,16 @@ public:
|
||||||
HttpMethod httpMethod,
|
HttpMethod httpMethod,
|
||||||
Url url,
|
Url url,
|
||||||
TokenCredentialOptions const& options)
|
TokenCredentialOptions const& options)
|
||||||
: m_httpMethod(std::move(httpMethod)), m_url(std::move(url)),
|
: TokenCredential("TokenCredentialImplTester"), m_httpMethod(std::move(httpMethod)),
|
||||||
m_tokenCredentialImpl(new TokenCredentialImpl(options))
|
m_url(std::move(url)), m_tokenCredentialImpl(new TokenCredentialImpl(options))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit TokenCredentialImplTester(
|
explicit TokenCredentialImplTester(
|
||||||
std::function<void()> throwingFunction,
|
std::function<void()> throwingFunction,
|
||||||
TokenCredentialOptions const& options)
|
TokenCredentialOptions const& options)
|
||||||
: m_throwingFunction(std::move(throwingFunction)),
|
: TokenCredential("TokenCredentialImplTester"),
|
||||||
|
m_throwingFunction(std::move(throwingFunction)),
|
||||||
m_tokenCredentialImpl(new TokenCredentialImpl(options))
|
m_tokenCredentialImpl(new TokenCredentialImpl(options))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -63,8 +64,41 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Disable deprecation warning
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4996)
|
||||||
|
#elif defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
|
// This credential is needed to test the default behavior when the customer has custom credential
|
||||||
|
// they implemented while using earlier versions of the SDK which didn't have a constructor with
|
||||||
|
// credentialName.
|
||||||
|
class CustomTokenCredential : public TokenCredential {
|
||||||
|
public:
|
||||||
|
AccessToken GetToken(TokenRequestContext const&, Context const&) const override { return {}; }
|
||||||
|
};
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#elif defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif // _MSC_VER
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TEST(CustomTokenCredential, GetCredentialName)
|
||||||
|
{
|
||||||
|
CustomTokenCredential cred;
|
||||||
|
EXPECT_EQ(cred.GetCredentialName(), "Custom Credential");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(TokenCredentialImpl, Normal)
|
TEST(TokenCredentialImpl, Normal)
|
||||||
{
|
{
|
||||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||||
|
|
Загрузка…
Ссылка в новой задаче