// This example shows how to create a hierarchical permission assignment in an OPC UA server, for Anonymous, Engineer and
// Operator roles.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server.
//
// Find all latest examples here: https://www.doc-that.com/files/onlinedocs/OPCLabs-ConnectivityStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-ConnectivityStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://forum.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.
using OpcLabs.BaseLib.Security.User.Extensions;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.NodeSpace;
using OpcLabs.EasyOpc.UA.Security.Subject;
using System;
namespace UAServerDocExamples.AccessControl
{
internal class PermissionAssignment
{
public static void Hierarchical()
{
// Instantiate the server object.
// By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
var server = new EasyUAServer();
// Clear the default security roles (Operator) for the Anonymous user.
server.UserManagers.Anonymous.SecurityRoleIdSet.Clear();
// Create users with Engineer and Operator roles.
server.UserManagers.NameAndPassword.CreateWithSecurityRoleIds("engineer", "pass",
new string[] {UASecurityRoles.Engineer});
server.UserManagers.NameAndPassword.CreateWithSecurityRoleIds("operator", "pass",
new string[] {UASecurityRoles.Operator});
// Specify the default permission assignment for the custom nodes under Objects folder. Anonymous users will be
// able to view only, authenticated users will be also able to modify.
server.ObjectsNamespaceDefaultPermissionAssignment = UAPermissionAssignment.AuthenticateUserToModify;
// Define some nodes with different permission assignments.
// This data variable is readable by anyone, but only writable by authenticated users, because it inherits
// permission assignments from the Objects folder, which further inherits them from the namespace.
server.Objects.Add(new UADataVariable("PublicReadableDataVariable").ReadWriteValue(0));
// This data variable will be readable and writable by anyone. It inherits the read permissions for anyone from
// the Objects folder, and it adds its own permission assignment for write permissions.
var publicReadWriteDataVariable = new UADataVariable("PublicReadWriteDataVariable").ReadWriteValue(0);
publicReadWriteDataVariable.PermissionAssignment = new UAPermissionAssignment
{
new UARolePermissions(UASecurityRoles.Anonymous, UAPermissions.ModifyBasic)
};
server.Objects.Add(publicReadWriteDataVariable);
// This data variable will only be accessible to authenticated users. Other users will not even be able to see
// it (browse for it). We specify that it should not inherit permissions from the namespace, but instead have
// its own permission assignment.
var authenticatedDataVariable = new UADataVariable("AuthenticatedDataVariable").ReadWriteValue(0);
authenticatedDataVariable.PermissionAssignment = new UAPermissionAssignment
{
new UARolePermissions(UASecurityRoles.AuthenticatedUser, UAPermissions.ViewBasic | UAPermissions.ModifyBasic)
};
authenticatedDataVariable.PermissionsInheritanceType = UAPermissionsInheritanceType.None;
server.Objects.Add(authenticatedDataVariable);
// This folder will only be accessible to users with Operator or Engineer security roles. User that do not have
// any of these security roles will not even be able to see it (browse for it).
var operatorOrEngineerFolder = new UAFolder("OperatorOrEngineerFolder");
operatorOrEngineerFolder.PermissionAssignment = new UAPermissionAssignment
{
new UARolePermissions(UASecurityRoles.Operator, UAPermissions.ViewBasic | UAPermissions.ModifyBasic),
new UARolePermissions(UASecurityRoles.Engineer, UAPermissions.ViewBasic | UAPermissions.ModifyBasic),
};
operatorOrEngineerFolder.PermissionsInheritanceType = UAPermissionsInheritanceType.None;
server.Objects.Add(operatorOrEngineerFolder);
// This data variable will inherit permissions from the OperatorOrEngineerFolder, so it will only be accessible to users
// with Operator or Engineer security roles.
var operatorOrEngineerDataVariable = new UADataVariable("OperatorOrEngineerDataVariable").ReadWriteValue(0);
operatorOrEngineerFolder.Add(operatorOrEngineerDataVariable);
// A data variable accessible to Operator but not Engineer (typically, live data).
var operatorDataVariable = new UADataVariable("OperatorDataVariable").ReadWriteValue(0);
operatorDataVariable.PermissionAssignment = new UAPermissionAssignment
{
new UARolePermissions(UASecurityRoles.Operator, UAPermissions.ViewBasic | UAPermissions.ModifyBasic),
};
operatorDataVariable.PermissionsInheritanceType = UAPermissionsInheritanceType.None;
operatorOrEngineerFolder.Add(operatorDataVariable);
// A data variable accessible to Engineer but not Operator (typically, configuration data).
var engineerDataVariable = new UADataVariable("EngineerDataVariable").ReadWriteValue(0);
engineerDataVariable.PermissionAssignment = new UAPermissionAssignment
{
new UARolePermissions(UASecurityRoles.Engineer, UAPermissions.ViewBasic | UAPermissions.ModifyBasic),
};
engineerDataVariable.PermissionsInheritanceType = UAPermissionsInheritanceType.None;
operatorOrEngineerFolder.Add(engineerDataVariable);
// Start the server.
Console.WriteLine("The server is starting...");
server.Start();
Console.WriteLine("The server is started.");
Console.WriteLine();
// Let the user decide when to stop.
Console.WriteLine("Press Enter to stop the server...");
Console.ReadLine();
// Stop the server.
Console.WriteLine("The server is stopping...");
server.Stop();
Console.WriteLine("The server is stopped.");
}
}
}