99 lines
3.8 KiB
C#
99 lines
3.8 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using StellaOps.Auth.Client;
|
|
using StellaOps.Zastava.Core.Configuration;
|
|
using StellaOps.Zastava.Core.Diagnostics;
|
|
using StellaOps.Zastava.Core.Security;
|
|
|
|
namespace Microsoft.Extensions.DependencyInjection;
|
|
|
|
public static class ZastavaServiceCollectionExtensions
|
|
{
|
|
public static IServiceCollection AddZastavaRuntimeCore(
|
|
this IServiceCollection services,
|
|
IConfiguration configuration,
|
|
string componentName)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(services);
|
|
ArgumentNullException.ThrowIfNull(configuration);
|
|
if (string.IsNullOrWhiteSpace(componentName))
|
|
{
|
|
throw new ArgumentException("Component name is required.", nameof(componentName));
|
|
}
|
|
|
|
services.AddOptions<ZastavaRuntimeOptions>()
|
|
.Bind(configuration.GetSection(ZastavaRuntimeOptions.SectionName))
|
|
.ValidateDataAnnotations()
|
|
.Validate(static options => !string.IsNullOrWhiteSpace(options.Tenant), "Tenant is required.")
|
|
.Validate(static options => !string.IsNullOrWhiteSpace(options.Environment), "Environment is required.")
|
|
.PostConfigure(options =>
|
|
{
|
|
if (string.IsNullOrWhiteSpace(options.Component))
|
|
{
|
|
options.Component = componentName;
|
|
}
|
|
})
|
|
.ValidateOnStart();
|
|
|
|
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFactoryOptions>, ZastavaLoggerFactoryOptionsConfigurator>());
|
|
services.TryAddSingleton<IZastavaLogScopeBuilder, ZastavaLogScopeBuilder>();
|
|
services.TryAddSingleton<IZastavaRuntimeMetrics, ZastavaRuntimeMetrics>();
|
|
ConfigureAuthorityServices(services, configuration);
|
|
services.TryAddSingleton<IZastavaAuthorityTokenProvider, ZastavaAuthorityTokenProvider>();
|
|
|
|
return services;
|
|
}
|
|
|
|
private static void ConfigureAuthorityServices(IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
var authoritySection = configuration.GetSection($"{ZastavaRuntimeOptions.SectionName}:authority");
|
|
var authorityOptions = new ZastavaAuthorityOptions();
|
|
authoritySection.Bind(authorityOptions);
|
|
|
|
services.AddStellaOpsAuthClient(options =>
|
|
{
|
|
options.Authority = authorityOptions.Issuer.ToString();
|
|
options.ClientId = authorityOptions.ClientId;
|
|
options.ClientSecret = authorityOptions.ClientSecret;
|
|
options.AllowOfflineCacheFallback = authorityOptions.AllowStaticTokenFallback;
|
|
options.ExpirationSkew = TimeSpan.FromSeconds(Math.Clamp(authorityOptions.RefreshSkewSeconds, 0, 300));
|
|
|
|
options.DefaultScopes.Clear();
|
|
var normalized = new SortedSet<string>(StringComparer.Ordinal);
|
|
|
|
if (authorityOptions.Audience is not null)
|
|
{
|
|
foreach (var audience in authorityOptions.Audience)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(audience))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
normalized.Add($"aud:{audience.Trim().ToLowerInvariant()}");
|
|
}
|
|
}
|
|
|
|
if (authorityOptions.Scopes is not null)
|
|
{
|
|
foreach (var scope in authorityOptions.Scopes)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(scope))
|
|
{
|
|
normalized.Add(scope.Trim());
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (var scope in normalized)
|
|
{
|
|
options.DefaultScopes.Add(scope);
|
|
}
|
|
});
|
|
}
|
|
}
|