4563940792
User decision: save, Test Connect, live browse and the deploy gate keep refusing out-of-namespace credential references, but an ALREADY-DEPLOYED driver must not fault at the upgrade restart or (Galaxy) at the next gateway reconnect, since ReopenAsync re-resolves Gateway.ApiKeySecretRef. - LegacyCredentialReferenceTracker (Core.Abstractions): the one, deprecated, call-site-chosen compatibility path. Running Galaxy (InitializeAsync, ReopenAsync, ack fallback) and OpcUaClient (session open) pass it and keep the pre-#815 semantics (case-insensitive prefixes, Galaxy file:, OpcUaClient literal pass-through) with a rate-limited Warning (driver/field/allowed form, never the value) and a credential-compat:<field> diagnostics entry (both drivers now implement IDriverDiagnostics). Browsers and probes pass none and stay hard-fail; Heidenhain has none. - Deploy-gate message names the migration. - Upgrade preflight: CredentialReferencePreflightService (admin nodes, once after ApplicationStarted, ConfigDb only, resolves nothing) logs a Warning per Draft row / Deployed-artifact finding; the /raw banner shows them plus Running drivers reporting warn-only use (driver-health diagnostics). - docs/security.md: exact replacement table (incl. the old form default env:MX_API_KEY, file:, un-namespaced secret:, casing changes), the ReopenAsync reconnect behaviour, the warn-only window and its removal. Co-Authored-By: Claude <noreply@anthropic.com>
86 lines
3.4 KiB
Plaintext
86 lines
3.4 KiB
Plaintext
@using Microsoft.EntityFrameworkCore
|
|
@using ZB.MOM.WW.OtOpcUa.AdminUI.Deployments
|
|
@using ZB.MOM.WW.OtOpcUa.AdminUI.Hubs
|
|
@using ZB.MOM.WW.OtOpcUa.Configuration
|
|
@inject CredentialReferencePreflightState State
|
|
@inject IDriverStatusSnapshotStore DriverStatus
|
|
@inject IServiceProvider Services
|
|
|
|
@* lmxopcua#815 upgrade preflight surface: stored / deployed configs whose credential references sit outside their
|
|
driver's namespace (the boot scan, re-runnable here) plus running drivers that reported resolving one through the
|
|
deprecated warn-only compatibility path (driver-health diagnostics, fleet-wide). Never shows a value. *@
|
|
|
|
@if (_findings.Count > 0 || _error is not null)
|
|
{
|
|
<div class="alert alert-warning small mb-3" role="alert">
|
|
<div class="d-flex justify-content-between align-items-start gap-2">
|
|
<div>
|
|
<strong>Credential references outside their driver's namespace (lmxopcua#815).</strong>
|
|
The deploy gate refuses these; a driver deployed before the upgrade keeps resolving them in
|
|
deprecated warn-only mode until its next deploy. Migrate each to the allowed form — see
|
|
docs/security.md "Credential references are namespaced per driver".
|
|
</div>
|
|
<button class="btn btn-sm btn-outline-secondary" disabled="@_busy" @onclick="RecheckAsync">Re-check</button>
|
|
</div>
|
|
@if (_error is not null)
|
|
{
|
|
<div class="text-danger mt-1">@_error</div>
|
|
}
|
|
<ul class="mb-0 mt-2">
|
|
@foreach (var f in _findings.Take(MaxRows))
|
|
{
|
|
<li>
|
|
<span class="badge bg-secondary me-1">@f.Source</span>
|
|
@if (!string.IsNullOrEmpty(f.DriverType)) { <span>@f.DriverType </span> }
|
|
driver <span class="mono">@f.DriverName</span>
|
|
@if (f.DeviceName is not null) { <span> device <span class="mono">@f.DeviceName</span></span> }
|
|
— @f.Problem
|
|
</li>
|
|
}
|
|
</ul>
|
|
@if (_findings.Count > MaxRows)
|
|
{
|
|
<div class="mt-1 text-muted">…and @(_findings.Count - MaxRows) more (see the node log).</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
@code {
|
|
private const int MaxRows = 25;
|
|
private IReadOnlyList<CredentialReferenceFinding> _findings = [];
|
|
private string? _error;
|
|
private bool _busy;
|
|
|
|
protected override void OnInitialized() => Compose(State.Current);
|
|
|
|
private void Compose(CredentialReferencePreflightState.Snapshot snapshot)
|
|
{
|
|
_error = snapshot.Error;
|
|
_findings = snapshot.Findings
|
|
.Concat(CredentialReferencePreflight.RunningFindings(DriverStatus.GetAll()))
|
|
.ToList();
|
|
}
|
|
|
|
private async Task RecheckAsync()
|
|
{
|
|
var factory = Services.GetService(typeof(IDbContextFactory<OtOpcUaConfigDbContext>)) as IDbContextFactory<OtOpcUaConfigDbContext>;
|
|
if (factory is null) return;
|
|
_busy = true;
|
|
try
|
|
{
|
|
var findings = await new CredentialReferencePreflight(factory).ScanAsync(CancellationToken.None);
|
|
var snapshot = new CredentialReferencePreflightState.Snapshot(findings, DateTime.UtcNow, null);
|
|
State.Set(snapshot);
|
|
Compose(snapshot);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_error = "The credential-reference preflight could not read the config DB.";
|
|
}
|
|
finally
|
|
{
|
|
_busy = false;
|
|
}
|
|
}
|
|
}
|