docs: add mqtt connection type design
This commit is contained in:
93
docs/plans/2026-02-23-mqtt-connection-type-design.md
Normal file
93
docs/plans/2026-02-23-mqtt-connection-type-design.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# MQTT Connection Type Port Design
|
||||
|
||||
## Goal
|
||||
Port MQTT-related connection type parity from Go into the .NET server for two scoped areas:
|
||||
1. JWT `allowed_connection_types` behavior for `MQTT` / `MQTT_WS` (plus existing known types).
|
||||
2. `/connz` filtering by `mqtt_client`.
|
||||
|
||||
## Scope
|
||||
- In scope:
|
||||
- JWT allowed connection type normalization and enforcement semantics.
|
||||
- `/connz?mqtt_client=` option parsing and filtering.
|
||||
- Unit/integration tests for new and updated behavior.
|
||||
- `differences.md` updates after implementation is verified.
|
||||
- Out of scope:
|
||||
- Full MQTT transport implementation.
|
||||
- WebSocket transport implementation.
|
||||
- Leaf/route/gateway transport plumbing.
|
||||
|
||||
## Architecture
|
||||
- Add an auth-facing connection-type model that can be passed through `ClientAuthContext`.
|
||||
- Implement Go-style allowed connection type conversion and matching in `JwtAuthenticator`:
|
||||
- normalize input to uppercase.
|
||||
- retain recognized types.
|
||||
- collect unknown types as non-fatal if at least one valid type remains.
|
||||
- reject when only unknown types are present.
|
||||
- enforce current connection type against the resulting allowed set.
|
||||
- Extend connz monitoring options to parse `mqtt_client` and apply exact-match filtering before sort/pagination.
|
||||
|
||||
## Components
|
||||
- `src/NATS.Server/Auth/IAuthenticator.cs`
|
||||
- Extend `ClientAuthContext` with a connection-type value.
|
||||
- `src/NATS.Server/Auth/Jwt/JwtConnectionTypes.cs` (new)
|
||||
- Canonical constants for known connection types:
|
||||
- `STANDARD`, `WEBSOCKET`, `LEAFNODE`, `LEAFNODE_WS`, `MQTT`, `MQTT_WS`, `INPROCESS`.
|
||||
- Helper(s) for normalization and validation behavior.
|
||||
- `src/NATS.Server/Auth/JwtAuthenticator.cs`
|
||||
- Evaluate `userClaims.Nats?.AllowedConnectionTypes` using Go-compatible semantics.
|
||||
- Enforce against current `ClientAuthContext.ConnectionType`.
|
||||
- `src/NATS.Server/NatsClient.cs`
|
||||
- Populate auth context connection type (currently `STANDARD`).
|
||||
- `src/NATS.Server/Monitoring/Connz.cs`
|
||||
- Add `MqttClient` to `ConnzOptions` with JSON field `mqtt_client`.
|
||||
- `src/NATS.Server/Monitoring/ConnzHandler.cs`
|
||||
- Parse `mqtt_client` query param.
|
||||
- Filter connection list by exact `MqttClient` match when provided.
|
||||
- `src/NATS.Server/Monitoring/ClosedClient.cs`
|
||||
- Add `MqttClient` field to closed snapshots.
|
||||
- `src/NATS.Server/NatsServer.cs`
|
||||
- Persist `MqttClient` into `ClosedClient` snapshot (empty for now).
|
||||
|
||||
## Data Flow
|
||||
1. Client sends `CONNECT`.
|
||||
2. `NatsClient.ProcessConnectAsync` builds `ClientAuthContext` with `ConnectionType=STANDARD`.
|
||||
3. `AuthService` invokes `JwtAuthenticator` for JWT-based auth.
|
||||
4. `JwtAuthenticator`:
|
||||
- converts `allowed_connection_types` to valid/unknown buckets.
|
||||
- rejects unknown-only lists.
|
||||
- enforces connection-type membership when valid list is non-empty.
|
||||
5. Monitoring request `/connz`:
|
||||
- `ConnzHandler.ParseQueryParams` reads `mqtt_client`.
|
||||
- open/closed conn rows are materialized.
|
||||
- rows are filtered on exact `MqttClient` when filter is present.
|
||||
- sorting and pagination run on filtered results.
|
||||
|
||||
## Error Handling and Compatibility
|
||||
- Auth failures remain non-throwing (`Authenticate` returns `null`).
|
||||
- Unknown connection type tokens in JWT are tolerated only when at least one known allowed type remains.
|
||||
- Unknown-only allowed lists are rejected to avoid unintended allow-all behavior.
|
||||
- `mqtt_client` query parsing is lenient and string-based; empty filter means no filter.
|
||||
- Existing JSON schema compatibility is preserved.
|
||||
|
||||
## Current Runtime Limitation (Explicit)
|
||||
- MQTT transport is not implemented yet in this repository.
|
||||
- Runtime connection type currently resolves to `STANDARD` in auth context.
|
||||
- `mqtt_client` values remain empty until MQTT path populates them.
|
||||
|
||||
## Testing Strategy
|
||||
- `tests/NATS.Server.Tests/JwtAuthenticatorTests.cs`
|
||||
- allow `STANDARD` for current client context.
|
||||
- reject `MQTT` for current client context.
|
||||
- allow mixed known+unknown when current type is known allowed.
|
||||
- reject unknown-only list.
|
||||
- validate case normalization behavior.
|
||||
- `tests/NATS.Server.Tests/MonitorTests.cs`
|
||||
- `/connz?mqtt_client=<id>` returns matching connections only.
|
||||
- `/connz?state=closed&mqtt_client=<id>` filters closed snapshots.
|
||||
- non-existing ID yields empty connection set.
|
||||
|
||||
## Success Criteria
|
||||
- JWT `allowed_connection_types` behavior matches Go semantics for known/unknown mixing and unknown-only rejection.
|
||||
- `/connz` supports exact `mqtt_client` filtering for open and closed sets.
|
||||
- Added tests pass.
|
||||
- `differences.md` accurately reflects implemented parity.
|
||||
Reference in New Issue
Block a user