docs(opcuaclient): keep server host-name check opt-in; surface it in the Security panel (#837)

Owner decision 2026-11-11: certificateValidation.validateServerHostName stays
opt-in (unset = off). The AdminUI toggle moves from the "Subscriptions, limits &
discovery" panel to the Security panel beside mode/policy, with help text on the
NAT/IP caveat, IPv6 zone ids and the loose first-label match. Binding unchanged
(tri-state, "Default (off)" leaves the key absent). OpcUaClient.md states the
decision; drivers rule updated; source-scan test pins placement + caveats.

Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
This commit is contained in:
Joseph Doherty
2026-11-11 11:57:59 -05:00
parent bdbc47f5fc
commit e6ec5a0948
4 changed files with 64 additions and 12 deletions
@@ -111,6 +111,30 @@
}
</InputSelect>
</div>
@* #816 / #837: opt-in by owner decision (unset = off). Kept in the Security panel so it is
found next to the mode/policy it depends on; "Default (off)" leaves the key absent. *@
<div class="col-md-4">
<label class="form-label" for="opcuaValidateHostName">Server certificate host-name check</label>
<InputSelect id="opcuaValidateHostName" @bind-Value="_form.OpcUa.ValidateServerHostName" @bind-Value:after="EmitAsync" class="form-select form-select-sm">
<option value="">Default (off)</option>
<option value="true">Validate configured host</option>
<option value="false">Off (NAT / port publish)</option>
</InputSelect>
</div>
<div class="col-12">
<div class="form-text">
<strong>Opt-in (off unless set).</strong> When validating, the server certificate must name the
endpoint host <em>you configured</em>; a miss refuses the connection
(<code>BadCertificateHostNameInvalid</code>). Applies to Sign / SignAndEncrypt only, never to
<code>None</code>, and auto-accept accepts a mismatch. Caveats:
<ul class="mb-0">
<li><strong>NAT / port publish / connecting by IP:</strong> fails unless the certificate lists that exact host or IP — leave off.</li>
<li><strong>IPv6 zone ids</strong> (<code>fe80::1%eth0</code>, link-local) never match — leave off.</li>
<li><strong>Loose match:</strong> the first DNS label alone counts (<code>plc1.site-b.corp</code> passes a certificate for <code>PLC1</code>), so use fully-qualified, site-unique certificate names.</li>
</ul>
Most useful with CA-issued trust; adds little over a pinned self-signed certificate.
</div>
</div>
</div>
</div>
</section>
@@ -195,15 +219,6 @@
</div>
<div class="form-text">Revoked certificates are always rejected.</div>
</div>
<div class="col-md-3">
<label class="form-label">Server host-name check</label>
<InputSelect @bind-Value="_form.OpcUa.ValidateServerHostName" @bind-Value:after="EmitAsync" class="form-select form-select-sm">
<option value="">Default (off)</option>
<option value="true">Validate configured host</option>
<option value="false">Off (NAT / port publish)</option>
</InputSelect>
<div class="form-text">Sign / SignAndEncrypt only (never on None): the server certificate must name the endpoint host you configured. Off for link-local IPv6.</div>
</div>
<div class="col-md-6">
<label class="form-label">Issuer store / CRL directory</label>
<InputText @bind-Value="_form.OpcUa.IssuerStorePath" @bind-Value:after="EmitAsync" class="form-control form-control-sm mono" />