feat(egress): auto-allow OTLP endpoint egress traffic - #1504
Conversation
…oup#1491) Parse OTEL_EXPORTER_OTLP_METRICS_ENDPOINT / OTEL_EXPORTER_OTLP_ENDPOINT at egress startup and inject an always-allow rule for the endpoint host so telemetry export works under the default deny-all policy without manual allowlist rules. The rule survives user policy updates and always-rule file reloads; deny.always still takes precedence.
There was a problem hiding this comment.
💡 Codex Review
In Kubernetes pods with the usual search domains, this single-label endpoint causes the resolver to query names such as otel-collector.<ns>.svc.cluster.local, while the auto-generated allow rule is only the exact host otel-collector; the DNS proxy returns NXDOMAIN for the search-expanded service name under default deny, so the documented example still cannot reach the collector. Use the full service DNS name in the example or teach the auto-allow logic to account for search-expanded service names.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Single-label names are subject to search-domain expansion; the deny-all DNS proxy answers expanded names with NXDOMAIN without fallback, so the example would not reach the collector.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e2da97a8ca
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…nsandbox-group#1491) - Auto-allow the exporter fallback node IP (HOST_IP / /etc/hostinfo) when no OTEL endpoint env var is set, so egress's own metric export is not blocked by its own deny-all chain in that configuration. - Trim the trailing root dot from FQDN endpoint hosts before building the rule so it matches DNS policy normalization.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1e63b77cf0
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Refactor the nested switch/if message handling into small helpers so the function stays under the gocognit threshold (37 > 30). The execd CI lint (installing golangci-lint@latest) fails every PR on this pre-existing issue.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e83886e3ea
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…opensandbox-group#1491) The otlpmetrichttp exporter parses endpoint env vars with url.Parse and reads u.Host, so bare host:port values become opaque URLs with an empty host and are never dialed; only scheme://host URLs are valid. Restrict parseOTLPEndpoint to URL form to avoid injecting allow rules for hosts the exporter never connects to. Also skip the node-IP fallback when an endpoint env var is set but unparseable: metricsClientOptions never falls back once the env var is non-empty, so the rule would open unrelated node-IP egress.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 64c15604d1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Closes #1491
Why
The egress component's default policy denies all outbound traffic, so users
had to manually inject allowlist rules for the OTLP endpoint to export
metrics. Since the egress sidecar shares the sandbox network namespace, its
own metric export is blocked by its own egress chain too.
What
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT(preferred) thenOTEL_EXPORTER_OTLP_ENDPOINTat egress startup(
components/internal/telemetry/endpoint.go), supporting URL,host:port, and bare-host forms with scheme-default ports.resolved via the DNS proxy, IP rules land in the static nft allow sets)
(
components/egress/telemetry_allow.go).POST/PATCH/DELETE policy updates and always-rule file reloads; operators
can still override via
deny.always, which takes precedence.per-rule port enforcement is not added.
components/egress/docs/opentelemetry.md.Tests
components/internal/telemetry/endpoint_test.go: endpoint parsing(URL/host:port/bare host, scheme defaults, precedence, invalid input).
components/egress/telemetry_allow_test.go: rule generation, static IPsets, merge/evaluate behavior, and pass-through when unconfigured.
go test -mod=mod ./...in components/egress and components/internal allgreen (note: egress vendor/ is stale vs go.mod — pre-existing, unrelated).