fix(security): count only this page's references in the browse-filter summary
On a BrowseNext the references list already carries the earlier pages, so the summary's denominator counted them again. Log accuracy only — the filtering itself was already scoped to this call's appended range. Claude-Session: https://claude.ai/code/session_015p7wGqy3YpZNCpDzTpGMKo
This commit is contained in:
@@ -522,6 +522,12 @@ services:
|
||||
ConfigSource__CentralFetchEndpoints__0: "http://central-1:4055"
|
||||
ConfigSource__CentralFetchEndpoints__1: "http://central-2:4055"
|
||||
ConfigSource__ApiKey: "configserve-docker-dev-key"
|
||||
# #520 stage 6 — node ACL enforcement, the dark switch. Default OFF everywhere, exactly as in
|
||||
# production; the site-a pair is the demo/live-gate subject, so it reads an env override:
|
||||
# OTOPCUA_ACL_ENABLED=true docker compose -f docker-dev/docker-compose.yml up -d site-a-1 site-a-2
|
||||
# With it on, EVERY data-plane operation needs a matching NodeAcl grant — a principal with no
|
||||
# grant connects and sees nothing. site-b stays hardcoded OFF as the A/B control.
|
||||
Security__Acl__Enabled: "${OTOPCUA_ACL_ENABLED:-false}"
|
||||
# Per-cluster mesh Phase 5/6 (gRPC live-telemetry stream) — see central-1/central-2. This
|
||||
# node carries cluster-SITE-A + driver, so SplitTopologyTransportValidator requires
|
||||
# Telemetry:Mode=Grpc (mandatory, not a dark switch, as of Phase 6). The dedicated :4056
|
||||
@@ -631,6 +637,12 @@ services:
|
||||
ConfigSource__CentralFetchEndpoints__0: "http://central-1:4055"
|
||||
ConfigSource__CentralFetchEndpoints__1: "http://central-2:4055"
|
||||
ConfigSource__ApiKey: "configserve-docker-dev-key"
|
||||
# #520 stage 6 — node ACL enforcement, the dark switch. Default OFF everywhere, exactly as in
|
||||
# production; the site-a pair is the demo/live-gate subject, so it reads an env override:
|
||||
# OTOPCUA_ACL_ENABLED=true docker compose -f docker-dev/docker-compose.yml up -d site-a-1 site-a-2
|
||||
# With it on, EVERY data-plane operation needs a matching NodeAcl grant — a principal with no
|
||||
# grant connects and sees nothing. site-b stays hardcoded OFF as the A/B control.
|
||||
Security__Acl__Enabled: "${OTOPCUA_ACL_ENABLED:-false}"
|
||||
# Per-cluster mesh Phase 5/6 (gRPC live-telemetry stream) — see central-1/site-a-1.
|
||||
# Telemetry:Mode=Grpc is mandatory as of Phase 6 (cluster-SITE-A + driver); the dedicated
|
||||
# :4056 listener binds regardless.
|
||||
|
||||
@@ -2754,8 +2754,11 @@ public sealed class OtOpcUaNodeManager : CustomNodeManager2
|
||||
if (source is not null && !Permits(identity, OpcUaOperation.Browse, source))
|
||||
throw new ServiceResultException(StatusCodes.BadUserAccessDenied);
|
||||
|
||||
// Only the references THIS call appends are ours to filter — on a BrowseNext the list already
|
||||
// carries the earlier pages, and re-examining them would both waste work and skew the summary.
|
||||
var before = references.Count;
|
||||
base.Browse(context, ref continuationPoint, references);
|
||||
var returned = references.Count - before;
|
||||
|
||||
var filtered = 0;
|
||||
for (var ii = references.Count - 1; ii >= before; ii--)
|
||||
@@ -2773,7 +2776,7 @@ public sealed class OtOpcUaNodeManager : CustomNodeManager2
|
||||
filtered++;
|
||||
}
|
||||
|
||||
LogAclFiltering("Browse", identity, filtered, references.Count + filtered);
|
||||
LogAclFiltering("Browse", identity, filtered, returned);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
Reference in New Issue
Block a user