Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for custom HTTP headers injected as an env var #233

Merged
merged 2 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/v1alpha1/frontendenvironment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ type FrontendEnvironmentSpec struct {
TargetNamespaces []string `json:"targetNamespaces,omitempty" yaml:"targetNamespaces,omitempty"`
// For the ChromeUI to render additional global components
ServiceCategories *[]FrontendServiceCategory `json:"serviceCategories,omitempty" yaml:"serviceCategories,omitempty"`
// Custom HTTP Headers
// These populate an ENV var that is then added into the caddy config as a header block
HTTPHeaders map[string]string `json:"httpHeaders,omitempty"`

DefaultReplicas *int32 `json:"defaultReplicas,omitempty" yaml:"defaultReplicas,omitempty"`
}
Expand Down
7 changes: 7 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions config/crd/bases/cloud.redhat.com_frontendenvironments.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ spec:
hostname:
description: Hostname
type: string
httpHeaders:
additionalProperties:
type: string
description: |-
Custom HTTP Headers
These populate an ENV var that is then added into the caddy config as a header block
type: object
ingressAnnotations:
additionalProperties:
type: string
Expand Down
49 changes: 40 additions & 9 deletions controllers/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,23 +397,54 @@ func populateVolumes(d *apps.Deployment, frontend *crd.Frontend, frontendEnviron
d.Spec.Template.Spec.Volumes = volumes
}

// Add the SSL env vars if we SSL mode is set in the frontend environment
// Add the env vars if eny are set
func (r *FrontendReconciliation) populateEnvVars(d *apps.Deployment, frontendEnvironment *crd.FrontendEnvironment) {
if !frontendEnvironment.Spec.SSL {
return
}
envVars := []v1.EnvVar{
{
envVars := []v1.EnvVar{}

if frontendEnvironment.Spec.SSL {
envVars = append(envVars, v1.EnvVar{
Name: "CADDY_TLS_MODE",
Value: "https_port 8000",
},
{
})
envVars = append(envVars, v1.EnvVar{
Name: "CADDY_TLS_CERT",
Value: "tls /opt/certs/tls.crt /opt/certs/tls.key",
}}
})
}

// Add the HTTP Headers to the env vars if the frontend environment has them
if frontendEnvironment.Spec.HTTPHeaders != nil {
envVars = append(envVars, v1.EnvVar{
Name: "CADDY_HTTP_HEADERS",
Value: createCaddyfileHeaderBlock(frontendEnvironment.Spec.HTTPHeaders),
})
}

d.Spec.Template.Spec.Containers[0].Env = envVars
}

// Create a Caddyfile header block from the FrontenbdEnvironment httpHeaders
func createCaddyfileHeaderBlock(httpHeaders map[string]string) string {
if len(httpHeaders) == 0 {
return ""
}
var keys []string
for key := range httpHeaders {
keys = append(keys, key)
}
// Sort keys alphabetically
// We do this to ensure the order of the headers is consistent
// without this tests will be flaky
sort.Strings(keys)

headerBlock := "header {\n"
for _, key := range keys {
headerBlock += fmt.Sprintf("%s %s\n", key, httpHeaders[key])
}
headerBlock += "}"
return headerBlock
}

func (r *FrontendReconciliation) createFrontendDeployment(annotationHashes []map[string]string) error {

// Create new empty struct
Expand Down
8 changes: 8 additions & 0 deletions deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,14 @@ objects:
hostname:
description: Hostname
type: string
httpHeaders:
additionalProperties:
type: string
description: 'Custom HTTP Headers

These populate an ENV var that is then added into the caddy config
as a header block'
type: object
ingressAnnotations:
additionalProperties:
type: string
Expand Down
2 changes: 2 additions & 0 deletions docs/antora/modules/ROOT/pages/api_reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ Preserving for backwards compatibility + | |
| *`targetNamespaces`* __string array__ | List of namespaces that should receive a copy of the frontend configuration as a config map +
By configurations we mean the fed-modules.json, navigation files, etc. + | |
| *`serviceCategories`* __xref:{anchor_prefix}-github-com-redhatinsights-frontend-operator-api-v1alpha1-frontendservicecategory[$$FrontendServiceCategory$$]__ | For the ChromeUI to render additional global components + | |
| *`httpHeaders`* __object (keys:string, values:string)__ | Custom HTTP Headers +
These populate an ENV var that is then added into the caddy config as a header block + | |
| *`defaultReplicas`* __integer__ | | |
|===

Expand Down
8 changes: 8 additions & 0 deletions tests/e2e/http_headers/00-create-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: test-http-headers
spec:
finalizers:
- kubernetes
38 changes: 38 additions & 0 deletions tests/e2e/http_headers/01-create-resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
apiVersion: cloud.redhat.com/v1alpha1
kind: FrontendEnvironment
metadata:
name: test-http-headers-environment
spec:
generateNavJSON: false
ssl: false
hostname: foo.redhat.com
sso: https://sso.foo.redhat.com
httpHeaders:
"X-Frame-Options": "Set"
"X-XSS-Protection": "1; mode=block;"
"X-Content-Type-Options": "nosniff"
"Content-Security-Policy": "default-src 'self'"
"Referrer-Policy": "no-referrer"
---
apiVersion: cloud.redhat.com/v1alpha1
kind: Frontend
metadata:
name: chrome
namespace: test-http-headers
spec:
API:
versions:
- v1
frontend:
paths:
- /
deploymentRepo: https://github.com/RedHatInsights/insights-chrome
envName: test-http-headers-environment
image: quay.io/cloudservices/insights-chrome-frontend:720317c
module:
config:
ssoUrl: 'https://'
manifestLocation: /apps/chrome/js/fed-mods.json
title: Chrome

46 changes: 46 additions & 0 deletions tests/e2e/http_headers/02-assert.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: chrome-frontend
namespace: test-http-headers
labels:
frontend: chrome
ownerReferences:
- apiVersion: cloud.redhat.com/v1alpha1
kind: Frontend
name: chrome
spec:
selector:
matchLabels:
frontend: chrome
template:
spec:
volumes:
- name: config
configMap:
name: test-http-headers-environment
defaultMode: 420
containers:
- name: fe-image
image: 'quay.io/cloudservices/insights-chrome-frontend:720317c'
env:
- name: CADDY_HTTP_HEADERS
value: |-
header {
Content-Security-Policy default-src 'self'
Referrer-Policy no-referrer
X-Content-Type-Options nosniff
X-Frame-Options Set
X-XSS-Protection 1; mode=block;
}
ports:
- name: web
containerPort: 80
protocol: TCP
- name: metrics
containerPort: 9000
protocol: TCP
volumeMounts:
- name: config
mountPath: /opt/app-root/src/build/stable/operator-generated
Loading