This reverts commit 60dff1dac1.
This commit is contained in:
parent
59aa20e3fa
commit
4f77d817b9
1
.vscode/cspell.json
vendored
1
.vscode/cspell.json
vendored
@ -132,6 +132,7 @@
|
||||
"hlocal",
|
||||
"HLOCAL",
|
||||
"HRESULT",
|
||||
"imds",
|
||||
"Imds",
|
||||
"IMDS",
|
||||
"immutability",
|
||||
|
||||
@ -19,6 +19,29 @@ namespace Azure { namespace Identity {
|
||||
class ManagedIdentitySource;
|
||||
}
|
||||
|
||||
// This will move to Azure::Core.
|
||||
/**
|
||||
* @brief An Azure Resource Manager resource identifier.
|
||||
*/
|
||||
class ResourceIdentifier final {
|
||||
std::string m_resourceId;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a resource identifier.
|
||||
*
|
||||
* @param resourceId The id string to create the ResourceIdentifier from.
|
||||
*/
|
||||
explicit ResourceIdentifier(std::string const& resourceId) : m_resourceId(resourceId){};
|
||||
|
||||
/**
|
||||
* @brief The string representation of this resource identifier.
|
||||
*
|
||||
* @return The resource identifier string.
|
||||
*/
|
||||
std::string ToString() const { return m_resourceId; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Attempts authentication using a managed identity that has been assigned to the
|
||||
* deployment environment. This authentication type works in Azure VMs, App Service and Azure
|
||||
@ -48,6 +71,17 @@ namespace Azure { namespace Identity {
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options
|
||||
= Azure::Core::Credentials::TokenCredentialOptions());
|
||||
|
||||
/**
|
||||
* @brief Constructs an instance of ManagedIdentityCredential capable of authenticating a
|
||||
* resource with a user-assigned managed identity.
|
||||
*
|
||||
* @param resourceId The resource ID to authenticate for a user-assigned managed identity.
|
||||
* @param options Options for token retrieval.
|
||||
*/
|
||||
explicit ManagedIdentityCredential(
|
||||
ResourceIdentifier const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options = {});
|
||||
|
||||
/**
|
||||
* @brief Constructs a Managed Identity Credential.
|
||||
*
|
||||
|
||||
@ -11,6 +11,7 @@ namespace {
|
||||
std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
||||
std::string const& credentialName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
{
|
||||
using namespace Azure::Core::Credentials;
|
||||
@ -18,6 +19,7 @@ std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
||||
static std::unique_ptr<ManagedIdentitySource> (*managedIdentitySourceCreate[])(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
TokenCredentialOptions const& options)
|
||||
= {AppServiceV2019ManagedIdentitySource::Create,
|
||||
AppServiceV2017ManagedIdentitySource::Create,
|
||||
@ -29,7 +31,7 @@ std::unique_ptr<_detail::ManagedIdentitySource> CreateManagedIdentitySource(
|
||||
// For that reason, it is not possible to cover that execution branch in tests.
|
||||
for (auto create : managedIdentitySourceCreate)
|
||||
{
|
||||
if (auto source = create(credentialName, clientId, options))
|
||||
if (auto source = create(credentialName, clientId, resourceId, options))
|
||||
{
|
||||
return source;
|
||||
}
|
||||
@ -47,7 +49,16 @@ ManagedIdentityCredential::ManagedIdentityCredential(
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
: TokenCredential("ManagedIdentityCredential")
|
||||
{
|
||||
m_managedIdentitySource = CreateManagedIdentitySource(GetCredentialName(), clientId, options);
|
||||
m_managedIdentitySource = CreateManagedIdentitySource(GetCredentialName(), clientId, {}, options);
|
||||
}
|
||||
|
||||
ManagedIdentityCredential::ManagedIdentityCredential(
|
||||
ResourceIdentifier const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
: TokenCredential("ManagedIdentityCredential")
|
||||
{
|
||||
m_managedIdentitySource
|
||||
= CreateManagedIdentitySource(GetCredentialName(), {}, resourceId.ToString(), options);
|
||||
}
|
||||
|
||||
ManagedIdentityCredential::ManagedIdentityCredential(
|
||||
|
||||
@ -140,6 +140,7 @@ template <typename T>
|
||||
std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options,
|
||||
char const* endpointVarName,
|
||||
char const* secretVarName,
|
||||
@ -154,6 +155,7 @@ std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
||||
{
|
||||
return std::unique_ptr<ManagedIdentitySource>(new T(
|
||||
clientId,
|
||||
resourceId,
|
||||
options,
|
||||
ParseEndpointUrl(credName, msiEndpoint, endpointVarName, credSource),
|
||||
msiSecret));
|
||||
@ -165,6 +167,7 @@ std::unique_ptr<ManagedIdentitySource> AppServiceManagedIdentitySource::Create(
|
||||
|
||||
AppServiceManagedIdentitySource::AppServiceManagedIdentitySource(
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options,
|
||||
Azure::Core::Url endpointUrl,
|
||||
std::string const& secret,
|
||||
@ -180,10 +183,17 @@ AppServiceManagedIdentitySource::AppServiceManagedIdentitySource(
|
||||
|
||||
url.AppendQueryParameter("api-version", apiVersion);
|
||||
|
||||
// Only one of clientId or resourceId will be set to a non-empty value.
|
||||
// AppService uses mi_res_id, and not msi_res_id:
|
||||
// https://learn.microsoft.com/azure/app-service/overview-managed-identity?tabs=portal%2Chttp#rest-endpoint-reference
|
||||
if (!clientId.empty())
|
||||
{
|
||||
url.AppendQueryParameter(clientIdHeaderName, clientId);
|
||||
}
|
||||
else if (!resourceId.empty())
|
||||
{
|
||||
url.AppendQueryParameter("mi_res_id", resourceId);
|
||||
}
|
||||
}
|
||||
|
||||
m_request.SetHeader(secretHeaderName, secret);
|
||||
@ -223,24 +233,28 @@ Azure::Core::Credentials::AccessToken AppServiceManagedIdentitySource::GetToken(
|
||||
std::unique_ptr<ManagedIdentitySource> AppServiceV2017ManagedIdentitySource::Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options)
|
||||
{
|
||||
return AppServiceManagedIdentitySource::Create<AppServiceV2017ManagedIdentitySource>(
|
||||
credName, clientId, options, "MSI_ENDPOINT", "MSI_SECRET", "2017");
|
||||
credName, clientId, resourceId, options, "MSI_ENDPOINT", "MSI_SECRET", "2017");
|
||||
}
|
||||
|
||||
std::unique_ptr<ManagedIdentitySource> AppServiceV2019ManagedIdentitySource::Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options)
|
||||
{
|
||||
return AppServiceManagedIdentitySource::Create<AppServiceV2019ManagedIdentitySource>(
|
||||
credName, clientId, options, "IDENTITY_ENDPOINT", "IDENTITY_HEADER", "2019");
|
||||
credName, clientId, resourceId, options, "IDENTITY_ENDPOINT", "IDENTITY_HEADER", "2019");
|
||||
}
|
||||
|
||||
// Cloud Shell doesn't support user-assigned managed identities
|
||||
std::unique_ptr<ManagedIdentitySource> CloudShellManagedIdentitySource::Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const&,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
{
|
||||
constexpr auto EndpointVarName = "MSI_ENDPOINT";
|
||||
@ -315,6 +329,7 @@ Azure::Core::Credentials::AccessToken CloudShellManagedIdentitySource::GetToken(
|
||||
std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
{
|
||||
using Azure::Core::Credentials::AuthenticationException;
|
||||
@ -330,11 +345,11 @@ std::unique_ptr<ManagedIdentitySource> AzureArcManagedIdentitySource::Create(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!clientId.empty())
|
||||
if (!clientId.empty() || !resourceId.empty())
|
||||
{
|
||||
throw AuthenticationException(
|
||||
"User assigned identity is not supported by the Azure Arc Managed Identity Endpoint. "
|
||||
"To authenticate with the system assigned identity, omit the client ID "
|
||||
"To authenticate with the system assigned identity, omit the client or resource ID "
|
||||
"when constructing the ManagedIdentityCredential.");
|
||||
}
|
||||
|
||||
@ -348,7 +363,6 @@ AzureArcManagedIdentitySource::AzureArcManagedIdentitySource(
|
||||
: ManagedIdentitySource(std::string(), endpointUrl.GetHost(), options),
|
||||
m_url(std::move(endpointUrl))
|
||||
{
|
||||
|
||||
m_url.AppendQueryParameter("api-version", "2019-11-01");
|
||||
}
|
||||
|
||||
@ -442,6 +456,7 @@ Azure::Core::Credentials::AccessToken AzureArcManagedIdentitySource::GetToken(
|
||||
std::unique_ptr<ManagedIdentitySource> ImdsManagedIdentitySource::Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
{
|
||||
IdentityLog::Write(
|
||||
@ -449,16 +464,28 @@ std::unique_ptr<ManagedIdentitySource> ImdsManagedIdentitySource::Create(
|
||||
credName + " will be created" + WithSourceMessage("Azure Instance Metadata Service")
|
||||
+ ".\nSuccessful creation does not guarantee further successful token retrieval.");
|
||||
|
||||
return std::unique_ptr<ManagedIdentitySource>(new ImdsManagedIdentitySource(clientId, options));
|
||||
std::string imdsHost = "http://169.254.169.254";
|
||||
std::string customImdsHost = Environment::GetVariable("AZURE_IMDS_CUSTOM_AUTHORITY_HOST");
|
||||
if (!customImdsHost.empty())
|
||||
{
|
||||
IdentityLog::Write(
|
||||
IdentityLog::Level::Informational, "Custom IMDS host is set to: " + customImdsHost);
|
||||
imdsHost = customImdsHost;
|
||||
}
|
||||
Azure::Core::Url imdsUrl(imdsHost);
|
||||
imdsUrl.AppendPath("/metadata/identity/oauth2/token");
|
||||
|
||||
return std::unique_ptr<ManagedIdentitySource>(
|
||||
new ImdsManagedIdentitySource(clientId, resourceId, imdsUrl, options));
|
||||
}
|
||||
|
||||
ImdsManagedIdentitySource::ImdsManagedIdentitySource(
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Azure::Core::Url const& imdsUrl,
|
||||
Azure::Core::Credentials::TokenCredentialOptions const& options)
|
||||
: ManagedIdentitySource(clientId, std::string(), options),
|
||||
m_request(
|
||||
Azure::Core::Http::HttpMethod::Get,
|
||||
Azure::Core::Url("http://169.254.169.254/metadata/identity/oauth2/token"))
|
||||
m_request(Azure::Core::Http::HttpMethod::Get, imdsUrl)
|
||||
{
|
||||
{
|
||||
using Azure::Core::Url;
|
||||
@ -466,10 +493,17 @@ ImdsManagedIdentitySource::ImdsManagedIdentitySource(
|
||||
|
||||
url.AppendQueryParameter("api-version", "2018-02-01");
|
||||
|
||||
// Only one of clientId or resourceId will be set to a non-empty value.
|
||||
// IMDS uses msi_res_id, and not mi_res_id:
|
||||
// https://learn.microsoft.com/entra/identity/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http
|
||||
if (!clientId.empty())
|
||||
{
|
||||
url.AppendQueryParameter("client_id", clientId);
|
||||
}
|
||||
else if (!resourceId.empty())
|
||||
{
|
||||
url.AppendQueryParameter("msi_res_id", resourceId);
|
||||
}
|
||||
}
|
||||
|
||||
m_request.SetHeader("Metadata", "true");
|
||||
|
||||
@ -54,6 +54,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
protected:
|
||||
explicit AppServiceManagedIdentitySource(
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options,
|
||||
Core::Url endpointUrl,
|
||||
std::string const& secret,
|
||||
@ -65,6 +66,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options,
|
||||
char const* endpointVarName,
|
||||
char const* secretVarName,
|
||||
@ -82,11 +84,13 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
private:
|
||||
explicit AppServiceV2017ManagedIdentitySource(
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options,
|
||||
Core::Url endpointUrl,
|
||||
std::string const& secret)
|
||||
: AppServiceManagedIdentitySource(
|
||||
clientId,
|
||||
resourceId,
|
||||
options,
|
||||
endpointUrl,
|
||||
secret,
|
||||
@ -100,6 +104,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options);
|
||||
};
|
||||
|
||||
@ -109,11 +114,13 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
private:
|
||||
explicit AppServiceV2019ManagedIdentitySource(
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options,
|
||||
Core::Url endpointUrl,
|
||||
std::string const& secret)
|
||||
: AppServiceManagedIdentitySource(
|
||||
clientId,
|
||||
resourceId,
|
||||
options,
|
||||
endpointUrl,
|
||||
secret,
|
||||
@ -127,6 +134,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options);
|
||||
};
|
||||
|
||||
@ -144,6 +152,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options);
|
||||
|
||||
Core::Credentials::AccessToken GetToken(
|
||||
@ -163,6 +172,7 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options);
|
||||
|
||||
Core::Credentials::AccessToken GetToken(
|
||||
@ -176,12 +186,15 @@ namespace Azure { namespace Identity { namespace _detail {
|
||||
|
||||
explicit ImdsManagedIdentitySource(
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Url const& imdsUrl,
|
||||
Core::Credentials::TokenCredentialOptions const& options);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<ManagedIdentitySource> Create(
|
||||
std::string const& credName,
|
||||
std::string const& clientId,
|
||||
std::string const& resourceId,
|
||||
Core::Credentials::TokenCredentialOptions const& options);
|
||||
|
||||
Core::Credentials::AccessToken GetToken(
|
||||
|
||||
@ -28,6 +28,7 @@ add_executable (
|
||||
environment_credential_test.cpp
|
||||
macro_guard_test.cpp
|
||||
managed_identity_credential_test.cpp
|
||||
resource_identifier_test.cpp
|
||||
simplified_header_test.cpp
|
||||
tenant_id_resolver_test.cpp
|
||||
token_cache_test.cpp
|
||||
|
||||
@ -30,6 +30,7 @@ using Azure::Core::Credentials::TokenCredentialOptions;
|
||||
using Azure::Core::Http::HttpMethod;
|
||||
using Azure::Core::Http::HttpStatusCode;
|
||||
using Azure::Identity::ManagedIdentityCredential;
|
||||
using Azure::Identity::ResourceIdentifier;
|
||||
using Azure::Identity::Test::_detail::CredentialTestHelper;
|
||||
|
||||
TEST(ManagedIdentityCredential, GetCredentialName)
|
||||
@ -240,6 +241,96 @@ TEST(ManagedIdentityCredential, AppServiceV2019ClientId)
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2019ResourceId)
|
||||
{
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", "https://microsoft.com/"},
|
||||
{"MSI_SECRET", "CLIENTSECRET1"},
|
||||
{"IDENTITY_ENDPOINT", "https://visualstudio.com/"},
|
||||
{"IMDS_ENDPOINT", "https://xbox.com/"},
|
||||
{"IDENTITY_HEADER", "CLIENTSECRET2"},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", "0123456789abcdef0123456789abcdef01234567"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
ResourceIdentifier("abcdef01-2345-6789-9876-543210fedcba"), options);
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}",
|
||||
"{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}",
|
||||
"{\"expires_in\":9999, \"access_token\":\"ACCESSTOKEN3\"}"});
|
||||
|
||||
EXPECT_EQ(actual.Requests.size(), 3U);
|
||||
EXPECT_EQ(actual.Responses.size(), 3U);
|
||||
|
||||
auto const& request0 = actual.Requests.at(0);
|
||||
auto const& request1 = actual.Requests.at(1);
|
||||
auto const& request2 = actual.Requests.at(2);
|
||||
|
||||
auto const& response0 = actual.Responses.at(0);
|
||||
auto const& response1 = actual.Responses.at(1);
|
||||
auto const& response2 = actual.Responses.at(2);
|
||||
|
||||
EXPECT_EQ(request0.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request1.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request2.HttpMethod, HttpMethod::Get);
|
||||
|
||||
EXPECT_EQ(
|
||||
request0.AbsoluteUrl,
|
||||
"https://visualstudio.com"
|
||||
"?api-version=2019-08-01"
|
||||
"&mi_res_id=abcdef01-2345-6789-9876-543210fedcba"
|
||||
"&resource=https%3A%2F%2Fazure.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request1.AbsoluteUrl,
|
||||
"https://visualstudio.com"
|
||||
"?api-version=2019-08-01"
|
||||
"&mi_res_id=abcdef01-2345-6789-9876-543210fedcba"
|
||||
"&resource=https%3A%2F%2Foutlook.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request2.AbsoluteUrl,
|
||||
"https://visualstudio.com"
|
||||
"?api-version=2019-08-01"
|
||||
"&mi_res_id=abcdef01-2345-6789-9876-543210fedcba");
|
||||
|
||||
EXPECT_TRUE(request0.Body.empty());
|
||||
EXPECT_TRUE(request1.Body.empty());
|
||||
EXPECT_TRUE(request2.Body.empty());
|
||||
|
||||
{
|
||||
EXPECT_NE(request0.Headers.find("X-IDENTITY-HEADER"), request0.Headers.end());
|
||||
EXPECT_EQ(request0.Headers.at("X-IDENTITY-HEADER"), "CLIENTSECRET2");
|
||||
|
||||
EXPECT_NE(request1.Headers.find("X-IDENTITY-HEADER"), request1.Headers.end());
|
||||
EXPECT_EQ(request1.Headers.at("X-IDENTITY-HEADER"), "CLIENTSECRET2");
|
||||
|
||||
EXPECT_NE(request2.Headers.find("X-IDENTITY-HEADER"), request2.Headers.end());
|
||||
EXPECT_EQ(request2.Headers.at("X-IDENTITY-HEADER"), "CLIENTSECRET2");
|
||||
}
|
||||
|
||||
EXPECT_EQ(response0.AccessToken.Token, "ACCESSTOKEN1");
|
||||
EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN2");
|
||||
EXPECT_EQ(response2.AccessToken.Token, "ACCESSTOKEN3");
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
EXPECT_GE(response0.AccessToken.ExpiresOn, response0.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response0.AccessToken.ExpiresOn, response0.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2019InvalidUrl)
|
||||
{
|
||||
using Azure::Core::Diagnostics::Logger;
|
||||
@ -522,6 +613,96 @@ TEST(ManagedIdentityCredential, AppServiceV2017ClientId)
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2017ResourceId)
|
||||
{
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", "https://microsoft.com/"},
|
||||
{"MSI_SECRET", "CLIENTSECRET1"},
|
||||
{"IDENTITY_ENDPOINT", ""},
|
||||
{"IMDS_ENDPOINT", "https://xbox.com/"},
|
||||
{"IDENTITY_HEADER", "CLIENTSECRET2"},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", "0123456789abcdef0123456789abcdef01234567"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
ResourceIdentifier("abcdef01-2345-6789-9876-543210fedcba"), options);
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}",
|
||||
"{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}",
|
||||
"{\"expires_in\":9999, \"access_token\":\"ACCESSTOKEN3\"}"});
|
||||
|
||||
EXPECT_EQ(actual.Requests.size(), 3U);
|
||||
EXPECT_EQ(actual.Responses.size(), 3U);
|
||||
|
||||
auto const& request0 = actual.Requests.at(0);
|
||||
auto const& request1 = actual.Requests.at(1);
|
||||
auto const& request2 = actual.Requests.at(2);
|
||||
|
||||
auto const& response0 = actual.Responses.at(0);
|
||||
auto const& response1 = actual.Responses.at(1);
|
||||
auto const& response2 = actual.Responses.at(2);
|
||||
|
||||
EXPECT_EQ(request0.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request1.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request2.HttpMethod, HttpMethod::Get);
|
||||
|
||||
EXPECT_EQ(
|
||||
request0.AbsoluteUrl,
|
||||
"https://microsoft.com"
|
||||
"?api-version=2017-09-01"
|
||||
"&mi_res_id=abcdef01-2345-6789-9876-543210fedcba"
|
||||
"&resource=https%3A%2F%2Fazure.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request1.AbsoluteUrl,
|
||||
"https://microsoft.com"
|
||||
"?api-version=2017-09-01"
|
||||
"&mi_res_id=abcdef01-2345-6789-9876-543210fedcba"
|
||||
"&resource=https%3A%2F%2Foutlook.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request2.AbsoluteUrl,
|
||||
"https://microsoft.com"
|
||||
"?api-version=2017-09-01"
|
||||
"&mi_res_id=abcdef01-2345-6789-9876-543210fedcba");
|
||||
|
||||
EXPECT_TRUE(request0.Body.empty());
|
||||
EXPECT_TRUE(request1.Body.empty());
|
||||
EXPECT_TRUE(request2.Body.empty());
|
||||
|
||||
{
|
||||
EXPECT_NE(request0.Headers.find("secret"), request0.Headers.end());
|
||||
EXPECT_EQ(request0.Headers.at("secret"), "CLIENTSECRET1");
|
||||
|
||||
EXPECT_NE(request1.Headers.find("secret"), request1.Headers.end());
|
||||
EXPECT_EQ(request1.Headers.at("secret"), "CLIENTSECRET1");
|
||||
|
||||
EXPECT_NE(request2.Headers.find("secret"), request2.Headers.end());
|
||||
EXPECT_EQ(request2.Headers.at("secret"), "CLIENTSECRET1");
|
||||
}
|
||||
|
||||
EXPECT_EQ(response0.AccessToken.Token, "ACCESSTOKEN1");
|
||||
EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN2");
|
||||
EXPECT_EQ(response2.AccessToken.Token, "ACCESSTOKEN3");
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
EXPECT_GE(response0.AccessToken.ExpiresOn, response0.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response0.AccessToken.ExpiresOn, response0.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AppServiceV2017InvalidUrl)
|
||||
{
|
||||
using Azure::Core::Credentials::AccessToken;
|
||||
@ -770,6 +951,84 @@ TEST(ManagedIdentityCredential, CloudShellClientId)
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, CloudShellResourceId)
|
||||
{
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", "https://microsoft.com/"},
|
||||
{"MSI_SECRET", ""},
|
||||
{"IDENTITY_ENDPOINT", "https://visualstudio.com/"},
|
||||
{"IMDS_ENDPOINT", "https://xbox.com/"},
|
||||
{"IDENTITY_HEADER", ""},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", "0123456789abcdef0123456789abcdef01234567"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
ResourceIdentifier("abcdef01-2345-6789-9876-543210fedcba"), options);
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}",
|
||||
"{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}",
|
||||
"{\"expires_in\":9999, \"access_token\":\"ACCESSTOKEN3\"}"});
|
||||
|
||||
EXPECT_EQ(actual.Requests.size(), 3U);
|
||||
EXPECT_EQ(actual.Responses.size(), 3U);
|
||||
|
||||
auto const& request0 = actual.Requests.at(0);
|
||||
auto const& request1 = actual.Requests.at(1);
|
||||
auto const& request2 = actual.Requests.at(2);
|
||||
|
||||
auto const& response0 = actual.Responses.at(0);
|
||||
auto const& response1 = actual.Responses.at(1);
|
||||
auto const& response2 = actual.Responses.at(2);
|
||||
|
||||
EXPECT_EQ(request0.HttpMethod, HttpMethod::Post);
|
||||
EXPECT_EQ(request1.HttpMethod, HttpMethod::Post);
|
||||
EXPECT_EQ(request2.HttpMethod, HttpMethod::Post);
|
||||
|
||||
EXPECT_EQ(request0.AbsoluteUrl, "https://microsoft.com");
|
||||
EXPECT_EQ(request1.AbsoluteUrl, "https://microsoft.com");
|
||||
EXPECT_EQ(request2.AbsoluteUrl, "https://microsoft.com");
|
||||
|
||||
EXPECT_EQ(request0.Body,
|
||||
"resource=https%3A%2F%2Fazure.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(request1.Body,
|
||||
"resource=https%3A%2F%2Foutlook.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(request2.Body, "");
|
||||
|
||||
{
|
||||
EXPECT_NE(request0.Headers.find("Metadata"), request0.Headers.end());
|
||||
EXPECT_EQ(request0.Headers.at("Metadata"), "true");
|
||||
|
||||
EXPECT_NE(request1.Headers.find("Metadata"), request1.Headers.end());
|
||||
EXPECT_EQ(request1.Headers.at("Metadata"), "true");
|
||||
|
||||
EXPECT_NE(request2.Headers.find("Metadata"), request2.Headers.end());
|
||||
EXPECT_EQ(request2.Headers.at("Metadata"), "true");
|
||||
}
|
||||
|
||||
EXPECT_EQ(response0.AccessToken.Token, "ACCESSTOKEN1");
|
||||
EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN2");
|
||||
EXPECT_EQ(response2.AccessToken.Token, "ACCESSTOKEN3");
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
EXPECT_GE(response0.AccessToken.ExpiresOn, response0.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response0.AccessToken.ExpiresOn, response0.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, CloudShellInvalidUrl)
|
||||
{
|
||||
using Azure::Core::Credentials::AccessToken;
|
||||
@ -1082,6 +1341,37 @@ TEST(ManagedIdentityCredential, AzureArcClientId)
|
||||
{"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}"}));
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AzureArcResourceId)
|
||||
{
|
||||
using Azure::Core::Credentials::AccessToken;
|
||||
using Azure::Core::Credentials::AuthenticationException;
|
||||
|
||||
static_cast<void>(CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", ""},
|
||||
{"MSI_SECRET", ""},
|
||||
{"IDENTITY_ENDPOINT", "https://visualstudio.com/"},
|
||||
{"IMDS_ENDPOINT", "https://xbox.com/"},
|
||||
{"IDENTITY_HEADER", ""},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", "0123456789abcdef0123456789abcdef01234567"},
|
||||
});
|
||||
|
||||
std::unique_ptr<ManagedIdentityCredential const> azureArcManagedIdentityCredential;
|
||||
EXPECT_THROW(
|
||||
azureArcManagedIdentityCredential = std::make_unique<ManagedIdentityCredential>(
|
||||
ResourceIdentifier("abcdef01-2345-6789-9876-543210fedcba"), options),
|
||||
AuthenticationException);
|
||||
|
||||
return azureArcManagedIdentityCredential;
|
||||
},
|
||||
{},
|
||||
{"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}"}));
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, AzureArcAuthHeaderMissing)
|
||||
{
|
||||
using Azure::Core::Credentials::AccessToken;
|
||||
@ -1755,6 +2045,96 @@ TEST(ManagedIdentityCredential, ImdsClientId)
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, ImdsResourceId)
|
||||
{
|
||||
auto const actual = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", ""},
|
||||
{"MSI_SECRET", ""},
|
||||
{"IDENTITY_ENDPOINT", ""},
|
||||
{"IMDS_ENDPOINT", ""},
|
||||
{"IDENTITY_HEADER", ""},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
ResourceIdentifier("abcdef01-2345-6789-9876-543210fedcba"), options);
|
||||
},
|
||||
{{"https://azure.com/.default"}, {"https://outlook.com/.default"}, {}},
|
||||
std::vector<std::string>{
|
||||
"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}",
|
||||
"{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}",
|
||||
"{\"expires_in\":9999, \"access_token\":\"ACCESSTOKEN3\"}"});
|
||||
|
||||
EXPECT_EQ(actual.Requests.size(), 3U);
|
||||
EXPECT_EQ(actual.Responses.size(), 3U);
|
||||
|
||||
auto const& request0 = actual.Requests.at(0);
|
||||
auto const& request1 = actual.Requests.at(1);
|
||||
auto const& request2 = actual.Requests.at(2);
|
||||
|
||||
auto const& response0 = actual.Responses.at(0);
|
||||
auto const& response1 = actual.Responses.at(1);
|
||||
auto const& response2 = actual.Responses.at(2);
|
||||
|
||||
EXPECT_EQ(request0.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request1.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request2.HttpMethod, HttpMethod::Get);
|
||||
|
||||
EXPECT_EQ(
|
||||
request0.AbsoluteUrl,
|
||||
"http://169.254.169.254/metadata/identity/oauth2/token"
|
||||
"?api-version=2018-02-01"
|
||||
"&msi_res_id=abcdef01-2345-6789-9876-543210fedcba"
|
||||
"&resource=https%3A%2F%2Fazure.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request1.AbsoluteUrl,
|
||||
"http://169.254.169.254/metadata/identity/oauth2/token"
|
||||
"?api-version=2018-02-01"
|
||||
"&msi_res_id=abcdef01-2345-6789-9876-543210fedcba"
|
||||
"&resource=https%3A%2F%2Foutlook.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request2.AbsoluteUrl,
|
||||
"http://169.254.169.254/metadata/identity/oauth2/token"
|
||||
"?api-version=2018-02-01"
|
||||
"&msi_res_id=abcdef01-2345-6789-9876-543210fedcba");
|
||||
|
||||
EXPECT_TRUE(request0.Body.empty());
|
||||
EXPECT_TRUE(request1.Body.empty());
|
||||
EXPECT_TRUE(request2.Body.empty());
|
||||
|
||||
{
|
||||
EXPECT_NE(request0.Headers.find("Metadata"), request0.Headers.end());
|
||||
EXPECT_EQ(request0.Headers.at("Metadata"), "true");
|
||||
|
||||
EXPECT_NE(request1.Headers.find("Metadata"), request1.Headers.end());
|
||||
EXPECT_EQ(request1.Headers.at("Metadata"), "true");
|
||||
|
||||
EXPECT_NE(request2.Headers.find("Metadata"), request2.Headers.end());
|
||||
EXPECT_EQ(request2.Headers.at("Metadata"), "true");
|
||||
}
|
||||
|
||||
EXPECT_EQ(response0.AccessToken.Token, "ACCESSTOKEN1");
|
||||
EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN2");
|
||||
EXPECT_EQ(response2.AccessToken.Token, "ACCESSTOKEN3");
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
EXPECT_GE(response0.AccessToken.ExpiresOn, response0.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response0.AccessToken.ExpiresOn, response0.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 4999s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 4999s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, ImdsCreation)
|
||||
{
|
||||
auto const actual1 = CredentialTestHelper::SimulateTokenRequest(
|
||||
@ -1847,3 +2227,127 @@ TEST(ManagedIdentityCredential, ImdsCreation)
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 3600s);
|
||||
}
|
||||
|
||||
TEST(ManagedIdentityCredential, ImdsCustomHost)
|
||||
{
|
||||
auto const actual1 = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", ""},
|
||||
{"MSI_SECRET", ""},
|
||||
{"IDENTITY_ENDPOINT", "https://visualstudio.com/"},
|
||||
{"IMDS_ENDPOINT", ""},
|
||||
{"IDENTITY_HEADER", ""},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||
{"AZURE_IMDS_CUSTOM_AUTHORITY_HOST", ""},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
"fedcba98-7654-3210-0123-456789abcdef", options);
|
||||
},
|
||||
{{"https://azure.com/.default"}},
|
||||
{"{\"expires_in\":3600, \"access_token\":\"ACCESSTOKEN1\"}"});
|
||||
|
||||
auto const actual2 = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", ""},
|
||||
{"MSI_SECRET", ""},
|
||||
{"IDENTITY_ENDPOINT", ""},
|
||||
{"IMDS_ENDPOINT", "https://xbox.com/"},
|
||||
{"IDENTITY_HEADER", ""},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||
{"AZURE_IMDS_CUSTOM_AUTHORITY_HOST", "https://custom.imds.endpoint/"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
"01234567-89ab-cdef-fedc-ba9876543210", options);
|
||||
},
|
||||
{{"https://outlook.com/.default"}},
|
||||
{"{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}"});
|
||||
|
||||
auto const actual3 = CredentialTestHelper::SimulateTokenRequest(
|
||||
[](auto transport) {
|
||||
TokenCredentialOptions options;
|
||||
options.Transport.Transport = transport;
|
||||
|
||||
CredentialTestHelper::EnvironmentOverride const env({
|
||||
{"MSI_ENDPOINT", ""},
|
||||
{"MSI_SECRET", ""},
|
||||
{"IDENTITY_ENDPOINT", ""},
|
||||
{"IMDS_ENDPOINT", "https://xbox.com/"},
|
||||
{"IDENTITY_HEADER", ""},
|
||||
{"IDENTITY_SERVER_THUMBPRINT", ""},
|
||||
{"AZURE_IMDS_CUSTOM_AUTHORITY_HOST", "http://localhost:59202"},
|
||||
});
|
||||
|
||||
return std::make_unique<ManagedIdentityCredential>(
|
||||
"01234567-89ab-cdef-fedc-ba9876543210", options);
|
||||
},
|
||||
{{"https://outlook.com/.default"}},
|
||||
{"{\"expires_in\":7200, \"access_token\":\"ACCESSTOKEN2\"}"});
|
||||
|
||||
EXPECT_EQ(actual1.Requests.size(), 1U);
|
||||
EXPECT_EQ(actual1.Responses.size(), 1U);
|
||||
|
||||
EXPECT_EQ(actual2.Requests.size(), 1U);
|
||||
EXPECT_EQ(actual2.Responses.size(), 1U);
|
||||
|
||||
auto const& request1 = actual1.Requests.at(0);
|
||||
auto const& response1 = actual1.Responses.at(0);
|
||||
|
||||
auto const& request2 = actual2.Requests.at(0);
|
||||
auto const& response2 = actual2.Responses.at(0);
|
||||
|
||||
EXPECT_EQ(request1.HttpMethod, HttpMethod::Get);
|
||||
EXPECT_EQ(request2.HttpMethod, HttpMethod::Get);
|
||||
|
||||
EXPECT_EQ(
|
||||
request1.AbsoluteUrl,
|
||||
"http://169.254.169.254/metadata/identity/oauth2/token"
|
||||
"?api-version=2018-02-01"
|
||||
"&client_id=fedcba98-7654-3210-0123-456789abcdef"
|
||||
"&resource=https%3A%2F%2Fazure.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_EQ(
|
||||
request2.AbsoluteUrl,
|
||||
"https://custom.imds.endpoint/metadata/identity/oauth2/token"
|
||||
"?api-version=2018-02-01"
|
||||
"&client_id=01234567-89ab-cdef-fedc-ba9876543210"
|
||||
"&resource=https%3A%2F%2Foutlook.com"); // cspell:disable-line
|
||||
|
||||
auto const& request3 = actual3.Requests.at(0);
|
||||
EXPECT_EQ(
|
||||
request3.AbsoluteUrl,
|
||||
"http://localhost:59202/metadata/identity/oauth2/token"
|
||||
"?api-version=2018-02-01"
|
||||
"&client_id=01234567-89ab-cdef-fedc-ba9876543210"
|
||||
"&resource=https%3A%2F%2Foutlook.com"); // cspell:disable-line
|
||||
|
||||
EXPECT_TRUE(request1.Body.empty());
|
||||
EXPECT_TRUE(request2.Body.empty());
|
||||
|
||||
{
|
||||
EXPECT_NE(request1.Headers.find("Metadata"), request1.Headers.end());
|
||||
EXPECT_EQ(request1.Headers.at("Metadata"), "true");
|
||||
|
||||
EXPECT_NE(request2.Headers.find("Metadata"), request2.Headers.end());
|
||||
EXPECT_EQ(request2.Headers.at("Metadata"), "true");
|
||||
}
|
||||
|
||||
EXPECT_EQ(response1.AccessToken.Token, "ACCESSTOKEN1");
|
||||
EXPECT_EQ(response2.AccessToken.Token, "ACCESSTOKEN2");
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
EXPECT_GE(response1.AccessToken.ExpiresOn, response1.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response1.AccessToken.ExpiresOn, response1.LatestExpiration + 3600s);
|
||||
|
||||
EXPECT_GE(response2.AccessToken.ExpiresOn, response2.EarliestExpiration + 3600s);
|
||||
EXPECT_LE(response2.AccessToken.ExpiresOn, response2.LatestExpiration + 3600s);
|
||||
}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "azure/identity/managed_identity_credential.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace Azure::Identity;
|
||||
|
||||
TEST(ResourceIdentifier, Basic)
|
||||
{
|
||||
std::string resourceId = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg/"
|
||||
"providers/Compute/virtualMachines/vm-name";
|
||||
ResourceIdentifier resourceIdentifier(resourceId);
|
||||
EXPECT_EQ(resourceIdentifier.ToString(), resourceId);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user