tools/code/common/Azure.cs (177 lines of code) (raw):

using Azure.Core; using Azure.Core.Pipeline; using Azure.Identity; using Azure.ResourceManager; using Flurl; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.JsonWebTokens; using System; using System.IO; using System.Reflection; namespace common; public sealed record AzureEnvironment(Uri AuthorityHost, string DefaultScope, Uri ManagementEndpoint) { public static AzureEnvironment Public { get; } = new(AzureAuthorityHosts.AzurePublicCloud, ArmEnvironment.AzurePublicCloud.DefaultScope, ArmEnvironment.AzurePublicCloud.Endpoint); public static AzureEnvironment USGovernment { get; } = new(AzureAuthorityHosts.AzureGovernment, ArmEnvironment.AzureGovernment.DefaultScope, ArmEnvironment.AzureGovernment.Endpoint); public static AzureEnvironment Germany { get; } = new(AzureAuthorityHosts.AzureGermany, ArmEnvironment.AzureGermany.DefaultScope, ArmEnvironment.AzureGermany.Endpoint); public static AzureEnvironment China { get; } = new(AzureAuthorityHosts.AzureChina, ArmEnvironment.AzureChina.DefaultScope, ArmEnvironment.AzureChina.Endpoint); } public sealed record SubscriptionId : NonEmptyString { public SubscriptionId(string value) : base(value) { } } public sealed record ResourceGroupName : NonEmptyString { public ResourceGroupName(string value) : base(value) { } } public static class AzureModule { private static void ConfigureAzureEnvironment(IHostApplicationBuilder builder) { builder.Services.TryAddSingleton(GetAzureEnvironment); } private static AzureEnvironment GetAzureEnvironment(IServiceProvider provider) { var configuration = provider.GetRequiredService<IConfiguration>(); return configuration.TryGetValue("AZURE_CLOUD_ENVIRONMENT") .Map(value => value switch { "AzureGlobalCloud" or nameof(ArmEnvironment.AzurePublicCloud) => AzureEnvironment.Public, "AzureChinaCloud" or nameof(ArmEnvironment.AzureChina) => AzureEnvironment.China, "AzureUSGovernment" or nameof(ArmEnvironment.AzureGovernment) => AzureEnvironment.USGovernment, "AzureGermanCloud" or nameof(ArmEnvironment.AzureGermany) => AzureEnvironment.Germany, _ => throw new InvalidOperationException($"AZURE_CLOUD_ENVIRONMENT is invalid. Valid values are {nameof(ArmEnvironment.AzurePublicCloud)}, {nameof(ArmEnvironment.AzureChina)}, {nameof(ArmEnvironment.AzureGovernment)}, {nameof(ArmEnvironment.AzureGermany)}") }) .IfNone(() => AzureEnvironment.Public); } private static void ConfigureTokenCredential(IHostApplicationBuilder builder) { ConfigureAzureEnvironment(builder); builder.Services.TryAddSingleton(GetTokenCredential); } private static TokenCredential GetTokenCredential(IServiceProvider provider) { var environment = provider.GetRequiredService<AzureEnvironment>(); var configuration = provider.GetRequiredService<IConfiguration>(); return configuration.TryGetValue("AZURE_BEARER_TOKEN") .Map(GetCredentialFromToken) .IfNone(() => GetDefaultAzureCredential(environment.AuthorityHost)); static TokenCredential GetCredentialFromToken(string token) { var jsonWebToken = new JsonWebToken(token); var expirationDate = new DateTimeOffset(jsonWebToken.ValidTo); var accessToken = new AccessToken(token, expirationDate); return DelegatedTokenCredential.Create((context, cancellationToken) => accessToken); } static DefaultAzureCredential GetDefaultAzureCredential(Uri azureAuthorityHost) => new(new DefaultAzureCredentialOptions { AuthorityHost = azureAuthorityHost }); } public static void ConfigureHttpPipeline(IHostApplicationBuilder builder) { ConfigureTokenCredential(builder); ConfigureAzureEnvironment(builder); builder.Services.TryAddSingleton(GetHttpPipeline); } private static HttpPipeline GetHttpPipeline(IServiceProvider provider) { var tokenCredential = provider.GetRequiredService<TokenCredential>(); var azureEnvironment = provider.GetRequiredService<AzureEnvironment>(); var clientOptions = ClientOptions.Default; clientOptions.RetryPolicy = new CommonRetryPolicy(); var bearerAuthenticationPolicy = new BearerTokenAuthenticationPolicy(tokenCredential, azureEnvironment.DefaultScope); var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(HttpPipeline)); var loggingPolicy = new ILoggerHttpPipelinePolicy(logger); var version = Assembly.GetEntryAssembly()?.GetName().Version ?? new Version("-1"); var telemetryPolicy = new TelemetryPolicy(version); return HttpPipelineBuilder.Build(clientOptions, bearerAuthenticationPolicy, loggingPolicy, telemetryPolicy); } private static void ConfigureManagementServiceName(IHostApplicationBuilder builder) { builder.Services.TryAddSingleton(GetManagementServiceName); } private static ManagementServiceName GetManagementServiceName(IServiceProvider provider) { var configuration = provider.GetRequiredService<IConfiguration>(); var name = configuration.TryGetValue("API_MANAGEMENT_SERVICE_NAME") .IfNone(() => configuration.GetValue("apimServiceName")); return ManagementServiceName.From(name); } public static void ConfigureManagementServiceUri(IHostApplicationBuilder builder) { ConfigureManagementServiceProviderUri(builder); ConfigureManagementServiceName(builder); builder.Services.TryAddSingleton(GetManagementServiceUri); } private static ManagementServiceUri GetManagementServiceUri(IServiceProvider provider) { var serviceProviderUri = provider.GetRequiredService<ManagementServiceProviderUri>(); var serviceName = provider.GetRequiredService<ManagementServiceName>(); var uri = serviceProviderUri.ToUri() .AppendPathSegment(serviceName) .ToUri(); return ManagementServiceUri.From(uri); } public static void ConfigureManagementServiceProviderUri(IHostApplicationBuilder builder) { ConfigureAzureEnvironment(builder); ConfigureSubscriptionId(builder); ConfigureResourceGroupName(builder); builder.Services.TryAddSingleton(GetManagementServiceProviderUri); } private static ManagementServiceProviderUri GetManagementServiceProviderUri(IServiceProvider provider) { var azureEnvironment = provider.GetRequiredService<AzureEnvironment>(); var subscriptionId = provider.GetRequiredService<SubscriptionId>(); var resourceGroupName = provider.GetRequiredService<ResourceGroupName>(); var configuration = provider.GetRequiredService<IConfiguration>(); var apiVersion = configuration.TryGetValue("ARM_API_VERSION") .IfNone(() => "2023-09-01-preview"); var uri = azureEnvironment.ManagementEndpoint .AppendPathSegment("subscriptions") .AppendPathSegment(subscriptionId) .AppendPathSegment("resourceGroups") .AppendPathSegment(resourceGroupName) .AppendPathSegment("providers/Microsoft.ApiManagement/service") .SetQueryParam("api-version", apiVersion) .ToUri(); return ManagementServiceProviderUri.From(uri); } private static void ConfigureSubscriptionId(IHostApplicationBuilder builder) { builder.Services.TryAddSingleton(GetSubscriptionId); } private static SubscriptionId GetSubscriptionId(IServiceProvider provider) { var configuration = provider.GetRequiredService<IConfiguration>(); var subscriptionId = configuration.GetValue("AZURE_SUBSCRIPTION_ID"); return new SubscriptionId(subscriptionId); } private static void ConfigureResourceGroupName(IHostApplicationBuilder builder) { builder.Services.TryAddSingleton(GetResourceGroupName); } private static ResourceGroupName GetResourceGroupName(IServiceProvider provider) { var configuration = provider.GetRequiredService<IConfiguration>(); var resourceGroupName = configuration.GetValue("AZURE_RESOURCE_GROUP_NAME"); return new ResourceGroupName(resourceGroupName); } public static void ConfigureManagementServiceDirectory(IHostApplicationBuilder builder) { builder.Services.TryAddSingleton(GetManagementServiceDirectory); } private static ManagementServiceDirectory GetManagementServiceDirectory(IServiceProvider provider) { var configuration = provider.GetRequiredService<IConfiguration>(); var directoryPath = configuration.GetValue("API_MANAGEMENT_SERVICE_OUTPUT_FOLDER_PATH"); var directory = new DirectoryInfo(directoryPath); return ManagementServiceDirectory.From(directory); } }