docs: TLS auto-cert and lenient client trust
This commit is contained in:
@@ -107,6 +107,7 @@ public sealed class MxGatewayClientOptions
|
||||
public required string ApiKey { get; init; }
|
||||
public bool UseTls { get; init; }
|
||||
public string? CaCertificatePath { get; init; }
|
||||
public bool RequireCertificateValidation { get; init; }
|
||||
public string? ServerNameOverride { get; init; }
|
||||
public TimeSpan ConnectTimeout { get; init; } = TimeSpan.FromSeconds(10);
|
||||
public TimeSpan DefaultCallTimeout { get; init; } = TimeSpan.FromSeconds(30);
|
||||
@@ -124,6 +125,24 @@ or subscription changes because those calls can partially succeed in MXAccess.
|
||||
API key may be loaded from `MXGATEWAY_API_KEY` by the CLI, not implicitly by the
|
||||
library constructor unless a helper explicitly says it does that.
|
||||
|
||||
### TLS trust posture
|
||||
|
||||
The gateway can serve a self-signed certificate it generates itself (it has no
|
||||
PKI). To make that usable, TLS is **lenient by default**: when `UseTls` is set
|
||||
and `CaCertificatePath` is empty, `CreateHttpHandler` installs a
|
||||
`RemoteCertificateValidationCallback` that returns `true`, so the gateway's
|
||||
self-signed certificate is accepted without verification.
|
||||
|
||||
To verify the gateway instead:
|
||||
|
||||
- set `CaCertificatePath` to pin a CA — validated via a `CustomRootTrust`
|
||||
`X509Chain` against that root, and the callback additionally rejects a
|
||||
hostname/SAN mismatch (`RemoteCertificateNameMismatch`); or
|
||||
- set `RequireCertificateValidation` to `true` to keep the default OS/system-trust
|
||||
verification on a connection with no pinned CA.
|
||||
|
||||
Pinning a CA always wins over the lenient default.
|
||||
|
||||
## Auth Interceptor
|
||||
|
||||
Use a gRPC call credentials/interceptor layer to attach:
|
||||
|
||||
@@ -287,6 +287,17 @@ Use TLS options for a secured gateway:
|
||||
dotnet run --project clients/dotnet/ZB.MOM.WW.MxGateway.Client.Cli -- smoke --endpoint https://ZB.MOM.WW.MxGateway.example.local:5001 --tls --ca-file C:\certs\mxgateway-ca.pem --server-name ZB.MOM.WW.MxGateway.example.local --api-key-env MXGATEWAY_API_KEY --item Area001.Pump001.Speed --json
|
||||
```
|
||||
|
||||
### TLS trust
|
||||
|
||||
The gateway can auto-generate its own self-signed certificate (it has no PKI), so
|
||||
the client is **lenient by default**: a TLS connection (`UseTls` / `--tls`) with
|
||||
no pinned CA accepts whatever certificate the gateway presents. To verify
|
||||
instead, pin a CA with `CaCertificatePath` / `--ca-file` (this path also enforces
|
||||
the certificate hostname/SAN match), or set `RequireCertificateValidation` to
|
||||
force OS/system-trust verification without pinning. Use `ServerNameOverride` /
|
||||
`--server-name` when the dialed host differs from the certificate SAN. See
|
||||
[Gateway Configuration](../../docs/GatewayConfiguration.md#automatic-self-signed-certificate).
|
||||
|
||||
## Integration Checks
|
||||
|
||||
Run live checks only when a gateway and MXAccess-backed worker are available:
|
||||
|
||||
@@ -104,6 +104,23 @@ Support:
|
||||
- `credentials.NewClientTLSFromFile`,
|
||||
- custom `tls.Config` for advanced callers.
|
||||
|
||||
### Trust posture
|
||||
|
||||
The gateway can serve a self-signed certificate it generates itself (it has no
|
||||
PKI). To make that usable, TLS is **lenient by default**: when `Plaintext` is
|
||||
`false` and no `CACertFile`/`TLSConfig`/`TransportCredentials` is supplied,
|
||||
`buildCredentials` dials with `tls.Config{InsecureSkipVerify: true}` (carrying
|
||||
`ServerNameOverride` as the SNI when set), so the gateway's self-signed
|
||||
certificate is accepted without verification.
|
||||
|
||||
To verify the gateway instead:
|
||||
|
||||
- set `CACertFile` to pin a CA (full verification against that root), or
|
||||
- set `RequireCertificateValidation: true` to verify against the OS/system trust
|
||||
roots without pinning.
|
||||
|
||||
Pinning a CA always wins over the lenient default.
|
||||
|
||||
## Streaming
|
||||
|
||||
`Events(ctx)` should return a receive channel of:
|
||||
|
||||
@@ -75,6 +75,14 @@ client, err := mxgateway.Dial(ctx, mxgateway.Options{
|
||||
})
|
||||
```
|
||||
|
||||
The gateway can auto-generate its own self-signed certificate (it has no PKI), so
|
||||
the client is **lenient by default**: a TLS connection (`Plaintext: false`) with
|
||||
no `CACertFile`/`TLSConfig` accepts whatever certificate the gateway presents
|
||||
(`InsecureSkipVerify`, with `ServerNameOverride` as the SNI when set). To verify
|
||||
instead, set `CACertFile` to pin a CA, or set `RequireCertificateValidation:
|
||||
true` to verify against the OS/system trust roots without pinning. See
|
||||
[Gateway Configuration](../../docs/GatewayConfiguration.md#automatic-self-signed-certificate).
|
||||
|
||||
`Client.OpenSession` returns a `Session` with helpers for `Register`,
|
||||
`AddItem`, `AddItem2`, `Advise`, `Write`, `Events`, and `Close`. Prefer
|
||||
`SubscribeEvents` or `SubscribeEventsAfter` for long-running streams because the
|
||||
|
||||
@@ -112,6 +112,23 @@ Support:
|
||||
- custom CA certificate file,
|
||||
- server name override for test environments.
|
||||
|
||||
### Trust posture
|
||||
|
||||
The gateway can serve a self-signed certificate it generates itself (it has no
|
||||
PKI). To make that usable, TLS is **lenient by default**: when the channel is not
|
||||
plaintext and no `caCertificatePath` is set, the client builds
|
||||
`GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)`
|
||||
(grpc-netty-shaded), so the gateway's self-signed certificate is accepted without
|
||||
verification.
|
||||
|
||||
To verify the gateway instead:
|
||||
|
||||
- set `caCertificatePath` to pin a CA (full verification against that root), or
|
||||
- set `requireCertificateValidation` to `true` to verify against the JVM trust
|
||||
store without pinning.
|
||||
|
||||
Pinning a CA always wins over the lenient default.
|
||||
|
||||
## Streaming
|
||||
|
||||
Support both:
|
||||
|
||||
@@ -57,6 +57,16 @@ try (MxGatewayClient client = MxGatewayClient.connect(options);
|
||||
}
|
||||
```
|
||||
|
||||
The gateway can auto-generate its own self-signed certificate (it has no PKI), so
|
||||
the client is **lenient by default**: a TLS connection (`plaintext(false)`) with
|
||||
no `caCertificatePath` accepts whatever certificate the gateway presents (via
|
||||
grpc-netty-shaded's `InsecureTrustManagerFactory`). To verify instead, set
|
||||
`caCertificatePath` to pin a CA, or set `requireCertificateValidation(true)` to
|
||||
verify against the JVM trust store without pinning. Use `serverNameOverride` /
|
||||
`--server-name-override` when the dialed host differs from the certificate SAN.
|
||||
See
|
||||
[Gateway Configuration](../../docs/GatewayConfiguration.md#automatic-self-signed-certificate).
|
||||
|
||||
Use `rawBlockingStub`, `rawFutureStub`, `rawAsyncStub`, `openSessionRaw`,
|
||||
`closeSessionRaw`, `invoke`, and raw session helper methods when tests need the
|
||||
underlying protobuf messages. `MxGatewayCommandException` and
|
||||
|
||||
@@ -112,6 +112,28 @@ Support:
|
||||
- TLS channel with default roots,
|
||||
- custom root certificate file.
|
||||
|
||||
### Trust posture (trust-on-first-use)
|
||||
|
||||
The gateway can serve a self-signed certificate it generates itself (it has no
|
||||
PKI). grpc-python exposes no per-channel skip-verify hook, so the client cannot
|
||||
"accept any certificate" the way the other clients do. Instead, when the channel
|
||||
is not plaintext and neither `ca_file` nor `require_certificate_validation` is
|
||||
set, the TLS default is **trust-on-first-use**: the client fetches the server's
|
||||
presented certificate once via `ssl.get_server_certificate` (an unverified
|
||||
probe), pins it as the channel's only trust root, and — because the generated
|
||||
certificate always carries a `localhost` SAN — defaults
|
||||
`grpc.ssl_target_name_override` to `localhost` when no `server_name_override` was
|
||||
supplied (tolerating dial-by-IP or a hostname mismatch). A failed probe is
|
||||
surfaced as a transport error naming the endpoint.
|
||||
|
||||
To verify the gateway instead:
|
||||
|
||||
- set `ca_file` to verify against a specific CA, or
|
||||
- set `require_certificate_validation=True` to verify against the system trust
|
||||
roots.
|
||||
|
||||
Both bypass the TOFU path.
|
||||
|
||||
## Streaming
|
||||
|
||||
Expose `stream_events` as an async iterator. Canceling the task should cancel
|
||||
|
||||
@@ -230,6 +230,17 @@ The client supports plaintext channels for local development, TLS with system
|
||||
roots, TLS with a custom `ca_file`, and an optional test server name override.
|
||||
API keys are redacted from option repr output and CLI error output.
|
||||
|
||||
The gateway can auto-generate its own self-signed certificate (it has no PKI).
|
||||
grpc-python has no per-channel skip-verify, so the lenient TLS default is
|
||||
**trust-on-first-use**: with no `ca_file` and `require_certificate_validation`
|
||||
left `False`, the client fetches the gateway's presented certificate once
|
||||
(unverified) and pins it for the channel, defaulting the SNI/target-name override
|
||||
to `localhost` (the generated certificate always carries a `localhost` SAN) when
|
||||
none was supplied. To verify instead, pass `ca_file` to verify against a specific
|
||||
CA, or set `require_certificate_validation=True` to verify against the system
|
||||
trust roots. See
|
||||
[Gateway Configuration](../../docs/GatewayConfiguration.md#automatic-self-signed-certificate).
|
||||
|
||||
## CLI
|
||||
|
||||
The CLI emits deterministic JSON for automation:
|
||||
|
||||
@@ -76,6 +76,19 @@ types.
|
||||
cargo run -p mxgw-cli -- smoke --endpoint https://mxgateway.example.local:5001 --tls --ca-file C:\certs\mxgateway-ca.pem --server-name-override mxgateway.example.local --api-key-env MXGATEWAY_API_KEY --item TestChildObject.TestInt --json
|
||||
```
|
||||
|
||||
### TLS trust (pin-only)
|
||||
|
||||
The gateway can auto-generate its own self-signed certificate (it has no PKI).
|
||||
Unlike the other clients, the Rust client is **not** lenient: tonic 0.13.1
|
||||
exposes no public hook to inject a custom certificate verifier, so TLS over Rust
|
||||
is pin-only. A TLS connection requires either `--ca-file` /
|
||||
`ClientOptions::with_ca_file(...)` to pin a CA (export the gateway's self-signed
|
||||
certificate and pin it), or `--require-certificate-validation` /
|
||||
`with_require_certificate_validation(true)` to verify against the system trust
|
||||
roots. TLS with neither set fails `connect` with a clear, actionable error rather
|
||||
than accepting the certificate. See
|
||||
[Gateway Configuration](../../docs/GatewayConfiguration.md#automatic-self-signed-certificate).
|
||||
|
||||
## Library Surface
|
||||
|
||||
`ClientOptions` configures endpoint, API key, plaintext or TLS transport,
|
||||
|
||||
@@ -189,6 +189,25 @@ Support:
|
||||
- custom CA file,
|
||||
- domain override.
|
||||
|
||||
### Trust posture (pin-only)
|
||||
|
||||
The gateway can serve a self-signed certificate it generates itself (it has no
|
||||
PKI). Rust is the **exception** to the lenient-by-default posture the other
|
||||
clients use: tonic 0.13.1 exposes no public hook to inject a custom certificate
|
||||
verifier, so the Rust client cannot accept an arbitrary certificate. TLS over the
|
||||
Rust client is therefore **pin-only** — it requires either:
|
||||
|
||||
- `ClientOptions::with_ca_file(...)` to pin a CA (the supported path for the
|
||||
gateway's self-signed certificate; export the certificate and pin it), or
|
||||
- `ClientOptions::with_require_certificate_validation(true)` to verify against the
|
||||
system trust roots.
|
||||
|
||||
With TLS enabled (`with_plaintext(false)`), no pinned CA, and certificate
|
||||
validation not required, `GatewayClient::connect` rejects the connection with a
|
||||
clear, actionable error pointing at `with_ca_file` /
|
||||
`require_certificate_validation` rather than silently accepting the certificate.
|
||||
The CLI exposes `--ca-file` and `--require-certificate-validation`.
|
||||
|
||||
## Streaming
|
||||
|
||||
Expose event streams as a `Stream<Item = Result<MxEvent, Error>>`. Dropping the
|
||||
|
||||
Reference in New Issue
Block a user