mishima-nexus-client-csharp/src/Robotico.Nexus.Client/NexusTlsMaterial.cs

79 lines
3.2 KiB
C#
Raw Normal View History

namespace Robotico.Nexus.Client;
/// <summary>
/// Per-connection TLS/mTLS material for a Nexus machine credential. Uses the same environment
/// variable names as <c>Mishima.Nexus.Wire.Clients.WireTlsMaterial</c> (POLA) without depending on
/// that assembly — see docs/adr/0001-nexus-client-monolith.adoc.
/// </summary>
public sealed class NexusTlsMaterial
{
/// <summary>Creates material with required PEM paths.</summary>
public NexusTlsMaterial(string caCertificateFile, string clientCertificateFile, string clientKeyFile, bool useHttps = true)
{
ArgumentException.ThrowIfNullOrWhiteSpace(caCertificateFile);
ArgumentException.ThrowIfNullOrWhiteSpace(clientCertificateFile);
ArgumentException.ThrowIfNullOrWhiteSpace(clientKeyFile);
CaCertificateFile = Path.GetFullPath(caCertificateFile.Trim());
ClientCertificateFile = Path.GetFullPath(clientCertificateFile.Trim());
ClientKeyFile = Path.GetFullPath(clientKeyFile.Trim());
UseHttps = useHttps;
}
/// <summary>CA PEM used to trust the Nexus server certificate.</summary>
public string CaCertificateFile { get; }
/// <summary>Client certificate PEM (machine credential).</summary>
public string ClientCertificateFile { get; }
/// <summary>Client private key PEM.</summary>
public string ClientKeyFile { get; }
/// <summary>When true, dial <c>https://</c> gRPC.</summary>
public bool UseHttps { get; }
/// <summary>
/// Loads material from process env: <c>NEXUS_TLS_CA_FILE</c>, <c>NEXUS_TLS_CLIENT_CERT_FILE</c>,
/// <c>NEXUS_TLS_CLIENT_KEY_FILE</c>, optional <c>NEXUS_TLS_MODE</c> (defaults to https).
/// Returns <see langword="null"/> when the required files are absent (insecure/dev connection).
/// </summary>
public static NexusTlsMaterial? TryFromEnvironment()
{
string? ca = Environment.GetEnvironmentVariable("NEXUS_TLS_CA_FILE");
string? cert = Environment.GetEnvironmentVariable("NEXUS_TLS_CLIENT_CERT_FILE");
string? key = Environment.GetEnvironmentVariable("NEXUS_TLS_CLIENT_KEY_FILE");
string mode = Environment.GetEnvironmentVariable("NEXUS_TLS_MODE") ?? string.Empty;
bool https = string.IsNullOrWhiteSpace(mode) || string.Equals(mode, "https", StringComparison.OrdinalIgnoreCase);
if (string.IsNullOrWhiteSpace(ca)
|| string.IsNullOrWhiteSpace(cert)
|| string.IsNullOrWhiteSpace(key)
|| !File.Exists(ca)
|| !File.Exists(cert)
|| !File.Exists(key))
{
return null;
}
return new NexusTlsMaterial(ca, cert, key, https);
}
/// <summary>Validates that all files exist.</summary>
public void EnsureFilesExist()
{
if (!File.Exists(CaCertificateFile))
{
throw new InvalidOperationException($"CA file not found: {CaCertificateFile}");
}
if (!File.Exists(ClientCertificateFile))
{
throw new InvalidOperationException($"Client cert not found: {ClientCertificateFile}");
}
if (!File.Exists(ClientKeyFile))
{
throw new InvalidOperationException($"Client key not found: {ClientKeyFile}");
}
}
}