Skip to content

Commit

Permalink
Add options to set additional nginx headers (#3817)
Browse files Browse the repository at this point in the history
* Add options to values.yaml and the nginx template for injecting extra add_header directives at the server and location levels. I haven't gone and stubbed this out for every location directive yet - I'd like directional feedback on the concept.

The primary motivation here is that security tools (correctly) flag that `Access-Control-Allow-Origin '*'` is, in many cases, overly-permissive, and that the absence of a `Content-Security-Policy` header opens attack vectors for XSS and clickjacking.

The default values supplied in `values.yaml` with this commit keep the CORS behavior consistent, by defaulting to the permissive approach. Users will now be able to override this permissive configuration to harden their application.
The default values for CSP disallow iframe embedding to prevent clickjacking, and forbid pulling in sources (scripts, images, etc) from domains other than self, and Userway (an accessibility application leveraged by some Kubecost users). Users who embed Kubecost in an iframe in their own context would need to update their Helm charts to allow this behavior again.

Signed-off-by: Neal Ormsbee <[email protected]>

* Signed-off-by: jesse goodier <[email protected]>

configurable cache control

* Add additional whitelist sources to CSP

Signed-off-by: Neal Ormsbee <[email protected]>

* Remove support for per-route header configs. Only use global server header configs for now

Signed-off-by: Neal Ormsbee <[email protected]>

---------

Signed-off-by: Neal Ormsbee <[email protected]>
Co-authored-by: jesse goodier <[email protected]>
  • Loading branch information
nealormsbee and jessegoodier authored Feb 10, 2025
1 parent 336c5fb commit 9ce2e52
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ data:
root /var/www;
index index.html;

add_header Cache-Control "must-revalidate";
{{- range .Values.kubecostFrontend.nginxHeaders.server }}
add_header {{ . }}
{{- end }}

{{- if .Values.kubecostFrontend.extraServerConfig }}
{{- .Values.kubecostFrontend.extraServerConfig | toString | nindent 8 -}}
Expand Down Expand Up @@ -240,8 +242,6 @@ data:

location ~ ^/(turndown|cluster)/ {

add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
{{- if .Values.clusterController }}
{{- if .Values.clusterController.enabled }}
{{- if or .Values.saml .Values.oidc }}
Expand Down Expand Up @@ -1473,8 +1473,6 @@ data:
{{- end }}
location = /model/hideOrphanedResources {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
{{- if .Values.kubecostFrontend.hideOrphanedResources }}
return 200 '{"hideOrphanedResources": "true"}';
{{- else }}
Expand All @@ -1483,8 +1481,6 @@ data:
}
location = /model/hideDiagnostics {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
{{- if .Values.kubecostFrontend.hideDiagnostics }}
return 200 '{"hideDiagnostics": "true"}';
{{- else }}
Expand All @@ -1500,8 +1496,6 @@ data:

location /model/multi-cluster-diagnostics-enabled {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
{{- if and .Values.diagnostics.enabled .Values.diagnostics.primary.enabled }}
{{- if or (not (empty .Values.kubecostModel.federatedStorageConfigSecret )) .Values.kubecostModel.federatedStorageConfig }}
return 200 '{"multiClusterDiagnosticsEnabled": true}';
Expand All @@ -1521,8 +1515,6 @@ data:
# Deployment, we should forward that path to the K8s Service.
location /model/diagnostics/multicluster {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
proxy_read_timeout 300;
proxy_pass http://multi-cluster-diagnostics/status;
proxy_redirect off;
Expand All @@ -1533,8 +1525,6 @@ data:
# simple alias for support
location /mcd {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
proxy_read_timeout 300;
proxy_pass http://multi-cluster-diagnostics/status?window=7d;
proxy_redirect off;
Expand All @@ -1554,8 +1544,6 @@ data:
{{- if .Values.forecasting.enabled }}
location /forecasting {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
proxy_read_timeout 300;
proxy_pass http://forecasting/;
proxy_redirect off;
Expand All @@ -1572,8 +1560,6 @@ data:

location /model/productConfigs {
default_type 'application/json';
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;
return 200 '\n
{
"ssoConfigured": "{{ template "ssoEnabled" . }}",
Expand Down
10 changes: 10 additions & 0 deletions cost-analyzer/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,16 @@ kubecostFrontend:
# fqdn: kubecost-multi-diag.kubecost.svc.cluster.local:9007
# clusterController:
# fqdn: cluster-controller.kubecost.svc.cluster.local:9731
#

# Configurable headers for nginx responses.
nginxHeaders:
# applied to all route locations
server:
- "'Access-Control-Allow-Origin' '*' always;"
- "'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS' always;"
- Content-Security-Policy "default-src 'self' 'unsafe-inline' api.userway.org cdn.userway.org api-js.mixpanel.com keyper.kubecost.com; frame-ancestors 'none'; font-src 'self' data:;";
- Cache-Control "must-revalidate";

# Kubecost Metrics deploys a separate pod which will emit kubernetes specific metrics required
# by the cost-model. This pod is designed to remain active and decoupled from the cost-model itself.
Expand Down

0 comments on commit 9ce2e52

Please sign in to comment.