docs: add LmxProxy requirements documentation with v2 protocol as authoritative design
Generate high-level requirements and 10 component documents derived from source code and protocol specs. Uses lmxproxy_updates.md (v2 TypedValue/QualityCode) as the source of truth, with v1 string-based encoding documented as legacy context. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
119
lmxproxy/docs/requirements/Component-Security.md
Normal file
119
lmxproxy/docs/requirements/Component-Security.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# 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 `FileSystemWatcher` monitors the API key file for changes.
|
||||
- Rapid changes are debounced (1-second minimum between reloads).
|
||||
- `ReloadConfigurationAsync` uses a `SemaphoreSlim` to 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 the `ApiKey` object if the key exists and `Enabled` is 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:
|
||||
|
||||
1. Extracts the `x-api-key` header from gRPC request metadata.
|
||||
2. Calls `ApiKeyService.ValidateApiKey()`.
|
||||
3. If the key is invalid or missing, returns `StatusCode.Unauthenticated`.
|
||||
4. For write-protected methods (`Write`, `WriteBatch`, `WriteBatchAndWait`), checks that the key has the `ReadWrite` role. Returns `StatusCode.PermissionDenied` if the key is `ReadOnly`.
|
||||
5. Adds the validated `ApiKey` to `context.UserState["ApiKey"]` for downstream use.
|
||||
6. Continues to the service method.
|
||||
|
||||
### 2.2 Write-Protected Methods
|
||||
|
||||
These RPCs require the `ReadWrite` role:
|
||||
- `Write`
|
||||
- `WriteBatch`
|
||||
- `WriteBatchAndWait`
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user