Files
SGU-CredentialProvider/src/SGU.CredentialProvider/ProviderSettings.cs
T

72 lines
2.7 KiB
C#

using System.Text.Json;
namespace SGU.CredentialProvider;
internal sealed class ProviderSettings
{
private const int MaximumSettingsBytes = 16 * 1024;
public Uri BrokerEndpoint { get; init; } = new("https://sgu-auth.lci.lasalle.mx:8443/v1/authenticate");
public string DomainNetbios { get; init; } = "LCI";
public int TimeoutSeconds { get; init; } = 35;
public string ClientCertificateThumbprint { get; init; } = string.Empty;
public string ServerCertificateThumbprint { get; init; } = string.Empty;
public static string DefaultPath => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"SGU",
"CredentialProvider",
"settings.json");
public static ProviderSettings Load(string? path = null)
{
path ??= Environment.GetEnvironmentVariable("SGU_CREDENTIAL_PROVIDER_CONFIG") ?? DefaultPath;
FileInfo file = new(path);
if (!file.Exists || file.Length is <= 0 or > MaximumSettingsBytes)
{
throw new InvalidOperationException("Credential Provider settings are missing or invalid.");
}
using FileStream stream = new(path, FileMode.Open, FileAccess.Read, FileShare.Read);
ProviderSettings settings = JsonSerializer.Deserialize<ProviderSettings>(stream, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
}) ?? throw new InvalidOperationException("Credential Provider settings could not be read.");
settings.Validate();
return settings;
}
public void Validate()
{
if (!BrokerEndpoint.IsAbsoluteUri ||
BrokerEndpoint.Scheme != Uri.UriSchemeHttps ||
!string.IsNullOrEmpty(BrokerEndpoint.UserInfo))
{
throw new InvalidOperationException("BrokerEndpoint must be an absolute HTTPS URL without user information.");
}
if (!string.Equals(BrokerEndpoint.AbsolutePath.TrimEnd('/'), "/v1/authenticate", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("BrokerEndpoint must target /v1/authenticate.");
}
if (string.IsNullOrWhiteSpace(DomainNetbios) || TimeoutSeconds is < 2 or > 60)
{
throw new InvalidOperationException("DomainNetbios or TimeoutSeconds is invalid.");
}
if (NormalizeThumbprint(ClientCertificateThumbprint).Length != 40 ||
NormalizeThumbprint(ServerCertificateThumbprint).Length != 40)
{
throw new InvalidOperationException("Client and server SHA-1 certificate thumbprints are required.");
}
}
public static string NormalizeThumbprint(string value) =>
value.Replace(" ", string.Empty, StringComparison.Ordinal).ToUpperInvariant();
}