mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-27 04:59:55 +08:00
* role management compliant with OPC UA Part 18 Server-side: - New IRoleManager / RoleManager with spec-correct status codes (Bad_AlreadyExists, Bad_NodeIdUnknown, Bad_RequestNotAllowed, Bad_NotFound) for every mutator per Part 18 4.2 / 4.4. - Pre-populate default identities for the three reserved well-known roles per Part 18 4.3 (Anonymous, AuthenticatedUser, TrustedApplication). - Reject mutations on reserved roles with Bad_RequestNotAllowed. - Validate IdentityMappingRuleType per Part 18 4.4.3 (empty criteria for Anonymous/AuthenticatedUser/TrustedApplication; upper-case hex for Thumbprint; Name=Value grammar for X509Subject). - Honour Part 18 4.4.2 default-field-as-wildcard EndpointType comparisons; tighten TrustedApplication/Application rules to require trusted certificate + signed channel. - Introduce CustomConfiguration flag per Part 18 4.4.1. - Add IRoleManager.RoleConfigurationChanged event raised after every successful mutation per Part 18 4.4.1. - Make RoleEntry an immutable snapshot. Address-space binding (typed proxies): - RoleStateBinding switched from stringly-typed OnCallMethod2 plumbing to the source-generated typed proxies (RoleSetState, RoleState, AddRoleMethodState, AddIdentityMethodState, ...). - DiagnosticsNodeManager.AddBehaviourToPredefinedNodeAsync upgrades passive BaseObjectState nodes of RoleSetType / RoleType to the typed RoleSetState / RoleState proxies at predefined-node load time. - New RoleAuthorizationGate.CheckAdmin centralizes SecurityAdmin role plus SignAndEncrypt enforcement per Part 18 4.2 / 4.4 / 5.2. - Bound writable ApplicationsExclude / EndpointsExclude / CustomConfiguration with the same auth gate. - Raise RoleMappingRuleChangedAuditEventType from every successful mutator (Part 18 4.5) via the existing AuditEvents helper. Client library: - New Opc.Ua.Client.Roles.RoleManagementClient + IRoleManagementClient + RoleInfo + SessionRoleExtensions.OpenRoleManagementClient. - Covers list / read / add / remove role, identity, application, endpoint operations plus Set*Exclude via Write Service. Tests: - New RoleManagerTests.cs - 37 NUnit tests for pre-populated roles, reserved-role immutability, spec-correct status codes, criteria validation, ResolveGrantedRoles, exclude semantics, CustomConfiguration, AddRole well-known NodeId reuse, and RoleConfigurationChanged event. Documentation: - Rewrite Docs/RoleBasedUserManagement.md as a Part 18 compliance reference (status-code matrix, client examples, known limitations). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add Part 18 5 UserManagement implementation Server-side: - New IUserManagement interface (Opc.Ua.Server.UserManagement) modelling Part 18 5.2.1 surface: PasswordLength, PasswordOptions, PasswordRestrictions, SnapshotUsers, AddUser, ModifyUser, RemoveUser, ChangePassword, MustChangePassword, IsUserActive, UserDeactivated event. - Default UserManagement implementation wraps the existing IUserDatabase and stores per-user UserConfigurationMask + description in memory. Validates passwords against PasswordLength + character-class flags from PasswordOptions; honours Part 18 5.2 result codes (Bad_AlreadyExists, Bad_NotFound, Bad_OutOfRange, Bad_NotSupported, Bad_ConfigurationError, Bad_InvalidSelfReference, Bad_IdentityTokenInvalid). - ChangePassword clears the MustChangePassword bit on success. - New UserManagementBinding wires the typed source-generated proxies (UserManagementState, AddUserMethodState, ModifyUserMethodState, RemoveUserMethodState, ChangePasswordMethodState) - typed OnCallAsync delegates everywhere; admin gate via RoleAuthorizationGate.CheckAdmin; ChangePassword gated via RoleAuthorizationGate.CheckSelfUserName; closes active sessions for deactivated users via ISessionManager. - ConfigurationNodeManager.AddBehaviourToPredefinedNodeAsync upgrades the passive UserManagement object to the typed UserManagementState proxy at predefined-node load time; CreateServerConfiguration invokes UserManagementBinding.Bind when an IUserManagement was injected. - IServerInternal gains UserManagement getter + SetUserManagement injector. Tests: - New Tests/Opc.Ua.Server.Tests/UserManagementTests.cs - 18 NUnit tests covering AddUser happy path, duplicate / password-length / config-flag validation, RemoveUser non-existent / self-reference / NoDelete, ModifyUser self-disable / disable-other UserDeactivated event, ChangePassword happy path / same-as-old / wrong-old / MustChangePassword bit clearing / NoChangeByUser rejection, IsUserActive on disabled vs active users. Documentation: - Update Docs/RoleBasedUserManagement.md with a User Management section including the spec result-code matrix, example wiring code, and reduce known limitations - UserManagement is no longer a limitation.
147 lines
5.5 KiB
C#
147 lines
5.5 KiB
C#
/* ========================================================================
|
|
* Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved.
|
|
*
|
|
* OPC Foundation MIT License 1.00
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use,
|
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following
|
|
* conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
* OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* The complete license agreement can be found here:
|
|
* http://opcfoundation.org/License/MIT/1.00/
|
|
* ======================================================================*/
|
|
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Opc.Ua.Client.Roles
|
|
{
|
|
/// <summary>
|
|
/// Strongly-typed client over the OPC UA Part 18 §4 role-management
|
|
/// methods on the server's <c>RoleSet</c> and <c>RoleType</c> objects.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// All mutator operations require the calling session to hold the
|
|
/// <c>SecurityAdmin</c> role and to use a <c>SignAndEncrypt</c> secure
|
|
/// channel; otherwise the server returns
|
|
/// <c>Bad_UserAccessDenied</c> / <c>Bad_SecurityModeInsufficient</c>
|
|
/// which surfaces as a <see cref="ServiceResultException"/>.
|
|
/// </remarks>
|
|
public interface IRoleManagementClient
|
|
{
|
|
/// <summary>
|
|
/// Browses the server's <c>RoleSet</c> and returns a snapshot of
|
|
/// every role exposed by it.
|
|
/// </summary>
|
|
ValueTask<IReadOnlyList<RoleInfo>> ListRolesAsync(CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Reads a single role by NodeId.
|
|
/// </summary>
|
|
ValueTask<RoleInfo> ReadRoleAsync(NodeId roleId, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleSet.AddRole</c> per Part 18 §4.2.2 and returns the
|
|
/// new role's NodeId.
|
|
/// </summary>
|
|
ValueTask<NodeId> AddRoleAsync(
|
|
string roleName,
|
|
string? namespaceUri = null,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleSet.RemoveRole</c> per Part 18 §4.2.3.
|
|
/// </summary>
|
|
ValueTask RemoveRoleAsync(NodeId roleId, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleType.AddIdentity</c> per Part 18 §4.4.5.
|
|
/// </summary>
|
|
ValueTask AddIdentityAsync(
|
|
NodeId roleId,
|
|
IdentityMappingRuleType rule,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleType.RemoveIdentity</c> per Part 18 §4.4.6.
|
|
/// </summary>
|
|
ValueTask RemoveIdentityAsync(
|
|
NodeId roleId,
|
|
IdentityMappingRuleType rule,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleType.AddApplication</c> per Part 18 §4.4.7.
|
|
/// </summary>
|
|
ValueTask AddApplicationAsync(
|
|
NodeId roleId,
|
|
string applicationUri,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleType.RemoveApplication</c> per Part 18 §4.4.8.
|
|
/// </summary>
|
|
ValueTask RemoveApplicationAsync(
|
|
NodeId roleId,
|
|
string applicationUri,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleType.AddEndpoint</c> per Part 18 §4.4.9.
|
|
/// </summary>
|
|
ValueTask AddEndpointAsync(
|
|
NodeId roleId,
|
|
EndpointType endpoint,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Invokes <c>RoleType.RemoveEndpoint</c> per Part 18 §4.4.10.
|
|
/// </summary>
|
|
ValueTask RemoveEndpointAsync(
|
|
NodeId roleId,
|
|
EndpointType endpoint,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Writes the <c>ApplicationsExclude</c> property on a role.
|
|
/// </summary>
|
|
ValueTask SetApplicationsExcludeAsync(
|
|
NodeId roleId,
|
|
bool value,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Writes the <c>EndpointsExclude</c> property on a role.
|
|
/// </summary>
|
|
ValueTask SetEndpointsExcludeAsync(
|
|
NodeId roleId,
|
|
bool value,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Writes the <c>CustomConfiguration</c> property on a role.
|
|
/// </summary>
|
|
ValueTask SetCustomConfigurationAsync(
|
|
NodeId roleId,
|
|
bool value,
|
|
CancellationToken cancellationToken = default);
|
|
}
|
|
}
|