diff --git a/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs b/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs index 589857224..60adf24e6 100644 --- a/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs +++ b/src/Promitor.Agents.ResourceDiscovery/Graph/AzureResourceGraph.cs @@ -243,9 +243,12 @@ private async Task OpenConnectionAsync() private async Task CreateClientAsync() { var azureEnvironment = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.Cloud.GetAzureEnvironment(); + var azureAuthorityHost = _resourceDeclarationMonitor.CurrentValue.AzureLandscape.Cloud.GetAzureAuthorityHost(); - var credentials = await AzureAuthenticationFactory.GetTokenCredentialsAsync(azureEnvironment.ManagementEndpoint, TenantId, _azureAuthenticationInfo); - var resourceGraphClient = new ResourceGraphClient(credentials); + var credentials = await AzureAuthenticationFactory.GetTokenCredentialsAsync(azureEnvironment.ManagementEndpoint, TenantId, _azureAuthenticationInfo, azureAuthorityHost); + var resourceManagerBaseUri = new Uri(azureEnvironment.ResourceManagerEndpoint); + + var resourceGraphClient = new ResourceGraphClient(resourceManagerBaseUri, credentials); var version = Promitor.Core.Version.Get(); var promitorUserAgent = UserAgent.Generate("Resource-Discovery", version); diff --git a/src/Promitor.Core/Extensions/AzureCloudExtensions.cs b/src/Promitor.Core/Extensions/AzureCloudExtensions.cs index 6a359c417..32f190aea 100644 --- a/src/Promitor.Core/Extensions/AzureCloudExtensions.cs +++ b/src/Promitor.Core/Extensions/AzureCloudExtensions.cs @@ -1,4 +1,5 @@ using System; +using Azure.Identity; using Microsoft.Azure.Management.ResourceManager.Fluent; using Promitor.Core.Serialization.Enum; @@ -27,5 +28,22 @@ public static AzureEnvironment GetAzureEnvironment(this AzureCloud azureCloud) throw new ArgumentOutOfRangeException(nameof(azureCloud), "No Azure environment is known for"); } } + + public static Uri GetAzureAuthorityHost(this AzureCloud azureCloud) + { + switch (azureCloud) + { + case AzureCloud.Global: + return AzureAuthorityHosts.AzurePublicCloud; + case AzureCloud.China: + return AzureAuthorityHosts.AzureChina; + case AzureCloud.Germany: + return AzureAuthorityHosts.AzureGermany; + case AzureCloud.UsGov: + return AzureAuthorityHosts.AzureGovernment; + default: + throw new ArgumentOutOfRangeException(nameof(azureCloud), "No Azure environment is known for"); + } + } } } \ No newline at end of file diff --git a/src/Promitor.Core/Promitor.Core.csproj b/src/Promitor.Core/Promitor.Core.csproj index 2a40c3831..dd9ab1568 100644 --- a/src/Promitor.Core/Promitor.Core.csproj +++ b/src/Promitor.Core/Promitor.Core.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Promitor.Integrations.Azure/Authentication/AzureAuthenticationFactory.cs b/src/Promitor.Integrations.Azure/Authentication/AzureAuthenticationFactory.cs index 34274e97e..d7a814611 100644 --- a/src/Promitor.Integrations.Azure/Authentication/AzureAuthenticationFactory.cs +++ b/src/Promitor.Integrations.Azure/Authentication/AzureAuthenticationFactory.cs @@ -69,7 +69,7 @@ public static AzureAuthenticationInfo GetConfiguredAzureAuthentication(IConfigur /// /// Gets a valid token using a Service Principal or a Managed Identity /// - public static async Task GetTokenCredentialsAsync(string resource, string tenantId, AzureAuthenticationInfo authenticationInfo) + public static async Task GetTokenCredentialsAsync(string resource, string tenantId, AzureAuthenticationInfo authenticationInfo, System.Uri azureAuthorityHost) { Guard.NotNullOrWhitespace(resource, nameof(resource)); Guard.NotNullOrWhitespace(tenantId, nameof(tenantId)); @@ -77,16 +77,18 @@ public static async Task GetTokenCredentialsAsync(string resou TokenCredential tokenCredential; + var tokenCredentialOptions = new TokenCredentialOptions { AuthorityHost = azureAuthorityHost }; + switch (authenticationInfo.Mode) { case AuthenticationMode.ServicePrincipal: - tokenCredential = new ClientSecretCredential(tenantId, authenticationInfo.IdentityId, authenticationInfo.Secret); + tokenCredential = new ClientSecretCredential(tenantId, authenticationInfo.IdentityId, authenticationInfo.Secret, tokenCredentialOptions); break; case AuthenticationMode.UserAssignedManagedIdentity: - tokenCredential = new ManagedIdentityCredential(authenticationInfo.IdentityId); + tokenCredential = new ManagedIdentityCredential(authenticationInfo.IdentityId, tokenCredentialOptions); break; case AuthenticationMode.SystemAssignedManagedIdentity: - tokenCredential = new ManagedIdentityCredential(); + tokenCredential = new ManagedIdentityCredential(options:tokenCredentialOptions); break; default: tokenCredential = new DefaultAzureCredential(); diff --git a/src/Promitor.Tests.Unit/Azure/AzureCloudUnitTests.cs b/src/Promitor.Tests.Unit/Azure/AzureCloudUnitTests.cs index 479b074a7..abcc83beb 100644 --- a/src/Promitor.Tests.Unit/Azure/AzureCloudUnitTests.cs +++ b/src/Promitor.Tests.Unit/Azure/AzureCloudUnitTests.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using Azure.Identity; using Microsoft.Azure.Management.ResourceManager.Fluent; using Promitor.Core.Extensions; using Promitor.Core.Serialization.Enum; @@ -75,5 +76,71 @@ public void GetAzureEnvironment_ForUnspecifiedAzureCloud_ThrowsException() // Act & Assert Assert.Throws(()=> azureCloud.GetAzureEnvironment()); } + + [Fact] + public void GetAzureAuthorityHost_ForAzureGlobalCloud_ProvidesCorrectAuthorityHost() + { + // Arrange + var azureCloud = AzureCloud.Global; + var expectedAuthorityHost = AzureAuthorityHosts.AzurePublicCloud; + + // Act + var actualAuthorityHost = azureCloud.GetAzureAuthorityHost(); + + // Assert + Assert.True(expectedAuthorityHost.Equals(actualAuthorityHost)); + } + + [Fact] + public void GetAzureAuthorityHost_ForAzureChinaCloud_ProvidesCorrectAuthorityHost() + { + // Arrange + var azureCloud = AzureCloud.China; + var expectedAuthorityHost = AzureAuthorityHosts.AzureChina; + + // Act + var actualAuthorityHost = azureCloud.GetAzureAuthorityHost(); + + // Assert + Assert.True(expectedAuthorityHost.Equals(actualAuthorityHost)); + } + + [Fact] + public void GetAzureAuthorityHost_ForAzureGermanCloud_ProvidesCorrectAuthorityHost() + { + // Arrange + var azureCloud = AzureCloud.Germany; + var expectedAuthorityHost = AzureAuthorityHosts.AzureGermany; + + // Act + var actualAuthorityHost = azureCloud.GetAzureAuthorityHost(); + + // Assert + Assert.True(expectedAuthorityHost.Equals(actualAuthorityHost)); + } + + [Fact] + public void GetAzureAuthorityHost_ForAzureUSGovernmentCloud_ProvidesCorrectAuthorityHost() + { + // Arrange + var azureCloud = AzureCloud.UsGov; + var expectedAuthorityHost = AzureAuthorityHosts.AzureGovernment; + + // Act + var actualAuthorityHost = azureCloud.GetAzureAuthorityHost(); + + // Assert + Assert.True(expectedAuthorityHost.Equals(actualAuthorityHost)); + } + + [Fact] + public void GetAzureAuthorityHost_ForUnspecifiedAzureCloud_ThrowsException() + { + // Arrange + var azureCloud = AzureCloud.Unspecified; + + // Act & Assert + Assert.Throws(() => azureCloud.GetAzureAuthorityHost()); + } } }