Extend the RoleManagement sample to the Part 18 items #836 recommends - #864
Merged
Merged
Conversation
Issue #836 is a menu of nine self-contained increments to Workshop/RoleManagement. This takes the four its own "suggested order" names, and gives each of them a demonstration in the sample client and a fixture in the tests. **AccessRestrictions (item 5).** Calibration carries EncryptionRequired and MaintenanceNote adds ApplyRestrictionsToBrowse, so an Engineer who holds Browse, Read and Write on both is refused with BadSecurityModeInsufficient on the unsecured endpoint. That is a different fix from BadUserAccessDenied - reconnect with security rather than sign in as somebody else - and the client shows the attribute in a new column. **Endpoint filter and CustomConfiguration (item 2).** The ConfigureAdmin Role is restricted to the encrypted endpoints, which Part 18 4.4.1 evaluates before any identity rule. Its CustomConfiguration flag stays false and the client's new button flips it, which is what lets a Role with an empty Identities list be granted at all. **Certificate criteria (item 1).** ConfigureAdmin is granted for an X509Subject rule naming the certificate the sample client creates for itself, so an anonymous Session from that client holds a Role no account can earn - and a new ServiceCode node is there to observe it. The client's criteria drop down adds Thumbprint and X509Subject beside UserName and fills the box with what it would present. **Auditing (item 7).** The server sets AuditingEnabled and the client subscribes to AuditEventType on the Server object. Three things the stack does rather than what the issue assumed, all measured: * Thumbprint and X509Subject match the client's *application instance* certificate, not a user certificate, so no X509 user token policy is needed. * IRoleManager.AddEndpoint refuses an entry with an empty EndpointUrl although 4.4.2 treats a default field as a wildcard, so the endpoints the server advertises are copied in OnServerStarted instead. * No audit event of any type reaches a subscriber in 2.0.0-preview.4: Server.Auditing reads true and a GeneralModelChangeEvent from the same object does arrive. The fixture is written the right way round and recorded with KnownIssueAsync, so it fails and asks for the note when that is fixed. TestClient gains an application certificate subject and thumbprint, so a test can assert what a server matched it by. Items 3 (the section 5 user management model) and 9 (a vendor-defined Role, which waits on UA-.NETStandard#4361) stay open, as #836 asks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ver surface #861 landed on master while this was open and deleted every per-sample StandardServer subclass, RoleManagementServer.cs among them, in favour of registrations on the server builder. The conflict is a real one rather than textual: this branch had added a Role configuration and an OnServerStarted override to exactly the class master removed. Resolved by keeping master's shape and porting the additions onto the new seams: * the X509Subject rule which grants ConfigureAdmin for the certificate of the maintenance workstation joins the other role mappings in SampleUsers.ConfigureRoles, as a RoleDefinitionOptions on the well known Role; WorkstationCertificateSubject and WorkstationRoleId move there with it. * the Endpoints filter becomes WorkstationEndpoints, an IServerStartupTask registered with AddStartupTask<T>. It still cannot be declared with the rest of the role configuration: AddEndpoint refuses an entry with an empty EndpointUrl (UA-.NETStandard#4412), so the endpoints the server advertises have to be copied, and those are only known once it has started. Declaring the wildcard in RoleConfigurationOptions would be worse than the startup task, because the stack applies those entries without looking at what AddEndpoint answered - the Role would end up granted on every endpoint. The tier 1.5 fixture follows the constant to SampleUsers; the README and the node manager comment follow the code. Tier 1 116 passed, tier 1.5 170 passed with 4 skipped (one of them the recorded audit known issue), tier 2 63 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
romanett
added a commit
that referenced
this pull request
Sep 4, 2026
Master extended four of the clients this branch had already split, so their new features are ported into the models rather than back into the windows: - RoleManagement (#864): the identity criteria (UserName/Thumbprint/X509Subject) and the criteria strings this client can be matched by, the CustomConfiguration flag, the AccessRestrictions and Endpoints columns, and the audit trail stream all live in RoleManagementClientModel; the window renders them. - StateMachines (#860): the materialized Part 16 model (available states and transitions), the sub state machine below Running with its StartBatch cause, and the effective state stream live in StateMachinesClientModel. - NodeManagement: the hand written model change pump is replaced by the stack's ModelChangeTracker inside the model. - UserAuthentication: the Kerberos and SAML stubs are gone from the model and the window, as on master. The model fixtures gained cases for the new surface; the testing guide keeps the model fixture column with master's updated StateMachines row. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed changes
Issue #836 is a menu of nine self-contained increments to
Workshop/RoleManagement, writtendown after #828 landed so that the gaps were a choice on record. This takes the four its own
Suggested order names — 5 (AccessRestrictions), 7 (auditing), 2 (endpoint-filtered
Role and
CustomConfiguration) and 1 limited toThumbprint/X509Subject— and giveseach of them a demonstration in the sample client and a fixture in the tests. Items 3 (the
§5 user management model, which wants its own sample) and 9 (a vendor-defined Role, blocked
on OPCFoundation/UA-.NETStandard#4361) stay open, as the issue asks.
AccessRestrictions — the half of the access story the sample was missing
CalibrationcarriesEncryptionRequired,MaintenanceNoteaddsApplyRestrictionsToBrowse.An Engineer who holds Browse, Read and Write on both is refused with
BadSecurityModeInsufficienton the unsecured endpoint, and the distinction is the point:BadUserAccessDeniedmeans sign in as somebody else,BadSecurityModeInsufficientmeansreconnect with security. The client shows the attribute in a new column.
An endpoint filter, and the flag that goes with it
ConfigureAdminis restricted to the encrypted endpoints, which Part 18 §4.4.1 evaluatesbefore any identity rule. Its
CustomConfigurationflag is deliberately leftfalseand theclient's new Toggle CustomConfiguration button flips it — that flag is the only thing which
lets a Role with an empty
Identitieslist be granted at all.A Role earned by a certificate rather than by an account
ConfigureAdminis granted by anX509Subjectrule naming the certificate the sample clientcreates for itself, so an anonymous Session from that client holds a Role no account can
earn. One new node,
ServiceCode, is there to observe it. The client's identity criteriadrop-down adds
ThumbprintandX509SubjectbesideUserNameand fills the box with what itwould present.
Auditing
The server sets
AuditingEnabledand the client subscribes toAuditEventTypeon the Serverobject — see the caveat below.
Three things the stack does differently from what the issue assumed
All measured against
2.0.0-preview.4, and all recorded in the README and in code comments sothe next reader does not have to rediscover them:
ThumbprintandX509Subjectmatch the client's application instance certificate, nota user certificate —
SessionManagerpassessession.ClientCertificatetoResolveGrantedRoles. So no X509 user token policy is needed, and such a Role belongs to theworkstation: every Session it opens holds it, signed in or not. The issue assumed the other
reading, which is why it estimated this item as needing a user certificate.
IRoleManager.AddEndpointrefuses an entry whoseEndpointUrlis empty, althoughEndpointTypeComparer.Matchestreats a default-valued field as a wildcard per §4.4.2 — so{ SecurityMode = SignAndEncrypt }cannot be stored. The server copies the endpointdescriptions it actually advertises instead, which is why that part of the Role configuration
runs in
OnServerStartedrather than inCreateRoleManager. Filed upstream asIRoleManager.AddEndpoint refuses the wildcard endpoint filter that EndpointTypeComparer is written to match UA-.NETStandard#4412.
2.0.0-preview.4.Server.Auditingreads
true,AddIdentityanswersGood, and aGeneralModelChangeEventfrom the sameServer object arrives on the same subscription — audit events do not. Reproduced on
RoleManagementand onNodeManagement, with nothing logged server-side. The tier 1.5fixture is therefore written the right way round and wrapped in
KnownIssueAsync, so itturns into a failure asking for the note to be removed the moment the stack delivers them.
A separate investigation into the root cause is under way; if it turns out to be sample
misconfiguration rather than a stack defect, that note and the matching README paragraph
are what have to change.
A smaller one, also in the README:
ApplyRestrictionsToBrowsecovers a Browse of the restrictednode itself and a
TranslateBrowsePathsToNodeIdsstarting there, but not the reference to it inits parent's browse result — that per-reference filter applies role permissions only.
Related Issues
Types of changes
Checklist
Further comments
Why the demonstrations are laid out the way they are
Each feature is observed through a Role and a node which the other features do not touch, so a
failing assertion names one cause.
MaintenanceNoteandCalibrationare observed throughRoles which are not endpoint-filtered;
ServiceCode, which the endpoint-filtered Role owns,carries no AccessRestrictions of its own. Without that separation a refusal on the unsecured
endpoint would be over-determined and the fixtures would stop teaching anything.
Test results
Run locally on Windows against
2.0.0-preview.4:Tests/SampleServers.Tests— 115 passedTests/SampleNodeManagers.Tests— 164 passed, 4 skipped (one of them the recordedaudit known issue; the other three pre-date this change)
Tests/SampleClients.Tests— 63 passedTwo of the tier 2 fixtures are new.
TheCertificateOfThisClientEarnsTheServiceCodeis the oneworth knowing about: it holds the server's hard-coded
X509Subjectcriteria to the certificatethe client's own configuration file actually produces, so it fails if either is edited without
the other.
Shared test helper
TestClientgains an application certificate subject and thumbprint, and a connect overloadwhich takes a certificate subject, so a test can assert what a server matched a client by. Two
clients built with the same subject still differ by thumbprint, which is exactly the contrast
between the two criteria.
🤖 Generated with Claude Code