Identity: Log Client ID used in ManagedIdentityCredential (#6426)
* Identity: Log Client ID used in ManagedIdentityCredential * Clang-format * [&] --------- Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
This commit is contained in:
parent
8d21d5d40d
commit
237e617a4a
@ -5,6 +5,7 @@
|
||||
### Features Added
|
||||
|
||||
- Added `Subscription` to `AzureCliCredentialOptions` which allows the caller to specify an Azure subscription that does not match the current Azure CLI subscription.
|
||||
- [[#6321]](https://github.com/Azure/azure-sdk-for-cpp/issues/6321) Log Client ID used in `ManagedIdentityCredential`.
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
|
||||
@ -28,9 +28,15 @@ namespace {
|
||||
// host.
|
||||
std::string const ImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
|
||||
|
||||
std::string WithSourceMessage(std::string const& credSource)
|
||||
std::string WithSourceAndClientIdMessage(std::string const& credSource, std::string const& clientId)
|
||||
{
|
||||
return " with " + credSource + " source";
|
||||
std::string result = " with " + credSource + " source";
|
||||
if (!clientId.empty())
|
||||
{
|
||||
result += " and Client ID '" + clientId + '\'';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void PrintEnvNotSetUpMessage(std::string const& credName, std::string const& credSource)
|
||||
@ -38,7 +44,7 @@ void PrintEnvNotSetUpMessage(std::string const& credName, std::string const& cre
|
||||
IdentityLog::Write(
|
||||
IdentityLog::Level::Verbose,
|
||||
credName + ": Environment is not set up for the credential to be created"
|
||||
+ WithSourceMessage(credSource) + '.');
|
||||
+ WithSourceAndClientIdMessage(credSource, {}) + '.');
|
||||
}
|
||||
|
||||
// ExpectedArcKeyDirectory returns the directory expected to contain Azure Arc keys.
|
||||
@ -113,7 +119,8 @@ Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||
std::string const& credName,
|
||||
std::string const& url,
|
||||
char const* envVarName,
|
||||
std::string const& credSource)
|
||||
std::string const& credSource,
|
||||
std::string const& clientId)
|
||||
{
|
||||
using Azure::Core::Url;
|
||||
using Azure::Core::Credentials::AuthenticationException;
|
||||
@ -124,7 +131,7 @@ Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||
|
||||
IdentityLog::Write(
|
||||
IdentityLog::Level::Informational,
|
||||
credName + " will be created" + WithSourceMessage(credSource) + '.');
|
||||
credName + " will be created" + WithSourceAndClientIdMessage(credSource, clientId) + '.');
|
||||
|
||||
return endpointUrl;
|
||||
}
|
||||
@ -135,7 +142,7 @@ Azure::Core::Url ManagedIdentitySource::ParseEndpointUrl(
|
||||
{
|
||||
}
|
||||
|
||||
auto const errorMessage = credName + WithSourceMessage(credSource)
|
||||
auto const errorMessage = credName + WithSourceAndClientIdMessage(credSource, {})
|
||||
+ ": Failed to create: The environment variable \'" + envVarName
|
||||
+ "\' contains an invalid URL.";
|
||||
|
||||
@ -166,7 +173,7 @@ std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
||||
objectId,
|
||||
resourceId,
|
||||
options,
|
||||
ParseEndpointUrl(credName, msiEndpoint, endpointVarName, credSource),
|
||||
ParseEndpointUrl(credName, msiEndpoint, endpointVarName, credSource, clientId),
|
||||
msiSecret));
|
||||
}
|
||||
|
||||
@ -287,7 +294,7 @@ std::unique_ptr<ManagedIdentitySource> CloudShellManagedIdentitySource::Create(
|
||||
constexpr auto EndpointVarName = "MSI_ENDPOINT";
|
||||
auto msiEndpoint = Environment::GetVariable(EndpointVarName);
|
||||
|
||||
std::string const CredSource = "Cloud Shell";
|
||||
std::string const credSource = "Cloud Shell";
|
||||
|
||||
if (!msiEndpoint.empty())
|
||||
{
|
||||
@ -299,10 +306,12 @@ std::unique_ptr<ManagedIdentitySource> CloudShellManagedIdentitySource::Create(
|
||||
}
|
||||
|
||||
return std::unique_ptr<ManagedIdentitySource>(new CloudShellManagedIdentitySource(
|
||||
clientId, options, ParseEndpointUrl(credName, msiEndpoint, EndpointVarName, CredSource)));
|
||||
clientId,
|
||||
options,
|
||||
ParseEndpointUrl(credName, msiEndpoint, EndpointVarName, credSource, clientId)));
|
||||
}
|
||||
|
||||
PrintEnvNotSetUpMessage(credName, CredSource);
|
||||
PrintEnvNotSetUpMessage(credName, credSource);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -380,7 +389,8 @@ std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
||||
}
|
||||
|
||||
return std::unique_ptr<ManagedIdentitySource>(new AzureArcManagedIdentitySource(
|
||||
options, ParseEndpointUrl(credName, identityEndpoint, EndpointVarName, credSource)));
|
||||
options,
|
||||
ParseEndpointUrl(credName, identityEndpoint, EndpointVarName, credSource, clientId)));
|
||||
}
|
||||
|
||||
AzureArcManagedIdentitySource::AzureArcManagedIdentitySource(
|
||||
@ -488,7 +498,8 @@ std::unique_ptr<ManagedIdentitySource> ImdsManagedIdentitySource::Create(
|
||||
{
|
||||
IdentityLog::Write(
|
||||
IdentityLog::Level::Informational,
|
||||
credName + " will be created" + WithSourceMessage("Azure Instance Metadata Service")
|
||||
credName + " will be created"
|
||||
+ WithSourceAndClientIdMessage("Azure Instance Metadata Service", clientId)
|
||||
+ ".\nSuccessful creation does not guarantee further successful token retrieval.");
|
||||
|
||||
return std::unique_ptr<ManagedIdentitySource>(
|
||||
|
||||
@ -32,7 +32,8 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
std::string const& credName,
|
||||
std::string const& url,
|
||||
char const* envVarName,
|
||||
std::string const& credSource);
|
||||
std::string const& credSource,
|
||||
std::string const& clientId);
|
||||
|
||||
explicit ManagedIdentitySource(
|
||||
std::string clientId,
|
||||
|
||||
@ -238,8 +238,14 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2019ClientId)
|
||||
{
|
||||
using Azure::Core::Diagnostics::Logger;
|
||||
using LogMsgVec = std::vector<std::pair<Logger::Level, std::string>>;
|
||||
LogMsgVec log;
|
||||
Logger::SetLevel(Logger::Level::Verbose);
|
||||
Logger::SetListener([&](auto lvl, auto msg) { log.push_back(std::make_pair(lvl, msg)); });
|
||||
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
[&](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
@ -252,8 +258,19 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
{"IDENTITY_SERVER_THUMBPRINT", "0123456789abcdef0123456789abcdef01234567"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
auto credential = std::make_unique<ManagedIdentityCredential>(
|
||||
"fedcba98-7654-3210-0123-456789abcdef", options);
|
||||
|
||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(1));
|
||||
EXPECT_EQ(log[0].first, Logger::Level::Informational);
|
||||
EXPECT_EQ(
|
||||
log[0].second,
|
||||
"Identity: ManagedIdentityCredential will be created with App Service 2019 source"
|
||||
" and Client ID 'fedcba98-7654-3210-0123-456789abcdef'.");
|
||||
|
||||
log.clear();
|
||||
|
||||
return credential;
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
@ -324,6 +341,8 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
|
||||
Logger::SetListener(nullptr);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2019ResourceId)
|
||||
@ -699,8 +718,14 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2017ClientId)
|
||||
{
|
||||
using Azure::Core::Diagnostics::Logger;
|
||||
using LogMsgVec = std::vector<std::pair<Logger::Level, std::string>>;
|
||||
LogMsgVec log;
|
||||
Logger::SetLevel(Logger::Level::Verbose);
|
||||
Logger::SetListener([&](auto lvl, auto msg) { log.push_back(std::make_pair(lvl, msg)); });
|
||||
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
[&](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
@ -713,8 +738,26 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
{"IDENTITY_SERVER_THUMBPRINT", "0123456789abcdef0123456789abcdef01234567"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
auto credential = std::make_unique<ManagedIdentityCredential>(
|
||||
"fedcba98-7654-3210-0123-456789abcdef", options);
|
||||
|
||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(2));
|
||||
|
||||
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[0].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with App Service 2019 source.");
|
||||
|
||||
EXPECT_EQ(log[1].first, Logger::Level::Informational);
|
||||
EXPECT_EQ(
|
||||
log[1].second,
|
||||
"Identity: ManagedIdentityCredential will be created with App Service 2017 source"
|
||||
" and Client ID 'fedcba98-7654-3210-0123-456789abcdef'.");
|
||||
|
||||
log.clear();
|
||||
|
||||
return credential;
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
@ -785,6 +828,8 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
|
||||
Logger::SetListener(nullptr);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2017ResourceId)
|
||||
@ -2455,9 +2500,15 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
|
||||
TEST(ManagedIdentityCredential, ImdsClientId)
|
||||
{
|
||||
using Azure::Core::Diagnostics::Logger;
|
||||
using LogMsgVec = std::vector<std::pair<Logger::Level, std::string>>;
|
||||
LogMsgVec log;
|
||||
Logger::SetLevel(Logger::Level::Verbose);
|
||||
Logger::SetListener([&](auto lvl, auto msg) { log.push_back(std::make_pair(lvl, msg)); });
|
||||
|
||||
{
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
[&](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
@ -2470,8 +2521,46 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
auto credential = std::make_unique<ManagedIdentityCredential>(
|
||||
"fedcba98-7654-3210-0123-456789abcdef", options);
|
||||
|
||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(5));
|
||||
|
||||
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[0].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with App Service 2019 source.");
|
||||
|
||||
EXPECT_EQ(log[1].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[1].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with App Service 2017 source.");
|
||||
|
||||
EXPECT_EQ(log[2].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[2].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with Cloud Shell source.");
|
||||
|
||||
EXPECT_EQ(log[3].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[3].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with Azure Arc source.");
|
||||
|
||||
EXPECT_EQ(log[4].first, Logger::Level::Informational);
|
||||
EXPECT_EQ(
|
||||
log[4].second,
|
||||
"Identity: ManagedIdentityCredential will be created "
|
||||
"with Azure Instance Metadata Service source"
|
||||
" and Client ID 'fedcba98-7654-3210-0123-456789abcdef'."
|
||||
"\nSuccessful creation does not guarantee further successful token retrieval.");
|
||||
|
||||
log.clear();
|
||||
|
||||
return credential;
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
@ -2545,7 +2634,7 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
}
|
||||
{
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
[&](auto transport) {
|
||||
ManagedIdentityCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
options.IdentityId = ManagedIdentityId::FromUserAssignedClientId(
|
||||
@ -2560,7 +2649,47 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(options);
|
||||
log.clear();
|
||||
|
||||
auto credential = std::make_unique<ManagedIdentityCredential>(options);
|
||||
|
||||
EXPECT_EQ(log.size(), LogMsgVec::size_type(5));
|
||||
|
||||
EXPECT_EQ(log[0].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[0].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with App Service 2019 source.");
|
||||
|
||||
EXPECT_EQ(log[1].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[1].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with App Service 2017 source.");
|
||||
|
||||
EXPECT_EQ(log[2].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[2].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with Cloud Shell source.");
|
||||
|
||||
EXPECT_EQ(log[3].first, Logger::Level::Verbose);
|
||||
EXPECT_EQ(
|
||||
log[3].second,
|
||||
"Identity: ManagedIdentityCredential: Environment is not set up for the credential "
|
||||
"to be created with Azure Arc source.");
|
||||
|
||||
EXPECT_EQ(log[4].first, Logger::Level::Informational);
|
||||
EXPECT_EQ(
|
||||
log[4].second,
|
||||
"Identity: ManagedIdentityCredential will be created "
|
||||
"with Azure Instance Metadata Service source"
|
||||
" and Client ID 'fedcba98-7654-3210-0123-456789abcdef'."
|
||||
"\nSuccessful creation does not guarantee further successful token retrieval.");
|
||||
|
||||
log.clear();
|
||||
|
||||
return credential;
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
@ -2632,6 +2761,8 @@ namespace Azure { namespace Identity { namespace Test {
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
Logger::SetListener(nullptr);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, ImdsResourceId)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user