This commit is contained in:
@@ -64,6 +64,18 @@ public sealed record RemoteAgentOptions
|
||||
[JsonPropertyName("token")]
|
||||
public string? Token { get; init; }
|
||||
|
||||
[JsonPropertyName("tokenFile")]
|
||||
public string? TokenFile { get; init; }
|
||||
|
||||
[JsonPropertyName("serverCaFile")]
|
||||
public string? ServerCaFile { get; init; }
|
||||
|
||||
[JsonPropertyName("clientCertificateFile")]
|
||||
public string? ClientCertificateFile { get; init; }
|
||||
|
||||
[JsonPropertyName("clientCertificateKeyFile")]
|
||||
public string? ClientCertificateKeyFile { get; init; }
|
||||
|
||||
[JsonPropertyName("nodeId")]
|
||||
public string? NodeId { get; init; }
|
||||
|
||||
@@ -74,15 +86,38 @@ public sealed record RemoteAgentOptions
|
||||
public bool AllowInsecureHttp { get; init; }
|
||||
|
||||
public bool IsConfigured => !string.IsNullOrWhiteSpace(AuthAddress)
|
||||
&& !string.IsNullOrWhiteSpace(Token)
|
||||
&& (!string.IsNullOrWhiteSpace(Token) || !string.IsNullOrWhiteSpace(TokenFile))
|
||||
&& !string.IsNullOrWhiteSpace(NodeId);
|
||||
|
||||
public string TokenState => string.IsNullOrWhiteSpace(Token) ? "not-configured" : "configured";
|
||||
public string TokenState => !string.IsNullOrWhiteSpace(TokenFile)
|
||||
? "file-configured"
|
||||
: string.IsNullOrWhiteSpace(Token) ? "not-configured" : "configured";
|
||||
|
||||
public string GetToken()
|
||||
{
|
||||
string? token;
|
||||
if (string.IsNullOrWhiteSpace(TokenFile))
|
||||
{
|
||||
token = Token;
|
||||
}
|
||||
else
|
||||
{
|
||||
try { token = File.ReadAllText(TokenFile).Trim(); }
|
||||
catch (Exception exception) when (exception is IOException or UnauthorizedAccessException or ArgumentException)
|
||||
{
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "tokenFile could not be read.", exception);
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "token or tokenFile must contain a non-empty token.");
|
||||
return token;
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(AuthAddress) || string.IsNullOrWhiteSpace(Token) || string.IsNullOrWhiteSpace(NodeId))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "authAddress, token and nodeId are required before remote access is enabled.");
|
||||
if (string.IsNullOrWhiteSpace(AuthAddress) || (!string.IsNullOrWhiteSpace(Token) && !string.IsNullOrWhiteSpace(TokenFile))
|
||||
|| (!IsConfigured) || string.IsNullOrWhiteSpace(NodeId))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "authAddress, token or tokenFile and nodeId are required before remote access is enabled.");
|
||||
if (!Uri.TryCreate(AuthAddress, UriKind.Absolute, out var uri) || uri is null
|
||||
|| uri.AbsolutePath == "/" && uri.Query.Length != 0
|
||||
|| uri.UserInfo.Length != 0
|
||||
@@ -92,12 +127,28 @@ public sealed record RemoteAgentOptions
|
||||
&& (!AllowInsecureHttp || !IsPrivateNetwork(uri.Host)))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "Non-loopback HTTP requires allowInsecureHttp=true and a private-network IP address.");
|
||||
ValidateIdentifier(NodeId, "nodeId", 200);
|
||||
if (Token.Any(char.IsWhiteSpace))
|
||||
var token = GetToken();
|
||||
if (token.Any(char.IsWhiteSpace))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "token must not contain whitespace.");
|
||||
if (!string.IsNullOrWhiteSpace(TokenFile) && !File.Exists(TokenFile))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "tokenFile does not exist.");
|
||||
ValidateOptionalFile(ServerCaFile, "serverCaFile");
|
||||
ValidateOptionalFile(ClientCertificateFile, "clientCertificateFile");
|
||||
ValidateOptionalFile(ClientCertificateKeyFile, "clientCertificateKeyFile");
|
||||
if (!string.IsNullOrWhiteSpace(ClientCertificateKeyFile) && string.IsNullOrWhiteSpace(ClientCertificateFile))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "clientCertificateFile is required with clientCertificateKeyFile.");
|
||||
if (!string.IsNullOrWhiteSpace(ClientCertificateFile) && string.IsNullOrWhiteSpace(ClientCertificateKeyFile))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "clientCertificateKeyFile is required for PEM client certificates.");
|
||||
}
|
||||
|
||||
public RemoteAgentOptions Redacted() => this with { Token = string.IsNullOrWhiteSpace(Token) ? null : "<redacted>" };
|
||||
|
||||
private static void ValidateOptionalFile(string? path, string name)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(path) && !File.Exists(path))
|
||||
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, $"{name} does not exist.");
|
||||
}
|
||||
|
||||
private static bool IsLoopback(string host) => host.Equals("localhost", StringComparison.OrdinalIgnoreCase)
|
||||
|| System.Net.IPAddress.TryParse(host.Trim('[', ']'), out var address) && System.Net.IPAddress.IsLoopback(address);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user