Skip to content

Commit 11a2a38

Browse files
authored
Implement Phase 3 features for DefaultAzureCredential (#6724)
* Implement Phase 3 features for DefaultAzureCredential * Forgotten change to update header * Clang-format * GCC fix * Change 'envVarName' string parameter to a boolean 'requireEnvVarValue' parameter * Rename EnvVarName to CredentialSpecifierEnvVarName and make it constexpr auto * requireEnvVarValue => requireCredentialSpecifierEnvVarValue * Clang-format * Update unit test name * Clang-format * Update CHANGELOG with new features and bug fixes --------- Co-authored-by: Anton Kolesnyk <antkmsft@users.noreply.github.com>
1 parent 573fe95 commit 11a2a38

File tree

6 files changed

+62
-11
lines changed

6 files changed

+62
-11
lines changed

sdk/core/azure-core/inc/azure/core/internal/environment.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ namespace Azure { namespace Core { namespace _internal {
1212
~Environment() = delete;
1313

1414
public:
15+
static std::string GetVariable(const std::string& name) { return GetVariable(name.c_str()); }
16+
static void SetVariable(const std::string& name, const std::string& value)
17+
{
18+
SetVariable(name.c_str(), value.c_str());
19+
}
20+
1521
static std::string GetVariable(const char* name);
1622
static void SetVariable(const char* name, const char* value);
1723
};

sdk/core/azure-core/inc/azure/core/internal/strings.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ namespace Azure { namespace Core { namespace _internal {
3838
return IsDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
3939
}
4040

41-
static constexpr bool IsAlphaNumeric(char c) noexcept
41+
static constexpr bool IsAlpha(char c) noexcept
4242
{
43-
return IsDigit(c) || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
43+
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
4444
}
4545

46+
static constexpr bool IsAlphaNumeric(char c) noexcept { return IsDigit(c) || IsAlpha(c); }
47+
4648
static constexpr bool IsSpace(char c) noexcept { return c == ' ' || (c >= '\t' && c <= '\r'); }
4749

4850
static constexpr bool IsPrintable(char c) noexcept { return c >= ' ' && c <= '~'; }

sdk/identity/azure-identity/CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
## 1.13.1 (2025-09-11)
44

5-
### Bugs Fixed
5+
### Features Added
66

7+
- Added a constructor overload for `DefaultAzureCredential` with a boolean parameter to indicate whether to throw an exception if `AZURE_TOKEN_CREDENTIALS` environment variable doesn't have a value.
8+
9+
### Bugs Fixed
710
- Fixed IMDS token requests for managed identities, which were broken by an invalid URL path in 1.12.0-beta.1. (A community contribution, courtesy of _[chewi](https://github.com/chewi)_)
811

912
### Acknowledgments

sdk/identity/azure-identity/inc/azure/identity/default_azure_credential.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ namespace Azure { namespace Identity {
6262
*/
6363
explicit DefaultAzureCredential(Core::Credentials::TokenCredentialOptions const& options);
6464

65+
/**
66+
* @brief Constructs `%DefaultAzureCredential`.
67+
*
68+
* @param requireCredentialSpecifierEnvVarValue Throw an exception if `AZURE_TOKEN_CREDENTIALS`
69+
* environment variable is not set.
70+
*
71+
* @param options Generic Token Credential Options.
72+
*
73+
*/
74+
explicit DefaultAzureCredential(
75+
bool requireCredentialSpecifierEnvVarValue,
76+
Core::Credentials::TokenCredentialOptions const& options = {});
77+
6578
/**
6679
* @brief Destructs `%DefaultAzureCredential`.
6780
*

sdk/identity/azure-identity/src/default_azure_credential.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,18 @@ using Azure::Core::_internal::StringExtensions;
2626
using Azure::Core::Diagnostics::Logger;
2727
using Azure::Identity::_detail::IdentityLog;
2828

29+
namespace {
30+
constexpr auto CredentialSpecifierEnvVarName = "AZURE_TOKEN_CREDENTIALS";
31+
} // namespace
32+
2933
DefaultAzureCredential::DefaultAzureCredential(
34+
Core::Credentials::TokenCredentialOptions const& options)
35+
: DefaultAzureCredential(false, options)
36+
{
37+
}
38+
39+
DefaultAzureCredential::DefaultAzureCredential(
40+
bool requireCredentialSpecifierEnvVarValue,
3041
Core::Credentials::TokenCredentialOptions const& options)
3142
: TokenCredential("DefaultAzureCredential")
3243
{
@@ -77,10 +88,16 @@ DefaultAzureCredential::DefaultAzureCredential(
7788
[](auto options) { return std::make_shared<AzureCliCredential>(options); }},
7889
};
7990

80-
constexpr auto envVarName = "AZURE_TOKEN_CREDENTIALS";
81-
const auto envVarValue = Environment::GetVariable(envVarName);
91+
const auto envVarValue = Environment::GetVariable(CredentialSpecifierEnvVarName);
8292
const auto trimmedEnvVarValue = StringExtensions::Trim(envVarValue);
8393

94+
if (requireCredentialSpecifierEnvVarValue && trimmedEnvVarValue.empty())
95+
{
96+
throw AuthenticationException(
97+
GetCredentialName() + ": '" + CredentialSpecifierEnvVarName
98+
+ "' environment variable is empty.");
99+
}
100+
84101
bool specificCred = false;
85102
if (!trimmedEnvVarValue.empty())
86103
{
@@ -92,8 +109,8 @@ DefaultAzureCredential::DefaultAzureCredential(
92109
specificCred = true;
93110
IdentityLog::Write(
94111
IdentityLog::Level::Verbose,
95-
GetCredentialName() + ": '" + envVarName + "' environment variable is set to '"
96-
+ envVarValue
112+
GetCredentialName() + ": '" + CredentialSpecifierEnvVarName
113+
+ "' environment variable is set to '" + envVarValue
97114
+ "', therefore credential chain will only contain single credential: "
98115
+ cred.CredentialName + '.');
99116
credentialChain.emplace_back(cred.Create(options));
@@ -143,7 +160,8 @@ DefaultAzureCredential::DefaultAzureCredential(
143160
}
144161
}
145162

146-
const auto logMsg = GetCredentialName() + ": '" + envVarName + "' environment variable is "
163+
const auto logMsg = GetCredentialName() + ": '" + CredentialSpecifierEnvVarName
164+
+ "' environment variable is "
147165
+ (envVarValue.empty() ? "not set" : ("set to '" + envVarValue + "'"))
148166
+ ((devCredCount > 0)
149167
? (", therefore " + devCredNames + " will " + (isProd ? "NOT " : "")
@@ -177,10 +195,13 @@ DefaultAzureCredential::DefaultAzureCredential(
177195
}
178196

179197
throw AuthenticationException(
180-
GetCredentialName() + ": Invalid value '" + envVarValue + "' for the '" + envVarName
198+
GetCredentialName() + ": Invalid value '" + envVarValue + "' for the '"
199+
+ CredentialSpecifierEnvVarName
181200
+ "' environment variable. Allowed values are 'dev', 'prod'" + allowedCredNames
182-
+ " (case insensitive). "
183-
"It is also valid to not have the environment variable defined.");
201+
+ " (case insensitive)."
202+
+ (requireCredentialSpecifierEnvVarValue
203+
? ""
204+
: " It is also valid to not have the environment variable defined."));
184205
}
185206
}
186207
}

sdk/identity/azure-identity/test/ut/default_azure_credential_test.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,9 @@ TEST_P(LogMessagesForSpecificCredential, )
522522

523523
Logger::SetListener(nullptr);
524524
}
525+
526+
TEST(DefaultAzureCredential, RequireCredentialSpecifierEnvVarValue)
527+
{
528+
EXPECT_THROW(
529+
static_cast<void>(std::make_unique<DefaultAzureCredential>(true)), AuthenticationException);
530+
}

0 commit comments

Comments
 (0)