LmxProxy is no longer needed. Moved the entire lmxproxy/ workspace, DCL adapter files, and related docs to deprecated/. Removed LmxProxy registration from DataConnectionFactory, project reference from DCL, protocol option from UI, and cleaned up all requirement docs.
5.1 KiB
5.1 KiB
Component: Security
Purpose
Provides API key-based authentication and role-based authorization for the gRPC service, along with TLS certificate management for transport security.
Location
src/ZB.MOM.WW.LmxProxy.Host/Security/ApiKeyService.cs— API key storage and validation.src/ZB.MOM.WW.LmxProxy.Host/Security/ApiKeyInterceptor.cs— gRPC server interceptor for authentication/authorization.src/ZB.MOM.WW.LmxProxy.Client/Security/GrpcChannelFactory.cs— Client-side TLS channel factory.
Responsibilities
- Load and hot-reload API keys from a JSON configuration file.
- Validate API keys on every gRPC request via a server interceptor.
- Enforce role-based access control (ReadOnly vs ReadWrite).
- Manage TLS certificates for server and optional mutual TLS.
1. API Key Service
1.1 Key Storage
- Keys are stored in a JSON file (default
apikeys.json). - File format:
{ "ApiKeys": [{ "Key": "...", "Description": "...", "Role": "ReadOnly|ReadWrite", "Enabled": true|false }] }. - If the file does not exist at startup, the service auto-generates a default file with two random keys: one ReadOnly and one ReadWrite.
1.2 Hot Reload
- A
FileSystemWatchermonitors the API key file for changes. - Rapid changes are debounced (1-second minimum between reloads).
ReloadConfigurationAsyncuses aSemaphoreSlimto serialize reload operations.- New and modified keys take effect on the next request. Removed or disabled keys reject future requests immediately.
- Active sessions are not affected by key changes — sessions are tracked independently by SessionManager.
1.3 Validation
ValidateApiKey(apiKey)— Returns theApiKeyobject if the key exists andEnabledis true, otherwise null.HasRole(apiKey, requiredRole)— Returns true if the key has the required role. Role hierarchy: ReadWrite implies ReadOnly.
2. API Key Interceptor
2.1 Authentication Flow
The ApiKeyInterceptor intercepts every unary and server-streaming RPC:
- Extracts the
x-api-keyheader from gRPC request metadata. - Calls
ApiKeyService.ValidateApiKey(). - If the key is invalid or missing, returns
StatusCode.Unauthenticated. - For write-protected methods (
Write,WriteBatch,WriteBatchAndWait), checks that the key has theReadWriterole. ReturnsStatusCode.PermissionDeniedif the key isReadOnly. - Adds the validated
ApiKeytocontext.UserState["ApiKey"]for downstream use. - Continues to the service method.
2.2 Write-Protected Methods
These RPCs require the ReadWrite role:
WriteWriteBatchWriteBatchAndWait
All other RPCs (Connect, Disconnect, GetConnectionState, Read, ReadBatch, Subscribe, CheckApiKey) are allowed for ReadOnly keys.
3. API Key Model
| Field | Type | Description |
|---|---|---|
| Key | string | The secret API key value |
| Description | string | Human-readable name for the key |
| Role | ApiKeyRole | ReadOnly or ReadWrite |
| Enabled | bool | Whether the key is active |
ApiKeyRole enum: ReadOnly (read and subscribe only), ReadWrite (full access including writes).
4. TLS Configuration
4.1 Server-Side (Host)
Configured via TlsConfiguration in appsettings.json:
| Setting | Default | Description |
|---|---|---|
| Enabled | false | Enable TLS on the gRPC server |
| ServerCertificatePath | certs/server.crt |
PEM server certificate |
| ServerKeyPath | certs/server.key |
PEM server private key |
| ClientCaCertificatePath | certs/ca.crt |
CA certificate for mTLS client validation |
| RequireClientCertificate | false | Require client certificates (mutual TLS) |
| CheckCertificateRevocation | false | Check certificate revocation lists |
If TLS is enabled but certificates are missing, the service generates self-signed certificates at startup.
4.2 Client-Side
ClientTlsConfiguration in the client library:
| Setting | Default | Description |
|---|---|---|
| UseTls | false | Enable TLS on the client connection |
| ClientCertificatePath | null | Client certificate for mTLS |
| ClientKeyPath | null | Client private key for mTLS |
| ServerCaCertificatePath | null | Custom CA for server validation |
| ServerNameOverride | null | SNI/hostname override |
| ValidateServerCertificate | true | Validate the server certificate chain |
| AllowSelfSignedCertificates | false | Accept self-signed server certificates |
| IgnoreAllCertificateErrors | false | Skip all certificate validation (dangerous) |
- SSL protocols: TLS 1.2 and TLS 1.3.
- Client certificates loaded from PEM files and converted to PKCS12.
- Custom CA trust store support via chain building.
Dependencies
- Configuration — TLS settings and API key file path from
appsettings.json. - System.IO.FileSystemWatcher — API key file change detection.
Interactions
- GrpcServer — the ApiKeyInterceptor runs before every RPC in ScadaGrpcService.
- ServiceHost — creates ApiKeyService and ApiKeyInterceptor at startup, configures gRPC server credentials.
- Client — GrpcChannelFactory creates TLS-configured gRPC channels in LmxProxyClient.