Auto: opcuaclient-5 — CRL/revocation handling
Adds explicit revoked-vs-untrusted distinction to the OpcUaClient driver's
server-cert validation hook, plus three new knobs on a new
OpcUaCertificateValidationOptions sub-record:
RejectSHA1SignedCertificates (default true — SHA-1 is OPC UA spec-deprecated;
this is a deliberately tighter default)
RejectUnknownRevocationStatus (default false — keeps brownfield deployments
without CRL infrastructure working)
MinimumCertificateKeySize (default 2048)
The validator hook now runs whether or not AutoAcceptCertificates is set:
revoked / issuer-revoked certs are always rejected with a distinct
"REVOKED" log line; SHA-1 + small-key certs are rejected per policy;
unknown-revocation gates on the new flag; untrusted still honours
AutoAccept.
Decision pipeline factored into a static EvaluateCertificateValidation
helper with a CertificateValidationDecision record so unit tests cover
all branches without needing to spin up an SDK CertificateValidator.
CRL files themselves: the OPC UA SDK reads them automatically from the
crl/ subdir of each cert store — no driver-side wiring needed.
Documented on the new options record.
Tests (12 new) cover defaults, every branch of the decision pipeline,
SHA-1 detection (custom X509SignatureGenerator since .NET 10's
CreateSelfSigned refuses SHA-1), and key-size detection. All 127
OpcUaClient unit tests still pass.
Closes #277
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -141,8 +141,56 @@ public sealed class OpcUaClientDriverOptions
|
||||
/// values so existing deployments see no behaviour change.
|
||||
/// </summary>
|
||||
public OpcUaSubscriptionDefaults Subscriptions { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Server-certificate validation knobs applied during the
|
||||
/// <c>CertificateValidator.CertificateValidation</c> callback. Surfaces explicit
|
||||
/// handling for revoked certs (always rejected, never auto-accepted), unknown
|
||||
/// revocation status (rejected only when <see cref="OpcUaCertificateValidationOptions.RejectUnknownRevocationStatus"/>
|
||||
/// is set), SHA-1 signature rejection, and minimum RSA key size. Defaults preserve
|
||||
/// existing behaviour wherever possible — the one tightening is
|
||||
/// <see cref="OpcUaCertificateValidationOptions.RejectSHA1SignedCertificates"/>=true
|
||||
/// since SHA-1 is spec-deprecated for OPC UA.
|
||||
/// </summary>
|
||||
public OpcUaCertificateValidationOptions CertificateValidation { get; init; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Knobs governing the server-certificate validation callback. Plumbed onto
|
||||
/// <see cref="OpcUaClientDriverOptions.CertificateValidation"/> rather than the top-level
|
||||
/// options to keep cert-related config grouped together.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <b>CRL discovery:</b> the OPC UA SDK reads CRL files automatically from the
|
||||
/// <c>crl/</c> sub-directory of each cert store (own, trusted, issuers). Drop the
|
||||
/// issuer's <c>.crl</c> in that folder and the SDK picks it up — no driver-side wiring
|
||||
/// required. When the directory is absent or empty, the SDK reports
|
||||
/// <c>BadCertificateRevocationUnknown</c>, which this driver gates with
|
||||
/// <see cref="RejectUnknownRevocationStatus"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="RejectSHA1SignedCertificates">
|
||||
/// Reject server certificates whose signature uses SHA-1. Default <c>true</c> — SHA-1 was
|
||||
/// deprecated by the OPC UA spec and is treated as a hard fail in production. Flip to
|
||||
/// <c>false</c> only for short-term interop with legacy controllers.
|
||||
/// </param>
|
||||
/// <param name="RejectUnknownRevocationStatus">
|
||||
/// When the SDK can't determine revocation status (no CRL present, or stale CRL),
|
||||
/// reject the cert if <c>true</c>; allow if <c>false</c>. Default <c>false</c> — many
|
||||
/// plant deployments don't run CRL infrastructure, and a hard-fail default would break
|
||||
/// them on first connection. Set <c>true</c> in environments with a managed PKI.
|
||||
/// </param>
|
||||
/// <param name="MinimumCertificateKeySize">
|
||||
/// Minimum RSA key size (bits) accepted. Certs with shorter keys are rejected. Default
|
||||
/// <c>2048</c> matches the current OPC UA spec floor; raise to 3072 or 4096 for stricter
|
||||
/// deployments. Non-RSA keys (ECC) bypass this check.
|
||||
/// </param>
|
||||
public sealed record OpcUaCertificateValidationOptions(
|
||||
bool RejectSHA1SignedCertificates = true,
|
||||
bool RejectUnknownRevocationStatus = false,
|
||||
int MinimumCertificateKeySize = 2048);
|
||||
|
||||
/// <summary>
|
||||
/// Tuning surface for OPC UA subscriptions created by <see cref="OpcUaClientDriver"/>.
|
||||
/// Lifted from the per-call hard-coded literals so operators can tune publish cadence,
|
||||
|
||||
Reference in New Issue
Block a user