Skip to content

Commit

Permalink
feat(reports): add auth proxy protecting report generators (#206)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores authored Nov 22, 2024
1 parent f6127ef commit b91e9bd
Show file tree
Hide file tree
Showing 14 changed files with 366 additions and 27 deletions.
42 changes: 22 additions & 20 deletions charts/cryostat/README.md

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion charts/cryostat/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,24 @@ Get or generate a default secret key for object storage.
{{- end -}}
{{- end -}}

{{/*
Get or generate a default secret password key for report generators.
*/}}
{{- define "cryostat.reportsPassSecretKey" -}}
{{- $secret := (lookup "v1" "Secret" .Release.Namespace (printf "%s-reports-secret" .Release.Name)) -}}
{{- if $secret -}}
{{/*
Use current secret. Do not regenerate.
*/}}
{{- $secret.data.REPORTS_PASS -}}
{{- else -}}
{{/*
Generate new secret
*/}}
{{- (randAlphaNum 32) -}}
{{- end -}}
{{- end -}}

{{/*
Get or generate a default secret key for auth proxy cookies.
*/}}
Expand All @@ -130,7 +148,7 @@ Get or generate a default secret key for auth proxy cookies.
{{/*
Generate new secret
*/}}
{{- (randAlphaNum 32) | b64enc | quote -}}
{{- (randAlphaNum 32) | b64enc -}}
{{- end -}}
{{- end -}}

Expand Down
2 changes: 1 addition & 1 deletion charts/cryostat/templates/_openshiftOauthProxy.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Create OpenShift OAuth Proxy container.
- --pass-basic-auth=false
- --upstream=http://localhost:8181/
- --upstream=http://localhost:3000/grafana/
- --cookie-secret="$(COOKIE_SECRET)"
- --cookie-secret=$(COOKIE_SECRET)
- --openshift-service-account={{ include "cryostat.serviceAccountName" . }}
- --proxy-websockets=true
- --http-address=0.0.0.0:4180
Expand Down
92 changes: 92 additions & 0 deletions charts/cryostat/templates/_reports_authproxy.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{{- define "cryostat.reportsAuthProxy" -}}
{{- if (.Values.authentication.openshift).enabled }}
- name: {{ printf "%s-reports-%s" .Chart.Name "authproxy" }}
securityContext:
{{- toYaml .Values.openshiftOauthProxy.securityContext | nindent 4 }}
image: "{{ .Values.openshiftOauthProxy.image.repository }}:{{ .Values.openshiftOauthProxy.image.tag }}"
env:
- name: COOKIE_SECRET
valueFrom:
secretKeyRef:
name: {{ default (printf "%s-cookie-secret" .Release.Name) .Values.authentication.cookieSecretName }}
key: COOKIE_SECRET
optional: false
args:
- --pass-access-token=false
- --pass-user-bearer-token=false
- --pass-basic-auth=false
- --htpasswd-file=/etc/oauth2_proxy/basicauth/htpasswd
- --upstream=http://localhost:10001/
- --cookie-secret=$(COOKIE_SECRET)
- --request-logging=true
- --openshift-service-account={{ include "cryostat.serviceAccountName" . }}
- --proxy-websockets=true
- --http-address=0.0.0.0:4180
- --https-address=:8443
- --tls-cert=/etc/tls/private/tls.crt
- --tls-key=/etc/tls/private/tls.key
- --proxy-prefix=/oauth2
- --bypass-auth-for=^/health$
imagePullPolicy: {{ .Values.openshiftOauthProxy.image.pullPolicy }}
ports:
- containerPort: 4180
name: http
protocol: TCP
- containerPort: 8443
name: https
protocol: TCP
resources:
{{- toYaml .Values.openshiftOauthProxy.resources | nindent 4 }}
volumeMounts:
- name: {{ .Release.Name }}-proxy-tls
mountPath: /etc/tls/private
- name: {{ .Release.Name }}-reports-secret
mountPath: /etc/oauth2_proxy/basicauth
readOnly: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
{{- else }}
- name: {{ printf "%s-reports-%s" .Chart.Name "authproxy" }}
securityContext:
{{- toYaml (.Values.oauth2Proxy).securityContext | nindent 4 }}
image: "{{ (.Values.oauth2Proxy).image.repository }}:{{ (.Values.oauth2Proxy).image.tag }}"
imagePullPolicy: {{ (.Values.oauth2Proxy).image.pullPolicy }}
env:
- name: OAUTH2_PROXY_CLIENT_ID
value: dummy
- name: OAUTH2_PROXY_CLIENT_SECRET
value: none
- name: OAUTH2_PROXY_HTTP_ADDRESS
value: 0.0.0.0:4180
- name: OAUTH2_PROXY_UPSTREAMS
value: http://localhost:10001/
- name: OAUTH2_PROXY_REDIRECT_URL
value: "http://localhost:4180/oauth2/callback"
- name: OAUTH2_PROXY_COOKIE_SECRET
valueFrom:
secretKeyRef:
name: {{ default (printf "%s-cookie-secret" .Release.Name) .Values.authentication.cookieSecretName }}
key: COOKIE_SECRET
optional: false
- name: OAUTH2_PROXY_EMAIL_DOMAINS
value: "*"
- name: OAUTH2_PROXY_HTPASSWD_USER_GROUP
value: write
- name: OAUTH2_PROXY_HTPASSWD_FILE
value: /etc/oauth2_proxy/basicauth/htpasswd
- name: OAUTH2_PROXY_SKIP_AUTH_ROUTES
value: "^/health$"
- name: OAUTH2_PROXY_PROXY_WEBSOCKETS
value: "false"
ports:
- containerPort: 4180
name: http
protocol: TCP
resources:
{{- toYaml .Values.oauth2Proxy.resources | nindent 4 }}
volumeMounts:
- name: {{ .Release.Name }}-reports-secret
mountPath: /etc/oauth2_proxy/basicauth
readOnly: true
{{- end }}
{{- end}}
13 changes: 12 additions & 1 deletion charts/cryostat/templates/cryostat_deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,19 @@ spec:
- name: QUARKUS_HIBERNATE_ORM_SQL_LOAD_SCRIPT
value: no-file
{{- if gt (int (.Values.reports).replicas) 0 }}
- name: REPORTS_PASS_SECRET_KEY
valueFrom:
secretKeyRef:
name: {{ default (printf "%s-reports-secret" .Release.Name) .Values.reports.reportsSecretName }}
key: REPORTS_PASS
optional: false
# TODO TLS trust
- name: QUARKUS_TLS_TRUST_ALL
value: "true"
- name: QUARKUS_REST_CLIENT_EXTENSIONS_API_VERIFY_HOST
value: "false"
- name: QUARKUS_REST_CLIENT_REPORTS_URL
value: {{ printf "http://%s-reports:%d" $fullName (int .Values.reports.service.httpPort) }}
value: {{ printf "%s://cryostat:$(REPORTS_PASS_SECRET_KEY)@%s-reports.%s.svc:%d" (ternary "https" "http" (.Values.authentication.openshift).enabled) $fullName $.Release.Namespace (int .Values.reports.service.httpPort) }}
{{- end }}
- name: QUARKUS_DATASOURCE_USERNAME
value: cryostat
Expand Down
13 changes: 13 additions & 0 deletions charts/cryostat/templates/reports_deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ spec:
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
{{- include "cryostat.reportsAuthProxy" . | nindent 8 }}
- name: {{ printf "%s-%s" .Chart.Name "reports" }}
securityContext:
{{- toYaml (.Values.reports).securityContext | nindent 12 }}
Expand All @@ -42,6 +43,8 @@ spec:
env:
- name: QUARKUS_HTTP_PORT
value: "{{ .Values.reports.service.httpPort }}"
- name: QUARKUS_LOG_LEVEL
value: {{ .Values.reports.debug.log.level }}
ports:
- containerPort: {{ .Values.reports.service.httpPort }}
protocol: TCP
Expand Down Expand Up @@ -71,4 +74,14 @@ spec:
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: {{ .Release.Name }}-reports-secret
secret:
defaultMode: 0440
secretName: {{ .Release.Name }}-reports-secret
{{- if (.Values.authentication.openshift).enabled }}
- name: {{ .Release.Name }}-proxy-tls
secret:
secretName: {{ .Release.Name }}-proxy-tls
{{- end }}
{{- end -}}
13 changes: 13 additions & 0 deletions charts/cryostat/templates/reports_secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{- if empty .Values.reports.reportsSecretName -}}
{{- $secretKey := include "cryostat.reportsPassSecretKey" . -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-reports-secret
labels:
{{- include "cryostat.labels" $ | nindent 4 }}
type: Opaque
data:
REPORTS_PASS: {{ $secretKey | b64enc }}
htpasswd: {{ htpasswd "cryostat" $secretKey | b64enc }}
{{- end -}}
4 changes: 2 additions & 2 deletions charts/cryostat/templates/reports_service.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{{- $fullName := include "cryostat.fullname" . -}}
---
{{- if gt (int (.Values.reports).replicas) 0 -}}
{{- $fullName := include "cryostat.fullname" . -}}
apiVersion: v1
kind: Service
metadata:
Expand All @@ -12,6 +11,7 @@ spec:
type: {{ .Values.reports.service.type }}
ports:
- port: {{ .Values.reports.service.httpPort }}
targetPort: {{ ternary "https" "http" (.Values.authentication.openshift).enabled }}
selector:
{{- include "cryostat.selectorLabels" $ | nindent 4 }}
app.kubernetes.io/component: reports
Expand Down
14 changes: 13 additions & 1 deletion charts/cryostat/tests/cryostat_deployment_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,19 @@ tests:
asserts:
- equal:
path: spec.template.spec.containers[?(@.name=='cryostat')].env[?(@.name=='QUARKUS_REST_CLIENT_REPORTS_URL')].value
value: http://RELEASE-NAME-cryostat-reports:10001
value: http://cryostat:$(REPORTS_PASS_SECRET_KEY)@RELEASE-NAME-cryostat-reports.NAMESPACE.svc:10001

- it: should set environment variable if sidecar report generator is enabled in OpenShift with HTTPS
set:
reports:
replicas: 1
authentication:
openshift:
enabled: true
asserts:
- equal:
path: spec.template.spec.containers[?(@.name=='cryostat')].env[?(@.name=='QUARKUS_REST_CLIENT_REPORTS_URL')].value
value: https://cryostat:$(REPORTS_PASS_SECRET_KEY)@RELEASE-NAME-cryostat-reports.NAMESPACE.svc:10001

- it: should set oauth2proxy resource overrides
set:
Expand Down
34 changes: 34 additions & 0 deletions charts/cryostat/tests/reports_deployment_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ tests:
reports:
replicas: 1
asserts:
- exists:
path: spec.template.spec.containers[?(@.name=='cryostat-reports-authproxy')]
- equal:
path: spec.template.spec.containers[?(@.name=='cryostat-reports-authproxy')].image
value: "quay.io/oauth2-proxy/oauth2-proxy:latest"
- equal:
path: spec.template.spec.containers[?(@.name=='cryostat-reports-authproxy')].ports
value:
- containerPort: 4180
name: http
protocol: TCP
- exists:
path: spec.template.spec.containers[?(@.name=='cryostat-reports')]
- equal:
Expand All @@ -73,6 +84,29 @@ tests:
path: spec.template.spec.containers[?(@.name=='cryostat-reports')].env[?(@.name=='QUARKUS_HTTP_PORT')].value
value: "10001"

- it: should validate authproxy settings when deployed in OpenShift
set:
reports:
replicas: 1
authentication:
openshift:
enabled: true
asserts:
- exists:
path: spec.template.spec.containers[?(@.name=='cryostat-reports-authproxy')]
- equal:
path: spec.template.spec.containers[?(@.name=='cryostat-reports-authproxy')].image
value: "quay.io/cryostat/openshift-oauth-proxy:cryostat-v3.0"
- equal:
path: spec.template.spec.containers[?(@.name=='cryostat-reports-authproxy')].ports
value:
- containerPort: 4180
name: http
protocol: TCP
- containerPort: 8443
name: https
protocol: TCP

- it: should apply Kubernetes specific settings when configured
set:
reports:
Expand Down
40 changes: 40 additions & 0 deletions charts/cryostat/tests/reports_secret_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
suite: test reports_secret.yaml
templates:
- reports_secret.yaml

tests:
- it: should create a reports secret if core.reportsSecretName is not set
set:
core.reportsSecretName: ""
asserts:
- hasDocuments:
count: 1
- equal:
path: kind
value: Secret
- equal:
path: metadata.name
value: RELEASE-NAME-reports-secret
- equal:
path: type
value: Opaque
- exists:
path: data.htpasswd
- exists:
path: data.REPORTS_PASS
- equal:
path: metadata.labels
value:
app.kubernetes.io/instance: RELEASE-NAME
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: cryostat
app.kubernetes.io/part-of: cryostat
app.kubernetes.io/version: 4.0.0-dev
helm.sh/chart: cryostat-2.0.0-dev

- it: should not create a database secret if reports.reportsSecretName is set
set:
reports.reportsSecretName: "custom-reports-secret"
asserts:
- hasDocuments:
count: 0
Loading

0 comments on commit b91e9bd

Please sign in to comment.