/* ======================================================================== * 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; using System.Collections.Generic; using Opc.Ua.Security.Certificates; namespace Opc.Ua.Server { /// /// Server-side identity-mapping & role-configuration store for /// OPC UA Part 18 §4 (Role-Based Security). The default in-process /// implementation lives in ; integrators that /// want to back roles with a custom store (e.g. an LDAP directory or a /// database) implement this interface and inject an instance via /// . /// /// /// /// Implementations must be thread-safe; callers may invoke these members /// from multiple session threads concurrently. /// /// /// Every successful mutator raises /// so the can re-evaluate granted roles on /// active sessions per Part 18 §4.4.1. /// /// public interface IRoleManager { /// /// Raised after any successful mutation. Re-entrant: handlers must not /// call back into the manager on the same thread. /// event EventHandler? RoleConfigurationChanged; /// /// NodeIds of every role currently tracked by the manager. /// IReadOnlyList RoleIds { get; } /// /// Returns an immutable snapshot of the role's configuration, or /// null if no role with the supplied NodeId is registered. /// RoleEntry? GetRole(NodeId roleId); /// /// Adds an identity-mapping rule per Part 18 §4.4.5. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved (Anonymous, /// AuthenticatedUser, TrustedApplication); /// Bad_InvalidArgument if the rule is malformed; /// Bad_AlreadyExists if an equivalent rule already exists. /// ServiceResult AddIdentity(NodeId roleId, IdentityMappingRuleType rule); /// /// Removes a previously added identity-mapping rule per Part 18 §4.4.6. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved; /// Bad_NotFound if the rule is not present. /// ServiceResult RemoveIdentity(NodeId roleId, IdentityMappingRuleType rule); /// /// Adds an application URI per Part 18 §4.4.7. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved; /// Bad_InvalidArgument if the URI is empty; /// Bad_AlreadyExists if the URI is already assigned. /// ServiceResult AddApplication(NodeId roleId, string applicationUri); /// /// Removes a previously added application URI per Part 18 §4.4.8. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved; /// Bad_NotFound if the URI is not present. /// ServiceResult RemoveApplication(NodeId roleId, string applicationUri); /// /// Adds an endpoint per Part 18 §4.4.9. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved; /// Bad_InvalidArgument if the endpoint is null or its URL is empty; /// Bad_AlreadyExists if an equivalent endpoint already exists. /// ServiceResult AddEndpoint(NodeId roleId, EndpointType endpoint); /// /// Removes a previously added endpoint per Part 18 §4.4.10. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved; /// Bad_NotFound if no equivalent endpoint is present. /// ServiceResult RemoveEndpoint(NodeId roleId, EndpointType endpoint); /// /// Updates the ApplicationsExclude flag. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved. /// ServiceResult SetApplicationsExclude(NodeId roleId, bool value); /// /// Updates the EndpointsExclude flag. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved. /// ServiceResult SetEndpointsExclude(NodeId roleId, bool value); /// /// Updates the CustomConfiguration flag (Part 18 §4.4.1). /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved. /// ServiceResult SetCustomConfiguration(NodeId roleId, bool value); /// /// Adds a new role per Part 18 §4.2.2. If the /// is the OPC UA URI (or empty) and /// the matches a well-known role /// (Part 3 §4.9.2), the spec-defined well-known NodeId is reused. /// Otherwise a fresh NodeId is allocated in . /// /// The browse name for the new role. /// /// The namespace URI qualifying the browse name; if null or empty the /// server's default namespace is used. /// /// Namespace table used to resolve the URI. /// Namespace index used when a fresh NodeId is allocated. /// On success, the new role's NodeId. /// /// Good on success; /// Bad_InvalidArgument if is empty; /// Bad_AlreadyExists if a role with the same browse name already exists. /// ServiceResult AddRole( string roleName, string? namespaceUri, NamespaceTable namespaces, ushort defaultNamespaceIndex, out NodeId newRoleId); /// /// Removes a role per Part 18 §4.2.3. /// /// /// Good on success; /// Bad_NodeIdUnknown if the role is unknown; /// Bad_RequestNotAllowed if the role is reserved /// (Anonymous, AuthenticatedUser, TrustedApplication). /// ServiceResult RemoveRole(NodeId roleId); /// /// Computes the set of roles to grant a session given its /// authenticated identity, client certificate, and endpoint per /// Part 18 §4.4.1. /// /// The authenticated user identity. Must be non-null. /// /// The client's ApplicationInstance certificate, if a secure channel /// was negotiated. Used to evaluate Application, /// TrustedApplication, X509Subject and the /// Applications filter. /// /// /// The endpoint used by the session. Used to evaluate the /// Endpoints filter and the "at least signed channel" /// requirement for Application / TrustedApplication rules. /// /// The set of granted role NodeIds. IList ResolveGrantedRoles( IUserIdentity identity, Certificate? clientCertificate, EndpointDescription? endpoint); } }