Gateway Integration#
In production, a gateway (reverse proxy, ingress controller, or service mesh) often sits in front of the NeMo Platform. This page explains how authorization works with and without gateway-level auth, what headers the gateway must set, and which paths skip authorization.
For the security architecture, see Security Model.
Overview#
NMP’s authorization middleware runs inside each service. Every request is evaluated there unless auth is disabled or the request matches a bypass path. Optionally, the gateway can perform the authorization check (e.g., via Envoy ext_authz) and forward the request with a special header so that services trust the gateway’s decision and do not call the PDP again. That reduces latency and centralizes auth at the edge.
Required Headers (Gateway-Level Auth)#
When the gateway has already authorized the request, it must set:
Header |
Description |
|---|---|
|
Must be |
|
Principal identifier (e.g., user ID or email). Required. |
|
User email (optional but recommended). |
|
Comma-separated group names (optional). |
Header names are case-insensitive; services normalize them.
Bypass Paths#
The following are not subject to authorization checks; they are always allowed:
Health and readiness:
/health,/healthz,/ready,/readyz,/health/live,/health/ready,/metricsDiscovery:
/apis/auth/discovery(for CLI/SDK OIDC discovery)PDP endpoints: Paths under
/apis/auth/v2/authz/are restricted to service principals only. The middleware rejects external and regular-user requests automatically.Studio: Paths under
/studio(the Studio UI handles its own OIDC login)
Configure the gateway so these paths are not sent to the PDP (or are always allowed) when using gateway-level auth.
Gateway Configuration Examples#
Envoy ext_authz#
Envoy ext_authz filter configuration
http_filters:
# JWT validation
- name: envoy.filters.http.jwt_authn
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
your_idp:
issuer: "https://your-idp.example.com/"
remote_jwks:
http_uri:
uri: "https://your-idp.example.com/.well-known/jwks.json"
cluster: idp_cluster
timeout: 5s
cache_duration: 600s
claim_to_headers:
- header_name: "X-NMP-Principal-Id"
claim_name: "sub"
- header_name: "X-NMP-Principal-Email"
claim_name: "email"
rules:
- match: { prefix: "/" }
requires: { provider_name: "your_idp" }
# External authorization via OPA PDP
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: opa_pdp
transport_api_version: V3
failure_mode_allow: false
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
Header Stripping#
Configure your gateway to remove NMP auth headers from incoming external requests. This prevents clients from forging identities.
Envoy header stripping
Add request_headers_to_remove to your route configuration:
route_config:
virtual_hosts:
- name: nmp_service
domains: ["*"]
request_headers_to_remove:
- "x-nmp-principal-id"
- "x-nmp-principal-email"
- "x-nmp-principal-groups"
- "x-nmp-principal-on-behalf-of"
- "x-nmp-scopes"
- "x-nmp-authorized"
routes:
- match: { prefix: "/" }
route: { cluster: nmp_backend }
Testing Gateway Auth#
After configuring gateway-level auth, verify:
Headers are set correctly — Make a request through the gateway and check that
X-NMP-AuthorizedandX-NMP-Principal-Idare present on the service side.Headers are stripped from external requests — Try sending
X-NMP-Authorized: truefrom outside; verify it is stripped by the gateway.