Data handling
What leaves your cluster
One connection, outbound, to one destination.
| Destination | api.gen0sec.com:443 |
| Made by | The relay pod only |
| Direction | Outbound, request and response |
| Purpose | Fetching four licensed datasets |
What is in the request. A path naming the artifact, and your own Gen0Sec API key. Nothing else. The relay does not add a customer identifier, a cluster identifier, an agent identifier, telemetry or usage data.
What is in the response. The artifact: a CTI indicator database, a GeoIP database, an ML model, or an IDS rule bundle.
What never leaves your cluster
| Data | What it is |
|---|---|
identity | Workload identity produced inside your cluster |
policy-edges | Pod IP addresses, namespaces, NetworkPolicy edges |
| Agent telemetry and events | Everything your agents report |
| Configuration and policy | Everything you configure |
| Logs | All of it, to container stdout in your cluster |
| Database contents | Postgres never leaves |
| Dashboard user accounts and passwords | Held in your Postgres |
identity and policy-edges deserve the explicit statement, because they are the two that are
technically served by the same service that does the relaying. They are never relayed. Doing so
would push a map of your workload topology to a service you do not run. It is not configurable, and no
flag enables it.
The upload surface is not relayed either, because the relay is read-only.
Who validates agent credentials
Your agents' keys are validated in your cluster, and they never leave it.
Every relayed route sits behind the local authentication middleware, and each one carries the same permission it carries in direct mode. So a key that would be refused when served locally is refused it when relayed.
agent --[agent key, authorized locally,
permission checked per route]--> relay --[your Gen0Sec API key]--> api.gen0sec.com
agent key stops here
Two separate concerns, deliberately separated:
| Hop | Credential | Checked by |
|---|---|---|
| Agent to relay | The agent's own key | Your cluster, against your installation, with the artifact's permission |
| Relay to Gen0Sec | Your Gen0Sec API key | Gen0Sec |
| Credentials Gen0Sec receives | One, belonging to your installation |
| Credentials Gen0Sec never receives | Your individual agent key |
| What Gen0Sec can infer about your fleet | Nothing from the credential. Requests carry no agent or cluster identifier |
| Revoking one agent | Local, in your dashboard, immediate |
| Revoking your installation's upstream access | Revoke or rotate your Gen0Sec API key |
This is the answer to "does our agent inventory leave our perimeter". It does not.
On a self-hosted deployment the relay never puts a caller's key in an outbound request, in any configuration. A locally-issued key could not authenticate to Gen0Sec anyway, so forwarding it could only leak a local credential to a third party without making the request succeed. With no Gen0Sec API key configured the relay sends no credential at all rather than sending yours.
Credentials at rest
| Credential | Where it lives | Generated by |
|---|---|---|
| Database role passwords | Kubernetes secrets | The Postgres operator |
| Object store keys | A Kubernetes secret | You, during install |
| Registry pull credentials | A Kubernetes secret per namespace | You, during install |
| Dashboard session signing key | A Kubernetes secret | Generated once, preserved across regeneration |
No credential appears in a chart, a values file or a rendered manifest. Every one is referenced by name. See Secrets.
The install procedure reads every credential from a file or from standard input rather than passing it as a command-line argument, so nothing lands in shell history or in the process list.
Credentials in transit
| Hop | Encrypted |
|---|---|
| Agents and users to your ingress | Yes, TLS you terminate |
Relay to api.gen0sec.com | Yes, TLS |
| Services to Postgres | Yes, TLS to the pooler |
| Services to the object store | Plain HTTP, in-cluster only |
| Services to the cache | Plain, in-cluster only, no credential in the URL |
The last two are in-cluster traffic on the pod network. If your threat model includes an attacker on the pod network, add NetworkPolicies and a service mesh. See Hardening.
The dashboard's database connection verifies encryption without verifying the certificate chain, because its client library rejects the pooler's self-signed certificate outright while every other service's library accepts encrypt-without-verify. The traffic is encrypted and in-cluster. Do not copy that setting onto the other services: their driver rejects it.
Data retention
Retention is yours. Nothing expires data on your behalf, and nothing is sent anywhere before it is deleted.
| Store | Grows with | Sized by |
|---|---|---|
| Postgres | Agents, events, history | postgres.volume.size |
| Kafka | In-flight events, and its retention window | kafka.storage.size |
| Object store | Datasets and locally-produced artifacts | rustfs.storageclass.dataStorageSize |
See Sizing.
Deleting everything
Uninstall without --keep-data deletes the namespaces and every
persistent volume in them: the database, the message log and the object store. There is no copy
anywhere else.