Skip to content
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
22 changes: 21 additions & 1 deletion charts/qtodo/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,24 @@ Generate the JWT Audience
{{- else }}
{{- print .Values.app.vault.audience }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Returns true if the termination is secure (https) and false otherwise
*/}}
{{- define "qtodo.isSecureTermination" }}
{{- if or (eq .Values.app.route.termination "reencrypt") (eq .Values.app.route.termination "passthrough") }}
true
{{- end }}
{{- end }}

{{/*
Returns the port the application should list on
*/}}
{{- define "qtodo.app.port" -}}
{{- if include "qtodo.isSecureTermination" . -}}
{{ .Values.app.securePort }}
{{- else -}}
{{ .Values.app.insecurePort }}
{{- end -}}
{{- end -}}
26 changes: 23 additions & 3 deletions charts/qtodo/templates/app-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ spec:
image: {{ template "qtodo.image" (dict "value" .Values.app.images.main "context" $ "useRegistry" true) }}
imagePullPolicy: {{ .Values.app.images.main.pullPolicy }}
ports:
- containerPort: 8080
name: http
- containerPort: {{ template "qtodo.app.port" . }}
name: {{ if (include "qtodo.isSecureTermination" .) }}https{{ else }}http{{ end }}
protocol: TCP
envFrom:
- configMapRef:
Expand All @@ -219,7 +219,17 @@ spec:
- name: QUARKUS_HTTP_HOST
value: '0.0.0.0'
- name: QUARKUS_HTTP_PORT
value: '8080'
value: {{ .Values.app.insecurePort | quote }}
{{- if include "qtodo.isSecureTermination" . }}
- name: QUARKUS_HTTP_SSL_PORT
value: {{ .Values.app.securePort | quote }}
- name: QUARKUS_TLS_KEY_STORE_PEM_QTODO_CERT
value: /certs/tls.crt
- name: QUARKUS_TLS_KEY_STORE_PEM_QTODO_KEY
value: /certs/tls.key
- name: QUARKUS_HTTP_INSECURE_REQUESTS
value: 'disabled'
{{- end }}
- name: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_STRATEGY
value: 'drop-and-create'
{{- if not .Values.app.spire.enabled }}
Expand Down Expand Up @@ -273,6 +283,11 @@ spec:
- name: ztvp-trusted-ca
mountPath: /etc/pki/ca-trust/extracted/pem
readOnly: true
{{- end }}
{{- if include "qtodo.isSecureTermination" . }}
- name: tls-certs
mountPath: /certs
readOnly: true
{{- end }}
resources: {}
serviceAccountName: qtodo
Expand Down Expand Up @@ -304,4 +319,9 @@ spec:
configMap:
name: qtodo-truststore-java
{{- end }}
{{- if include "qtodo.isSecureTermination" . }}
- name: tls-certs
secret:
secretName: {{ .Values.app.tls.secret }}
{{- end }}
{{- end }}
4 changes: 2 additions & 2 deletions charts/qtodo/templates/app-route.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ metadata:
name: qtodo
spec:
port:
targetPort: 8080-tcp
targetPort: {{ printf "%s-tcp" (include "qtodo.app.port" .) }}
tls:
insecureEdgeTerminationPolicy: Redirect
termination: edge
termination: {{ .Values.app.route.termination }}
to:
kind: Service
name: qtodo
Expand Down
9 changes: 6 additions & 3 deletions charts/qtodo/templates/app-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ kind: Service
metadata:
annotations:
argocd.argoproj.io/sync-wave: '51'
{{- if eq .Values.app.tls.serviceServing true }}
service.beta.openshift.io/serving-cert-secret-name: {{ .Values.app.tls.secret | quote }}
{{- end }}
labels:
app: qtodo
name: qtodo
namespace: qtodo
spec:
ports:
- name: 8080-tcp
port: 8080
- name: {{ printf "%s-tcp" (include "qtodo.app.port" .) }}
port: {{ template "qtodo.app.port" . }}
protocol: TCP
targetPort: 8080
targetPort: {{ template "qtodo.app.port" . }}
selector:
app: qtodo
sessionAffinity: None
Expand Down
2 changes: 1 addition & 1 deletion charts/qtodo/templates/qtodo-network-policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
# to generate the correct ACLs for host-network ingress traffic.
- ports:
- protocol: TCP
port: 8080
port: {{ include "qtodo.app.port" . }}
from:
- namespaceSelector:
matchLabels:
Expand Down
11 changes: 11 additions & 0 deletions charts/qtodo/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ global:
# QTodo application configuration
app:
name: qtodo
insecurePort: 8080
securePort: 8443
images:
main:
name: quay.io/validatedpatterns/qtodo
Expand Down Expand Up @@ -62,10 +64,19 @@ app:
name: "oidc-client-secret"
vaultPath: "secret/data/apps/qtodo/qtodo-oidc-client"

