Network and hardening
This page is for the platform and security teams who run Olympusx AI: what it exposes, what it reaches, how its secrets are kept, and how to check that the images you run are the ones Olympusx built.
What must be reachable from outside
Section titled “What must be reachable from outside”| Address | Who reaches it | Needed |
|---|---|---|
https://<console-host> |
People’s browsers: the console and its API under /api |
Yes, from wherever people work |
https://<gateway-host>/v1 |
Applications, editors and agents calling models with API keys | Yes, from wherever those run |
| The identity provider’s issuer | People’s browsers, to sign in | Yes. With the built-in identity service it is under /auth on the console host. |
https://<console-host>/api/v1/hooks/code-sources/<id> |
Your code host (GitLab, GitHub, Bitbucket Cloud), for merge request reviews | Only for code sources that review merge requests. See Merge request review. |
https://<console-host>/api/v1/hooks/log-sources/<id> |
Your alerting system, sending alerts for investigation | Only when alerts are sent in. See Alert integration. |
A code host or alerting system on the public internet must reach the hook addresses. Everything else can stay on a private network. Each hook is authenticated by its source’s own secret.
The platform’s internal ports, its metrics endpoints and the database are never exposed through the console or gateway hosts.
Network policies in the platform’s namespace
Section titled “Network policies in the platform’s namespace”Network policies are on by default. They make sure:
- the control plane’s internal listeners, which the gateway calls on every request, are reachable from the gateway’s pods only. Anyone who could reach them could mint authorization decisions and billing events.
- the metrics ports are reachable only by your monitoring. See Metrics scrapers.
- the database instances admit the database operator on their management port and nothing else beyond the platform’s own pods.
Leave them on. If your cluster’s network plugin does not enforce network policies, the objects are inert: record that in your risk register rather than relying on them. OVN-Kubernetes and Calico enforce them; a managed cluster with policy enforcement disabled does not.
Narrowing who may call the gateway
Section titled “Narrowing who may call the gateway”By default any source may reach the gateway’s port: it is the authenticated inference API, reached through the ingress or route and directly by in-cluster applications. To narrow it, list the allowed peers in the chart’s networkPolicy.gatewayFrom: your ingress controller’s namespace (on OpenShift, the router) and the namespaces of in-cluster clients. The control plane is always admitted, because agent runs call the gateway.
Metrics scrapers
Section titled “Metrics scrapers”spec.networkPolicy.metricsScrapers lists who may scrape the control plane’s port 8086, the metering worker’s 8082 and the database’s 9187. Each entry is a network policy peer, as in a policy’s from:. The list replaces the default:
| Cluster | Default |
|---|---|
| Kubernetes | The namespace named monitoring |
| OpenShift | Namespaces labelled network.openshift.io/policy-group: monitoring, which admits user-workload monitoring |
spec: networkPolicy: metricsScrapers: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: observabilityAn empty list is refused. A wrong list breaks nothing visibly: pods stay ready, and Prometheus shows the targets down.
A second field names the namespace the database operator runs in, when it is not that operator’s default. Wrong, the database still serves queries but stops failing over. See Configuration.
Project namespaces
Section titled “Project namespaces”Each project gets a namespace on every cluster where it holds quota. Olympusx AI applies to it:
- network policies that deny all traffic in both directions by default, then allow DNS, traffic within the namespace, and traffic to and from the platform’s namespace. There is no internet egress. A model server there loads its weights from your registry, not from the internet;
- a resource quota and default limits from the project’s quota;
- an edit role and a view role, neither of which can change the quota, the limits, the network policies or roles. People cannot weaken their own boundary.
Olympusx AI never adopts a namespace labelled for another tenant, or an unlabelled one that already exists, and never deletes a namespace it did not create for a project.
The roles are bound to people only when the installation sets a group template, a pattern containing {tenant} that names the group your cluster’s authentication gives a tenant’s people. Without it, no binding is created.
Outbound traffic
Section titled “Outbound traffic”What the platform itself reaches, and how to control it:
| Destination | From | Control |
|---|---|---|
| The identity provider’s discovery and keys | The control plane | Must be reachable. |
| Cloud model providers, over HTTPS | The control plane | An egress proxy through the chart’s control-plane environment (HTTPS_PROXY, NO_PROXY). |
| Hugging Face, for imports | An import job on a connected cluster, or the bastion agent | Declare air-gapped clusters; fetch through a bastion. See Remote access. |
| Tenants’ tool servers (MCP) | The control plane, during agent runs | Public addresses over https:// only, by default. In-cluster hosts must be listed in spec.agents.mcpInternalAllowList. See below. |
| Registered clusters’ API servers | The control plane | Must be reachable from the platform. |
Tool servers inside your network
Section titled “Tool servers inside your network”By default a tenant’s tool server is reached only on a public address over https://. Private ranges (10/8, 172.16/12, 192.168/16, fc00::/7, 100.64/10) are reached only when listed:
spec: agents: mcpInternalAllowList: - '*.tenant-tools.svc.cluster.local' - 10.20.0.0/16Entries are host names, *. wildcards, addresses and CIDRs. A listed host may also be reached over plain http://. Loopback, link-local and cloud metadata addresses are never reached, whatever the list says, and the control plane refuses to start on such an entry, or on *.
Keep the list narrow. The cluster’s service and pod ranges contain the platform’s own services, and listing them gives a tenant administrator the reach the policy exists to take away. Prefer a namespace wildcard or a range set aside for tool servers. See Tools.
- Console and gateway are served over HTTPS through your ingress, or OpenShift routes with edge termination that redirect plain HTTP. One TLS secret can serve both hosts (
spec.ingress.tlsSecret). - The console sends
Strict-Transport-Security: max-age=31536000; includeSubDomainsand a content security policy that allows scripts only from itself and connections only to itself and the identity provider. - Registered clusters are reached with their certificate verified against the CA you give, or the system’s roots. Skip TLS verification (dev only) exists for development and must stay off.
- Registries a cluster pulls from are verified the same way; Plain HTTP sends credentials unencrypted and suits only an isolated internal mirror.
- The bastion agent is reached over mutual TLS only.
The master key and sealed secrets
Section titled “The master key and sealed secrets”The platform’s master key, a Secret named by spec.secrets.masterKey with a SECRETS_MASTER_KEY entry, seals every credential Olympusx AI stores: cluster tokens, registry passwords, model provider keys, bastion client keys and backup keys. Create it once:
kubectl -n <namespace> create secret generic olympus-master-key \ --from-literal=SECRETS_MASTER_KEY="$(openssl rand -base64 32)"- No API response ever contains a sealed credential. Pages show only whether one is set, or its last four characters.
- Without the master key, Olympusx AI refuses to store a credential rather than store it in the clear.
- Changing the key makes every sealed credential unreadable, and each must be entered again. Treat it as long-lived, and keep a copy outside the cluster: a restore needs the original. See Backup and restore.
API keys are shown once, when issued, and stored only as a hash. Sign-in passwords are never seen by Olympusx AI: they live in the identity provider.
Database isolation
Section titled “Database isolation”Every tenant-scoped table in the platform database carries a row-level security policy that is enforced even for the table’s owner: a request scoped to one tenant cannot read another tenant’s rows. On an installation with the bundled database, the platform’s database account holds no superuser rights, so the policies apply from the first query.
Turning on tenant isolation at installation goes further: the platform then connects with a restricted role that does not own the tables and cannot drop the policies that constrain it. It needs a separate database role Secret. The operator refuses the resource when tenant isolation is on and that Secret is not given. See Configuration.
Tenant knowledge lives in separate vector databases, one per instance, with its own credentials.
Verify the images you run
Section titled “Verify the images you run”Every published Olympusx AI image and the Helm chart are signed, and every image except the operator catalog carries a software bill of materials (SBOM) and build provenance.
What you need
Section titled “What you need”-
cosignv2 or later. -
The Olympusx AI public signing key, supplied with your release. Check its fingerprint against the one your Olympusx contact gives you through a separate channel: that comparison is what makes the rest meaningful.
sha256sum olympus-cosign.pub
Verify a signature
Section titled “Verify a signature”cosign verify \ --key olympus-cosign.pub \ --insecure-ignore-tlog=true \ <registry>/olympus-control-plane:<version>Output naming the key and the digest means the image is exactly what Olympusx built. An error means it is not: do not deploy it, and tell your Olympusx contact.
Verify each image you run, starting with the operator catalog, which a cluster installing through the operator pulls first: the operator catalog, operator and operator bundle, the control plane, the console, the code parser, the guardrails service, the reranker, the model importer, the optional GPU agent, and the chart. The guardrails and reranker images do not change with every release; verify the digest your installation pins, not a tag.
--insecure-ignore-tlog=true turns off only the public transparency-log check. The signature is still verified against the key.
Pin the digest
Section titled “Pin the digest”A tag can be moved; a digest cannot. Deploy by the digest you verified, by setting each image’s tag to <version>@sha256:<digest>.
Read the SBOM and provenance
Section titled “Read the SBOM and provenance”They are attestations inside the image index, read with the tool that wrote them, from the verified digest:
D=$(crane digest <registry>/olympus-control-plane:<version>)cosign verify --key olympus-cosign.pub --insecure-ignore-tlog=true \ "<registry>/olympus-control-plane@$D"docker buildx imagetools inspect "<registry>/olympus-control-plane@$D" \ --format '{{ json .SBOM }}' > sbom.jsondocker buildx imagetools inspect "<registry>/olympus-control-plane@$D" \ --format '{{ json .Provenance }}'Reading them from a tag proves nothing on its own: pin first, then inspect. The registry address and pull credential come with your subscription.