Consolidate LDAP roles into OPC UA session roles with granular write permissions

Map LDAP groups to custom OPC UA role NodeIds on RoleBasedIdentity.GrantedRoleIds
during authentication, replacing the username-to-role side cache. Split ReadWrite
into WriteOperate/WriteTune/WriteConfigure so write access is gated per Galaxy
security classification. AnonymousCanWrite now behaves consistently regardless
of LDAP state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-29 01:50:16 -04:00
parent 50b9603465
commit 50b85d41bd
21 changed files with 549 additions and 94 deletions

View File

@@ -143,6 +143,62 @@ alarms --node DEV --refresh:
Same 5 alarms visible at DEV (grandparent) level
```
## Auth Consolidation Update
Updated: `2026-03-28`
Both instances updated to consolidate LDAP roles into OPC UA session roles (`RoleBasedIdentity.GrantedRoleIds`).
Code changes:
- LDAP groups now map to custom OPC UA role NodeIds in `urn:zbmom:lmxopcua:roles` namespace
- Roles stored on session identity via `GrantedRoleIds` — no username-to-role side cache
- Permission checks use `GrantedRoleIds.Contains()` instead of username extraction
- `AnonymousCanWrite` behavior is consistent regardless of LDAP state
- Galaxy namespace moved from `ns=2` to `ns=3` (roles namespace is `ns=2`)
No configuration changes required.
Verification (instance1, port 4840):
```
anonymous read → allowed
anonymous write → denied (BadUserAccessDenied, AnonymousCanWrite=false)
readonly write → denied (BadUserAccessDenied)
readwrite write → allowed
admin write → allowed
alarmack write → denied (BadUserAccessDenied)
bad password → rejected (connection failed)
```
## Granular Write Roles Update
Updated: `2026-03-28`
Both instances updated with granular write roles replacing the single ReadWrite role.
Code changes:
- `ReadWrite` role replaced by `WriteOperate`, `WriteTune`, `WriteConfigure`
- Write permission checks now consider the Galaxy security classification of the target attribute
- `SecurityClassification` stored in `TagMetadata` for per-node lookup at write time
GLAuth changes:
- New groups: `WriteOperate` (5502), `WriteTune` (5504), `WriteConfigure` (5505)
- New users: `writeop`, `writetune`, `writeconfig`
- `admin` user added to all groups (5502, 5503, 5504, 5505)
Config changes (both instances):
- `Authentication.Ldap.ReadWriteGroup` replaced by `WriteOperateGroup`, `WriteTuneGroup`, `WriteConfigureGroup`
Verification (instance1, port 4840, Operate-classified attributes):
```
anonymous read → allowed
anonymous write → denied (AnonymousCanWrite=false)
readonly write → denied (no write role)
writeop write → allowed (WriteOperate matches Operate classification)
writetune write → denied (WriteTune doesn't match Operate)
writeconfig write → denied (WriteConfigure doesn't match Operate)
admin write → allowed (has all write roles)
```
## Notes
The service deployment and restart succeeded. The live CLI checks confirm the endpoint is reachable and that the array node identifier has changed to the bracketless form. The array value on the live service still prints as blank even though the status is good, so if this environment should have populated `MoveInPartNumbers`, the runtime data path still needs follow-up investigation.