Outbound connections: proxies, egress policy and private endpoints¶
Several Vista Platform services call systems outside the cluster that a tenant or an operator configured: webhook, Slack and PagerDuty receivers, mail relays, vendor and cloud APIs, and — in Enterprise — a tenant's NetBox, CMDB or SIEM collector, and the model provider. This page covers the four things an operator decides about that traffic:
- whether it goes through an egress proxy (
HTTPS_PROXY); - whether a NetworkPolicy restricts it (
networkPolicy.egressEnabled); - whether a connection may reach a private address on your own network;
- which certificate authorities a connection trusts.
Which services dial out¶
| Service | What it reaches |
|---|---|
notification-service |
Webhook, Slack, PagerDuty and SMTP delivery |
monitoring-service, auth-service, admin-service |
SMTP; admin-service also fetches the catalogue feeds, delivers licence reports, reaches the Google or Microsoft identity provider for staff single sign-on and posts incident webhooks (public addresses only) |
device-interrogation-service, sensor-manager, cluster-sensor-service |
Device management APIs and active probes on your networks |
audit-service |
S3 archival of expired audit logs, when configured, and the legacy webhook alert action (public addresses only) |
compliance-engine, cbom-service |
Enterprise: the configured model provider — framework authoring and remediation drafts, and the CBOM comparison narrative. inventory-service and admin-service, the other two AI callers, reach it too. |
This is the chart's networkPolicy.externalEgressBackends list. Every one of
these opens its connection from its own pod — there is no central egress
pod — so proxy settings and policy exceptions have to apply to each service
that needs them.
Behind an egress proxy¶
The services honour the standard HTTP_PROXY, HTTPS_PROXY and NO_PROXY
variables. Set them per service with extraEnv:
backends:
inventory-service:
extraEnv:
- name: HTTPS_PROXY
value: http://proxy.corp.example:3128
- name: NO_PROXY
value: localhost,127.0.0.1,.svc,.cluster.local,10.42.0.0/16,10.43.0.0/16
NO_PROXY must cover everything inside the cluster: the .svc /
.cluster.local names and your pod and Service CIDRs (the same ranges as
networkPolicy.clusterInternalCIDRs). Service-to-service calls use the same
environment, and without those entries they are sent to the proxy.
How the SSRF guard behaves behind a proxy¶
Every outbound client that reaches a tenant-configured destination is guarded:
it refuses loopback, link-local (which includes the cloud metadata endpoint
169.254.169.254), the platform's own cluster ranges, and — unless the
connection has opted in — private addresses.
With a proxy in the path, the socket the service opens is to the proxy, so the guard judges the destination of each request instead: the host in the URL, resolved by the service. The proxy address itself is trusted, because you configured it. Redirects are judged again at every hop.
What the service cannot see is what the proxy resolves a name to. Two consequences, stated plainly:
- A name that resolves differently for the proxy than for the service (split-horizon DNS, or a record that changes between the two lookups) is outside what the platform can check.
- If the service cannot resolve a name at all — normal in a cluster where
only the proxy has external DNS — the request is handed to the proxy rather
than refused. IP literals, and names such as
localhost,metadata.google.internaland*.svc.cluster.local, are refused without any lookup.
So configure your proxy to refuse internal destinations as well: loopback,
169.254.0.0/16, your cluster's pod and Service CIDRs, and any network the
platform should never reach. That ACL is the control that closes the gap above.
A proxy that re-signs TLS¶
If the proxy intercepts TLS, the services must trust the proxy's CA for every
destination. Mount a bundle and point SSL_CERT_FILE at it, per
Running with an internal CA. SSL_CERT_FILE
replaces the image's trust store, so the bundle must include the public
roots too. (This is a platform-wide setting; the per-connection CA bundles
below are for one receiver and are added to the trust store, not substituted.)
Restricting egress with NetworkPolicy¶
With networkPolicy.egressEnabled: true the chart denies egress by default and
lets only the services in externalEgressBackends leave the cluster, to any
address except networkPolicy.clusterInternalCIDRs and link-local. Set
clusterInternalCIDRs to your cluster's pod and Service CIDRs first — the
chart refuses to render without them. See the comments on networkPolicy in
the chart's values.yaml for the port list and per-distribution defaults.
If your proxy runs inside the cluster, it sits in one of those excepted ranges, so the chart's rule does not reach it. NetworkPolicies are additive: add one of your own that lets the dialling services reach the proxy.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-to-proxy
namespace: vista # your release namespace
spec:
podSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values: [notification-service, inventory-service, audit-service]
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels: { kubernetes.io/metadata.name: egress-proxy }
ports:
- { protocol: TCP, port: 3128 }
Private endpoints¶
A connector whose target is on-premises by nature may be allowed to reach a
private address (RFC 1918, 100.64.0.0/10, IPv6 ULA) — a per-connection
setting the tenant turns on, recorded in the audit log.
That setting never opens:
- loopback, the unspecified address, link-local and the cloud metadata endpoints, and multicast;
- the platform's own cluster ranges. The chart passes
networkPolicy.clusterInternalCIDRsasVISTA_PLATFORM_INTERNAL_CIDRSto the services that dial private targets —device-interrogation-serviceand any backend whose values entry setsprivateNetworkDialer: true— whether or notegressEnabledis on, and refuses to render if you try to override it withextraEnv. A malformed value makes those services refuse every outbound connection rather than ignore it. So setclusterInternalCIDRsto your cluster's real ranges even if you never enable the egress NetworkPolicy.
The same ranges are kept out of scans the Platform Sensor runs: the
Platform Sensor (cluster-sensor-service) also receives
networkPolicy.clusterInternalCIDRs, and a tenant's Discover Assets or Active
Scan run from the platform refuses any address inside them, whatever prefixes the tenant has declared. A scan run by a tenant's own sensor is
unaffected: to that sensor the same numbers are the customer's own address
space. Private address space is otherwise the tenant's own, so the rest of
RFC 1918 stays scannable. Set clusterInternalCIDRs to your cluster's real pod
and Service ranges; the chart default (10.42.0.0/16, 10.43.0.0/16) is RKE2's.
An operator can forbid private targets for the whole deployment with
CONNECTOR_ALLOW_PRIVATE_ENDPOINTS=false (via extraEnv on the services
concerned). The operator's setting wins over the tenant's.
Certificate authorities for integrations¶
Outbound connections verify TLS against the image's trust store. A receiver
whose certificate your own CA issued — an on-premises NetBox, CMDB or SIEM
collector — would fail that check, so a connection can carry a custom CA
bundle: one or more PEM CERTIFICATE blocks that are added to the trust
store for that connection only.
- It is checked when the connection is saved: text that is not PEM, text after the last certificate, or anything other than a certificate is refused with a message saying which. A private key pasted by mistake is refused outright; it would otherwise be stored in a non-secret field.
- A CA certificate is public, so it is shown again on the edit form.
There is no "skip certificate verification" option, deliberately. The only legitimate reason to want one is a receiver signed by a CA the platform does not trust, and a CA bundle fixes exactly that while keeping verification on. A connection that verifies nothing sends its API token, or a stream of audit events, to whoever is in the network path.
Webhook, Slack and PagerDuty delivery reach public endpoints only and use the image's trust store. All of these outbound clients honour the egress proxy.