- Remove ConfigUserAuthenticationProvider and Users property — LDAP is the only auth mechanism - Fix historian quality mapping to use existing QualityMapper (OPC DA quality bytes, not custom mapping) - Add AppRoles constants, unify HasWritePermission/HasAlarmAckPermission into shared HasRole helper - Hoist write permission check out of per-item loop, eliminate redundant _ldapRolesEnabled field - Update docs (Configuration.md, Security.md, OpcUaServer.md, HistoricalDataAccess.md) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
7.7 KiB
OPC UA Server
The OPC UA server component hosts the Galaxy-backed namespace on a configurable TCP endpoint and exposes deployed System Platform objects and attributes to OPC UA clients.
Configuration
OpcUaConfiguration defines the server endpoint and session settings. All properties have sensible defaults:
| Property | Default | Description |
|---|---|---|
BindAddress |
0.0.0.0 |
IP address or hostname the server binds to |
Port |
4840 |
TCP port the server listens on |
EndpointPath |
/LmxOpcUa |
URI path appended to the base address |
ServerName |
LmxOpcUa |
Application name presented to clients |
GalaxyName |
ZB |
Galaxy name used in the namespace URI |
MaxSessions |
100 |
Maximum concurrent client sessions |
SessionTimeoutMinutes |
30 |
Idle session timeout |
AlarmTrackingEnabled |
false |
Enables AlarmConditionState nodes for alarm attributes |
The resulting endpoint URL is opc.tcp://{BindAddress}:{Port}{EndpointPath}, e.g., opc.tcp://0.0.0.0:4840/LmxOpcUa.
The namespace URI follows the pattern urn:{GalaxyName}:LmxOpcUa and is used as the ProductUri. The ApplicationUri can be set independently via OpcUa.ApplicationUri to support redundant deployments where each instance needs a unique identity. When ApplicationUri is null, it defaults to the namespace URI.
Programmatic ApplicationConfiguration
OpcUaServerHost builds the entire ApplicationConfiguration in code. There are no XML configuration files. This keeps deployment simple on factory floor machines where editing XML is error-prone.
The configuration covers:
- ServerConfiguration -- base address, session limits, security policies, and user token policies
- SecurityConfiguration -- certificate store paths under
%LOCALAPPDATA%\OPC Foundation\pki\, auto-accept enabled - TransportQuotas -- 4 MB max message/string/byte-string size, 120-second operation timeout, 1-hour security token lifetime
- TraceConfiguration -- OPC Foundation SDK tracing is disabled (output path
null, trace masks0); all logging goes through Serilog instead
Security Profiles
The server supports configurable transport security profiles controlled by the Security section in appsettings.json. The default configuration exposes only MessageSecurityMode.None for backward compatibility.
Supported Phase 1 profiles:
| Profile Name | SecurityPolicy URI | MessageSecurityMode |
|---|---|---|
None |
SecurityPolicy#None |
None |
Basic256Sha256-Sign |
SecurityPolicy#Basic256Sha256 |
Sign |
Basic256Sha256-SignAndEncrypt |
SecurityPolicy#Basic256Sha256 |
SignAndEncrypt |
SecurityProfileResolver maps configured profile names to ServerSecurityPolicy instances at startup. Unknown names are skipped with a warning, and an empty or invalid list falls back to None.
For production deployments, configure ["Basic256Sha256-SignAndEncrypt"] or ["None", "Basic256Sha256-SignAndEncrypt"] and set AutoAcceptClientCertificates to false. See the Security Guide for hardening details.
Redundancy
When Redundancy.Enabled = true, LmxOpcUaServer exposes the standard OPC UA redundancy nodes on startup:
Server/ServerRedundancy/RedundancySupport— set toWarmorHotbased on configurationServer/ServerRedundancy/ServerUriArray— populated with the configuredServerUrisServer/ServiceLevel— computed dynamically from role and runtime health
The ServiceLevel is updated whenever MXAccess connection state changes or Galaxy DB health changes. See Redundancy Guide for full details.
User token policies
UserTokenPolicies are dynamically configured based on the Authentication settings in appsettings.json:
- An
Anonymoususer token policy is added whenAllowAnonymousistrue(the default). - A
UserNameuser token policy is added whenLdap.Enabledistrue.
Both policies can be active simultaneously, allowing clients to connect with or without credentials.
Session impersonation
When a client presents UserName credentials, the server validates them through IUserAuthenticationProvider. If LDAP authentication is enabled, credentials are validated via LDAP bind and group membership determines the user's application-level roles (ReadOnly, ReadWrite, AlarmAck). If validation fails, the session is rejected.
On successful validation, the session identity is set to a RoleBasedIdentity that carries the user's granted role IDs. Authenticated users receive the WellKnownRole_AuthenticatedUser role. Anonymous connections receive the WellKnownRole_Anonymous role. When LDAP is enabled, application-level roles from group membership control write and alarm-ack permissions. Without LDAP, AnonymousCanWrite controls whether anonymous users can write.
Certificate handling
On startup, OpcUaServerHost.StartAsync calls CheckApplicationInstanceCertificate(false, minKeySize) to locate or create a self-signed certificate meeting the configured minimum key size (default 2048). The certificate subject defaults to CN={ServerName}, O=ZB MOM, DC=localhost but can be overridden via Security.CertificateSubject. Certificate stores use the directory-based store type under the configured Security.PkiRootPath (default %LOCALAPPDATA%\OPC Foundation\pki\):
| Store | Path suffix |
|---|---|
| Own | pki/own |
| Trusted issuers | pki/issuer |
| Trusted peers | pki/trusted |
| Rejected | pki/rejected |
AutoAcceptUntrustedCertificates is controlled by Security.AutoAcceptClientCertificates (default true). Set to false in production to enforce client certificate trust. When RejectSHA1Certificates is true (default), client certificates signed with SHA-1 are rejected. Certificate validation events are logged for visibility into accepted and rejected client connections.
Server class hierarchy
LmxOpcUaServer extends StandardServer
LmxOpcUaServer inherits from the OPC Foundation StandardServer base class and overrides two methods:
CreateMasterNodeManager-- InstantiatesLmxNodeManagerwith the Galaxy namespace URI, theIMxAccessClientfor runtime I/O, performance metrics, and an optionalHistorianDataSource. The node manager is wrapped in aMasterNodeManagerwith no additional core node managers.LoadServerProperties-- Returns server metadata: manufacturerZB MOM, productLmxOpcUa Server, and the assembly version as the software version.
Session tracking
LmxOpcUaServer exposes ActiveSessionCount by querying ServerInternal.SessionManager.GetSessions().Count. OpcUaServerHost surfaces this for status reporting.
Startup and Shutdown
OpcUaServerHost.StartAsync performs the following sequence:
- Build
ApplicationConfigurationprogrammatically - Validate the configuration via
appConfig.Validate(ApplicationType.Server) - Create
ApplicationInstanceand check/create the application certificate - Instantiate
LmxOpcUaServerand start it viaApplicationInstance.Start
OpcUaServerHost.Stop calls _server.Stop() and nulls both the server and application instance references. The class implements IDisposable, delegating to Stop.
Key source files
src/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/OpcUaServerHost.cs-- Application lifecycle and programmatic configurationsrc/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/LmxOpcUaServer.cs-- StandardServer subclass and node manager creationsrc/ZB.MOM.WW.LmxOpcUa.Host/OpcUa/SecurityProfileResolver.cs-- Profile-name to ServerSecurityPolicy mappingsrc/ZB.MOM.WW.LmxOpcUa.Host/Configuration/OpcUaConfiguration.cs-- Configuration POCOsrc/ZB.MOM.WW.LmxOpcUa.Host/Configuration/SecurityProfileConfiguration.cs-- Security configuration POCO