Add authentication and role-based write access control

Implements configurable user authentication (anonymous + username/password)
with pluggable credential provider (IUserAuthenticationProvider). Anonymous
writes can be disabled via AnonymousCanWrite setting while reads remain
open. Adds -U/-P flags to all CLI commands for authenticated sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-27 02:14:37 -04:00
parent b27d355763
commit bbd043e97b
24 changed files with 499 additions and 34 deletions

View File

@@ -21,6 +21,7 @@ configuration.GetSection("MxAccess").Bind(_config.MxAccess);
configuration.GetSection("GalaxyRepository").Bind(_config.GalaxyRepository);
configuration.GetSection("Dashboard").Bind(_config.Dashboard);
configuration.GetSection("Historian").Bind(_config.Historian);
configuration.GetSection("Authentication").Bind(_config.Authentication);
```
This pattern uses `IConfiguration.GetSection().Bind()` rather than `IOptions<T>` because the service targets .NET Framework 4.8, where the full dependency injection container is not used.
@@ -102,6 +103,33 @@ Controls the Wonderware Historian connection for OPC UA historical data access.
| `CommandTimeoutSeconds` | `int` | `30` | SQL command timeout for historian queries |
| `MaxValuesPerRead` | `int` | `10000` | Maximum values returned per `HistoryRead` request |
### Authentication
Controls user authentication and write authorization for the OPC UA server. Defined in `AuthenticationConfiguration`.
| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `AllowAnonymous` | `bool` | `true` | Accepts anonymous client connections when `true` |
| `AnonymousCanWrite` | `bool` | `true` | Permits anonymous users to write when `true` |
| `Users` | `List<UserCredential>` | `[]` | List of username/password credentials for `UserName` token authentication |
Each entry in the `Users` list has two properties: `Username` (string) and `Password` (string).
The defaults preserve the existing behavior: anonymous clients can connect, read, and write with no credentials required. To restrict writes to authenticated users, set `AnonymousCanWrite` to `false` and add entries to the `Users` list.
Example configuration:
```json
"Authentication": {
"AllowAnonymous": true,
"AnonymousCanWrite": false,
"Users": [
{ "Username": "operator", "Password": "op123" },
{ "Username": "engineer", "Password": "eng456" }
]
}
```
## Feature Flags
Three boolean properties act as feature flags that control optional subsystems:
@@ -177,6 +205,11 @@ Integration tests use this constructor to inject substitute implementations of `
"ConnectionString": "Server=localhost;Database=Runtime;Integrated Security=true;",
"CommandTimeoutSeconds": 30,
"MaxValuesPerRead": 10000
},
"Authentication": {
"AllowAnonymous": true,
"AnonymousCanWrite": true,
"Users": []
}
}
```