# Route configuration
route:
termination: reencrypt

spire:
enabled: true # Enable SPIFFE + OIDC integration by default
sidecars: true

# TLS Configuration
tls:
secret: qtodo-tls
serviceServing: true

# Vault configuration for SPIFFE integration
# Uses SPIFFE JWT to authenticate and fetch DB password
vault:
Expand Down
37 changes: 37 additions & 0 deletions docs/multi-tier.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,40 @@ Switch back to the qtodo application and enter the username and password on the
Once you have authenticated to RHBK, you will be instructed to change the temporary password and set a more permanent password. Once complete, you will be redirected to the qtodo application verifying the OIDC based authentication functions properly.

Feel free to add new items to the list of todos. By being able to add and remove items from the page, the integration between the Quarkus application and the backend PostgreSQL database using credentials sourced from HashiCorp Vault was successful.

## TLS Termination Options

The qtodo application uses `reencrypt` TLS termination on the OpenShift Route by default, ensuring that traffic is encrypted end-to-end from the client to the pod. Ingress TLS communication is terminated at the OpenShift Router and reencrypted with a certificate generated using the [Service Serving Certificate feature](https://docs.redhat.com/en/documentation/openshift_container_platform/4.21/html/security_and_compliance/configuring-certificates#add-service-serving).

### Configuration

The qtodo Helm chart provides options to control how and where TLS communication is terminated:

* **`app.route.termination`** — Specifies the TLS termination type for the OpenShift Route
* `reencrypt` (default) — TLS is terminated at the Router and reencrypted to the pod using the certificate specified in `app.tls.secret`
* `passthrough` — TLS traffic passes through the Router without decryption and is terminated at the pod
* `edge` — TLS is terminated at the Router; backend communication uses HTTP

* **`app.securePort`** — The HTTPS port used by the application (default: `8443`)
* Used when `app.route.termination` is set to `reencrypt` or `passthrough`

* **`app.insecurePort`** — The HTTP port used by the application (default: `8080`)
* Used when `app.route.termination` is set to `edge` or when TLS is disabled

* **`app.tls.secret`** — Name of the Kubernetes Secret containing the TLS certificate and key (default: `qtodo-tls`)
* Used for pod-level TLS termination with `reencrypt` or `passthrough` routes

* **`app.tls.serviceServing`** — Enable automatic certificate generation via Service Serving Certificates (default: `true`)
* When enabled, OpenShift automatically generates and rotates the certificate in `app.tls.secret`
* When using custom certificates (e.g., for `passthrough` mode), set this to `false` and provide your own certificate in the secret

### Termination Types

| Termination Type | TLS at Router | TLS to Pod | Certificate Source | Use Case |
| --- | --- | --- | --- | --- |
| `reencrypt` (default) | Yes | Yes | Service Serving Certificate | End-to-end encryption with automatic cert rotation |
| `passthrough` | No | Yes | User-provided in `app.tls.secret` | Custom certificates or strict no-decrypt requirement |
| `edge` | Yes | No | Route certificate | Legacy apps without TLS support |

> [!NOTE]
> When using `passthrough` termination with custom certificates, ensure the certificate's Subject Alternative Name (SAN) matches the Route hostname. The Service Serving Certificate feature cannot be used in this mode.
Loading