Configure CORS policy
Configure Cross-Origin Resource Sharing (CORS) headers at the ingress level so external browser-based clients can make API requests to vCluster Platform.
Prerequisites​
- A deployed vCluster Platform instance with external access configured.
- An ingress controller (such as ingress-nginx) deployed on the host cluster.
helmv3.10+ andkubectlwith admin access to the cluster.
Overview​
If you build browser-based tools, such as a custom operations dashboard, a monitoring UI, or a CI interface, that call the Platform API from a different domain, browsers block those requests by default. This is the same-origin policy. CORS headers tell the browser which external origins are allowed.
For example, a dashboard at https://dashboard.example.com that fetches data from the Platform API at https://platform.example.com fails unless the Platform ingress returns the correct CORS headers.
The Platform UI and API share the same origin. Normal Platform access, kubectl commands, and in-cluster service-to-service traffic don't require CORS. Configure CORS only when a browser-based application at a different origin calls the Platform API.
The Platform doesn't set CORS headers by default. Add them through your ingress controller.
Configure ingress-level CORS​
ingress-nginx​
Create or update your
vcluster-platform.yamlwith CORS annotations on the Platform ingress:Modify the following with your specific values to generate a copyable command:vcluster-platform.yamlingress:
enabled: true
host: "platform.example.com"
annotations:
# CORS
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://dashboard.example.com"
nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "Authorization, Content-Type"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
nginx.ingress.kubernetes.io/cors-max-age: "3600"
tls:
enabled: true
secret: tls-vcluster-platformApply the configuration:
Modify the following with your specific values to generate a copyable command:Upgrade the Platform with CORS annotationshelm upgrade vcluster-platform vcluster-platform \
--repo https://charts.loft.sh/ \
--namespace vcluster-platform \
--reuse-values \
-f vcluster-platform.yamlVerify the ingress returns CORS headers by sending a preflight request:
Modify the following with your specific values to generate a copyable command:Test CORS preflightcurl -v -X OPTIONS \
-H "Origin: https://dashboard.example.com" \
-H "Access-Control-Request-Method: GET" \
https://platform.example.com/kubernetes/management/apisA correct response includes these headers:
Access-Control-Allow-Origin: https://dashboard.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-TypeIf these headers are missing, check the ingress annotations and confirm the ingress controller processes them.
Annotation reference​
All annotations use the nginx.ingress.kubernetes.io/ prefix.
| Annotation | Description | Default |
|---|---|---|
enable-cors | Enable CORS headers | "false" |
cors-allow-origin | Allowed origins (comma-separated) | "*" |
cors-allow-methods | Allowed HTTP methods | "GET, PUT, POST, DELETE, PATCH, OPTIONS" |
cors-allow-headers | Allowed request headers | Standard browser headers and Authorization |
cors-allow-credentials | Allow credentials (cookies, auth) | "false" |
cors-expose-headers | Response headers exposed to browser | (none) |
cors-max-age | Preflight cache duration in seconds | "1728000" |
Don't set cors-allow-origin to "*" when cors-allow-credentials is "true". Browsers reject this combination per the CORS specification. List explicit origins instead.
Other ingress controllers​
Traefik, Istio, and Gateway API support CORS through their own configuration:
- Traefik: Use the headers middleware with
accessControlAllowOriginListon an IngressRoute. - Istio: Use the
corsPolicyfield on a VirtualService. See Expose vCluster Platform with Istio for a related setup guide. - Gateway API: The experimental CORS filter (Gateway API v1.3+) supports CORS on HTTPRoute resources. See the Gateway API CORS guide for details.
Security considerations​
Restrict allowed origins​
Setting cors-allow-origin to "*" disables CORS protection. Any website a user visits can make cross-origin requests to the Platform API.
Never use cors-allow-origin: "*" in production. List only the specific domains that need access.
- Prefer explicit origins (
https://dashboard.example.com) over wildcards. - Separate development and production configurations. Don't include localhost origins in production values.
CORS doesn't replace authentication​
CORS headers control which origins a browser permits for cross-origin requests. They don't authenticate or authorize API calls. The Platform's authentication, RBAC, and network policies remain the primary access controls.
Troubleshoot CORS issues​
Browser shows "blocked by CORS policy"​
The ingress didn't return an Access-Control-Allow-Origin header for the requesting origin. Verify the following:
- The
enable-corsannotation is"true"on the Platform ingress. - The
cors-allow-originvalue matches the exact origin the browser sends. Scheme, host, and port must all match. - The ingress controller terminates TLS. Check the Platform's TLS configuration.
Limitations​
- Changes to ingress annotations require a
helm upgradeof the Platform to update the ingress resource.