Implements configurable user authentication (anonymous + username/password) with pluggable credential provider (IUserAuthenticationProvider). Anonymous writes can be disabled via AnonymousCanWrite setting while reads remain open. Adds -U/-P flags to all CLI commands for authenticated sessions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
97 lines
4.0 KiB
C#
97 lines
4.0 KiB
C#
using Opc.Ua;
|
|
using Opc.Ua.Client;
|
|
using Opc.Ua.Configuration;
|
|
|
|
namespace OpcUaCli;
|
|
|
|
public static class OpcUaHelper
|
|
{
|
|
/// <summary>
|
|
/// Creates an OPC UA client session for the specified endpoint URL.
|
|
/// </summary>
|
|
/// <param name="endpointUrl">The OPC UA endpoint URL to connect to.</param>
|
|
/// <returns>An active OPC UA client session.</returns>
|
|
public static async Task<Session> ConnectAsync(string endpointUrl, string? username = null, string? password = null)
|
|
{
|
|
var config = new ApplicationConfiguration
|
|
{
|
|
ApplicationName = "OpcUaCli",
|
|
ApplicationUri = "urn:localhost:OpcUaCli",
|
|
ApplicationType = ApplicationType.Client,
|
|
SecurityConfiguration = new SecurityConfiguration
|
|
{
|
|
ApplicationCertificate = new CertificateIdentifier
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "own")
|
|
},
|
|
TrustedIssuerCertificates = new CertificateTrustList
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "issuer")
|
|
},
|
|
TrustedPeerCertificates = new CertificateTrustList
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "trusted")
|
|
},
|
|
RejectedCertificateStore = new CertificateTrustList
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "rejected")
|
|
},
|
|
AutoAcceptUntrustedCertificates = true
|
|
},
|
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
|
};
|
|
|
|
#pragma warning disable CS0618 // Sync/obsolete API is fine for a CLI tool
|
|
await config.Validate(ApplicationType.Client);
|
|
config.CertificateValidator.CertificateValidation += (_, e) => e.Accept = true;
|
|
|
|
var endpoint = CoreClientUtils.SelectEndpoint(config, endpointUrl, false);
|
|
var endpointConfig = EndpointConfiguration.Create(config);
|
|
var configuredEndpoint = new ConfiguredEndpoint(null, endpoint, endpointConfig);
|
|
|
|
UserIdentity identity = (username != null)
|
|
? new UserIdentity(username, System.Text.Encoding.UTF8.GetBytes(password ?? ""))
|
|
: new UserIdentity();
|
|
|
|
var session = await Session.Create(
|
|
config,
|
|
configuredEndpoint,
|
|
false,
|
|
"OpcUaCli",
|
|
60000,
|
|
identity,
|
|
null);
|
|
|
|
return session;
|
|
#pragma warning restore CS0618
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a raw command-line string into the runtime type expected by the target node.
|
|
/// </summary>
|
|
/// <param name="rawValue">The raw string supplied by the user.</param>
|
|
/// <param name="currentValue">The current node value used to infer the target type.</param>
|
|
/// <returns>A typed value suitable for an OPC UA write request.</returns>
|
|
public static object ConvertValue(string rawValue, object? currentValue)
|
|
{
|
|
return currentValue switch
|
|
{
|
|
bool => bool.Parse(rawValue),
|
|
byte => byte.Parse(rawValue),
|
|
short => short.Parse(rawValue),
|
|
ushort => ushort.Parse(rawValue),
|
|
int => int.Parse(rawValue),
|
|
uint => uint.Parse(rawValue),
|
|
long => long.Parse(rawValue),
|
|
ulong => ulong.Parse(rawValue),
|
|
float => float.Parse(rawValue),
|
|
double => double.Parse(rawValue),
|
|
_ => rawValue
|
|
};
|
|
}
|
|
}
|