Gateway
Repo: AnyGateway (Rust). The gateway sits between the endpoints and the backend. It transports
telemetry and enrollments up to Kafka, and forwards commands and enrollment results down to
the agents.
gRPC services
Two gRPC services defined in AnyProto contracts.
| Proto service | Rust impl (src/service/) | RPC | Role |
|---|---|---|---|
OcsfEvent Service | ocsf.rs | OcsfBatch (unary) | Schema-encodes each OCSF event, produces it to Kafka, and returns accept and reject counts. |
Endpoint Service | endpoint_ channel.rs | EndpointChannel (bidirectional stream) | The long-lived control channel (see below). |
The control stream requires Hello as its first frame (otherwise failed_precondition), verifies
the endpoint identity, publishes an enrollment event, and registers the live downstream sender in
the connection registry keyed by endpoint_id. It then pumps commands and enrollment results down,
and heartbeats and command results up.
Component view
Arrow colors: blue = data plane (telemetry flowing up), orange = control plane (commands, enrollment, and remediation actions flowing down).
External communication
The diagram shows the wires. This table describes what actually crosses each one, the external processes the gateway talks to, what moves, and over which protocol. Internal module-to-module calls are omitted.
| From | To | Data | Protocol |
|---|---|---|---|
| Endpoints | service/ocsf | Batched telemetry | gRPC, mTLS |
| Endpoints | service/endpoint_channel | Control stream. Up: Hello, heartbeats, and command results. Down: signed commands and trust bundles | gRPC bidirectional stream, mTLS |
broker | Kafka | Up topics: raw.endpoint, enrollment.endpoint, command.endpoint.response | Kafka |
| Kafka | broker | Down topics: command.endpoint, enrollment.endpoint.response | Kafka |
certmgr | step-ca | Certificate enrollment and renewal | ACME over HTTPS |
registry | Schema Registry | OCSF schema registration and lookup | HTTP |
Module layout (src)
| Module | Responsibility |
|---|---|
server/ | gRPC server wiring: the TLS authentication and resolver, certificate setup, and shutdown. |
service/ | gRPC service implementations plus the enrollment publisher. |
identity/ | Endpoint SPKI-based identity verification from the peer mTLS certificate, fingerprint checking, and revocation. |
connections/ | Stream each endpoint_id message to its downstream sender. |
downlink/ | The Kafka-to-delivery loop that decides whether each frame is a command or a trust bundle. |
delivery/ | Routes a downstream frame to the matching live stream. |
certmgr/ | Managed certificate lifecycle with step-ca: enroll, renew, and hot-swap. |
registry/ | Schema Registry client and the message encoder. |
broker/ | Kafka producer and consumer. |
config/ | Environment-based configuration for the server, TLS, and Kafka. |
Kafka topics
| Topic | Direction | Carries |
|---|---|---|
raw.endpoint | up | OCSF telemetry (OcsfService) |
enrollment.endpoint | up | Enrollment events |
command.endpoint. response | up | CommandResult acknowledgements |
command.endpoint | down | Backend commands, forwarded as Command frames |
enrollment.endpoint. response (optional) | down | Trust-bundle responses, forwarded as TrustBundle frames |
mTLS scheme
Two modes, chosen at startup in priority order (config/server.rs). The gateway refuses to
start with neither configured, and partial configuration in either mode is rejected:
- Managed mTLS (recommended). step-ca ACME (HTTP-01) when
CA_URL,CA_FINGERPRINT, andACME_PROVISIONERare set. The gateway enrolls itself, auto-renews at a fraction of the certificate lifetime, and hot-swaps the renewed certificate onto live listeners. - Static mTLS.
GRPC_TLS_CERT_PATH,GRPC_TLS_KEY_PATH, andGRPC_TLS_CLIENT_CA_PATH, for use when step-ca is unavailable.
Both modes are secure and fail closed. There is no plaintext or self-reported-key path.
Identity verification
Each agent has an endpoint_id, a short fingerprint of its public key (the first 8 bytes of the
SHA-256 of the certificate’s SubjectPublicKeyInfo, written as 16 lowercase hex characters). Because
it is derived from the key, the same agent always produces the same id, and no other agent can
reproduce it without the matching private key.
The gateway computes this fingerprint from the certificate the agent presented during the mTLS
handshake. It compares that against the endpoint_id the agent claims in its Hello, rejects the connection on
a mismatch, then checks the id against a revocation list and rejects revoked devices (identity/fingerprint.rs,
service/endpoint_channel.rs).
Downstream delivery
The gateway sends two kinds of frame down to an agent, and treats both as opaque payloads. It forwards the bytes verbatim and never decodes, inspects, or signs them.
- Commands. Remediation actions from the backend, such as isolate host, kill process, or quarantine file.
- Trust bundles. The “enrollment result” shown on the diagram. A signed set of keys the agent uses to verify the authenticity of a command.
The gateway parses a routing header (the endpoint_id) to pick the destination stream, then
forwards the payload into a downstream frame unchanged (downlink/runner.rs,
service/endpoint_channel.rs). The gateway acts as a dumb relay. Verification happens end-to-end at
the agent using the trust bundle sent earlier (see Command Trust).
Configuration
The gateway is configured entirely from environment variables. This table covers the connection
security variables behind the mTLS scheme and identity verification above. Required means required
within the selected mode. The full set (Kafka tuning, batching, and topic overrides) lives in the
AnyGateway README. These are gateway variables, distinct from the agent’s install-time variables in
the Installation Guide even where a name is shared.
| Variable | Required | Purpose |
|---|---|---|
CA_URL | Yes | Managed. step-ca base URL. With the fingerprint and provisioner set, selects managed mTLS. Takes precedence over the static paths. |
CA_FINGERPRINT | Yes | Managed. SHA-256 hex of the step-ca root, the trust anchor for fetching and pinning the root. |
ACME_PROVISIONER | Yes | Managed. step-ca ACME provisioner name. |
CA_ROOT_PATH | No | Managed. Optional shipped root PEM. When omitted, the root is fetched from the CA URL and pinned against the fingerprint. |
CERT_RENEW_FRACTION | No | Managed. Fraction of the certificate lifetime at which to renew. |
GATEWAY_IDENTITY_DNS | No | Managed. DNS name ordered from ACME and placed in the certificate SAN. |
GRPC_TLS_CERT_PATH | Yes | Static. Gateway TLS certificate. |
GRPC_TLS_KEY_PATH | Yes | Static. Gateway TLS private key. |
GRPC_TLS_CLIENT_CA_PATH | Yes | Static. CA used to validate client certificates. |
REVOKED_ENDPOINTS_PATH | No | Revocation. File of revoked endpoint ids the gateway refuses to serve. Feeds the revocation gate. |
Library inventory
Key third-party libraries the gateway depends on, for traceability when reading the code.
| Library | Used for |
|---|---|
tokio | Asynchronous runtime for all concurrent tasks. |
tonic, tonic-prost, prost | gRPC transport and Protocol Buffers encoding. |
anyproto | Shared AnyOne protobuf contracts. |
rdkafka | Kafka producer and consumer. |
rustls, tokio-rustls, rustls-pemfile | TLS termination and certificate loading. |
instant-acme | ACME client for the managed certificate lifecycle. |
rcgen, x509-parser | Certificate generation and parsing peer certificates. |
reqwest, hyper, hyper-util, http, http-body-util | HTTP client and server plumbing. |
sha2 | Hashing for endpoint identity fingerprints. |
dashmap, arc-swap | Concurrent connection registry and hot-swapping certificates. |
serde, serde_json | Serialization. |
tracing, tracing-subscriber | Logging and diagnostics. |
metrics | Runtime metrics. |
futures, async-trait, tokio-stream | Async utilities. |