Signed ingest (SEC-015)
An ingest credential can carry the Ed25519 public key its senders sign with: PUT /v1/projects/{prj}/credentials/{cred}/signing with {"public_key": "<base64 32 bytes>", "required": true|false}. Only the public key is stored. A present signature must always verify; required also refuses unsigned data.
Transport | Carrier | Signed bytes |
|---|---|---|
OTLP/HTTP and the HTTP push receivers | headers |
|
OTLP gRPC | metadata |
|
OTel Arrow streams, Jaeger/OpenCensus/profiles/push gRPC, Firehose, Pub/Sub, syslog, Kafka | none | cannot carry a per-payload signature |
The timestamp must be within 5 minutes of the gateway clock.
With
required, a credential is refused on every transport without a carrier (gRPCUNAUTHENTICATED, HTTP 401,signature required). Send such data over OTLP/HTTP or OTLP gRPCExportinstead. Arrow exporters must be set to plain OTLP.A signature sent on a gRPC method other than
Exportis refused, because it cannot be checked.gRPC: sign the encoding your protobuf library produces for the request (field-number order; OTLP has no map fields). In Go:
proto.MarshalOptions{Deterministic: true}.Marshal(req), signed in a unary client interceptor that sets both metadata keys. The gateway checks it against its own encoding of the decoded request, so build against an OTLP proto version no newer than the gateway's.Refusals count in
wt_gateway_signature_denied_total{signal="http"|"grpc"}(HTTP and gRPC verification failures).
Per-record integrity
Logs that arrive with a verified signature keep a proof of it. After its pipeline runs, the worker stamps each record with:
Attribute | Value |
|---|---|
| hex SHA-256 of the RFC 8785 (JCS) form of the stored record: time ( |
|
|
| base64 HMAC-SHA256 of |
| key id and |
audit.integrity.* attributes sent by clients are always dropped, signed or not.
POST /v1/projects/{prj}/logs/integrity/verify takes the same body as logs/search, checks one page and returns counts (valid, unsigned, modified, bad_signature, unknown_key), the failing records and next_cursor. A record changed after ingest (for example by a redaction job) reports modified. Rotating WT_SECRET_KEY makes older stamps unknown_key. Only logs carry the stamp; spans and metrics are verified in transit only.