Skip to content
This repository has been archived by the owner on May 2, 2023. It is now read-only.

Fix HealthCheck auth endpoint for alternate Azure Clouds #39

Merged
merged 3 commits into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions source/Calamari.Tests/AzureClientFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using Azure.ResourceManager;
using Calamari.Azure;
using NUnit.Framework;

namespace Calamari.AzureAppService.Tests
{
public class AzureClientFixture
{
[Test]
[TestCase("", "https://login.microsoftonline.com/")]
[TestCase("AzureCloud", "https://login.microsoftonline.com/")]
[TestCase("AzureGlobalCloud", "https://login.microsoftonline.com/")]
[TestCase("AzureChinaCloud", "https://login.chinacloudapi.cn/")]
[TestCase("AzureGermanCloud", "https://login.microsoftonline.de/")]
[TestCase("AzureUSGovernment", "https://login.microsoftonline.us/")]
public void AzureClientOptions_IdentityAuth_UsesCorrectEndpointsForRegions(string azureCloud, string expectedAuthorityHost)
{
// Arrange
var servicePrincipalAccount = GetAccountFor(azureCloud);

// Act
var (_, tokenCredentialOptions) = servicePrincipalAccount.GetArmClientOptions();

// Assert
Assert.AreEqual(new Uri(expectedAuthorityHost), tokenCredentialOptions.AuthorityHost);
}

[Test]
[TestCase("", "https://management.azure.com")]
[TestCase("AzureCloud", "https://management.azure.com")]
[TestCase("AzureGlobalCloud", "https://management.azure.com")]
[TestCase("AzureChinaCloud", "https://management.chinacloudapi.cn")]
[TestCase("AzureGermanCloud", "https://management.microsoftazure.de")]
[TestCase("AzureUSGovernment", "https://management.usgovcloudapi.net")]
public void AzureClientOptions_APiCall_UsesCorrectEndpointsForRegions(string azureCloud, string expectedManagementEndpoint)
mjhilton marked this conversation as resolved.
Show resolved Hide resolved
{
// Arrange
var servicePrincipalAccount = GetAccountFor(azureCloud);

// Act
var (armClientOptions, _) = servicePrincipalAccount.GetArmClientOptions();

// Assert
Assert.AreEqual(new Uri(expectedManagementEndpoint), armClientOptions.Environment.Value.Endpoint);
}

private ServicePrincipalAccount GetAccountFor(string azureCloud)
{
return new ServicePrincipalAccount("123-456-789",
"clientId",
"tenantId",
"p@ssw0rd",
azureCloud,
null,
null);
}
}
}
30 changes: 25 additions & 5 deletions source/Calamari/Azure/AzureClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,35 @@ public static IAzure CreateAzureClient(this ServicePrincipalAccount servicePrinc
/// <returns></returns>
public static ArmClient CreateArmClient(this ServicePrincipalAccount servicePrincipal)
{
var environment = new AzureKnownEnvironment(servicePrincipal.AzureEnvironment).AsAzureArmEnvironment();
var (armClientOptions, tokenCredentialOptions) = GetArmClientOptions(servicePrincipal);
var credential = new ClientSecretCredential(servicePrincipal.TenantId, servicePrincipal.ClientId, servicePrincipal.Password, tokenCredentialOptions);
return new ArmClient(credential, defaultSubscriptionId: servicePrincipal.SubscriptionNumber, armClientOptions);
}

public static (ArmClientOptions, TokenCredentialOptions) GetArmClientOptions(this ServicePrincipalAccount servicePrincipalAccount)
{
var azureKnownEnvironment = new AzureKnownEnvironment(servicePrincipalAccount.AzureEnvironment);

// Configure a specific transport that will pick up the proxy settings set by Calamari
var httpClientTransport = new HttpClientTransport(new HttpClientHandler { Proxy = WebRequest.DefaultWebProxy });

var tokenCredentialOptions = new TokenCredentialOptions { Transport = httpClientTransport };
var credential = new ClientSecretCredential(servicePrincipal.TenantId, servicePrincipal.ClientId, servicePrincipal.Password, tokenCredentialOptions);
// Specifically tell the new Azure SDK which authentication endpoint to use
var authorityHost = azureKnownEnvironment.GetAzureAuthorityHost();
var tokenCredentialOptions = new TokenCredentialOptions
{
Transport = httpClientTransport,
AuthorityHost = authorityHost
};

var armClientOptions = new ArmClientOptions() { Transport = httpClientTransport, Environment = environment };
return new ArmClient(credential, defaultSubscriptionId: servicePrincipal.SubscriptionNumber, armClientOptions);
// The new Azure SDK uses a different representation of Environments
var armEnvironment = azureKnownEnvironment.AsAzureArmEnvironment();
var armClientOptions = new ArmClientOptions()
{
Transport = httpClientTransport,
Environment = armEnvironment
};

return (armClientOptions, tokenCredentialOptions);
}
}
}
12 changes: 12 additions & 0 deletions source/Calamari/Azure/AzureKnownEnvironment.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Azure.Identity;
using Azure.ResourceManager;
using Microsoft.Azure.Management.ResourceManager.Fluent;

Expand Down Expand Up @@ -43,5 +44,16 @@ public AzureEnvironment AsAzureSDKEnvironment()
"AzureUSGovernment" => ArmEnvironment.AzureGovernment,
_ => throw new InvalidOperationException($"ARM Environment {name} is not a known Azure Environment name.")
};

public Uri GetAzureAuthorityHost() => ToAzureAuthorityHost(Value);

private static Uri ToAzureAuthorityHost(string name) => name switch
{
"AzureGlobalCloud" => AzureAuthorityHosts.AzurePublicCloud,
"AzureChinaCloud" => AzureAuthorityHosts.AzureChina,
"AzureGermanCloud" => AzureAuthorityHosts.AzureGermany,
"AzureUSGovernment" => AzureAuthorityHosts.AzureGovernment,
_ => throw new InvalidOperationException($"ARM Environment {name} is not a known Azure Environment name.")
};
}
}