Skip to content
Open
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
32 changes: 29 additions & 3 deletions charts/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,20 @@ spec:
- name: db-migrate
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command: ["/app/hyperfleet-api", "migrate"]
command:
- /app/hyperfleet-api
- migrate
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
- --db-host-file={{ .Values.database.external.secretMountPath }}/db.host
- --db-port-file={{ .Values.database.external.secretMountPath }}/db.port
- --db-name-file={{ .Values.database.external.secretMountPath }}/db.name
- --db-user-file={{ .Values.database.external.secretMountPath }}/db.user
- --db-password-file={{ .Values.database.external.secretMountPath }}/db.password
- --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
{{- end }}
Comment on lines +43 to +50
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

database.external.sslMode is ignored when pod identity is disabled.

At Line 43 and Line 68, --db-sslmode is only added inside the pod-identity branch. For external DB using Kubernetes Secret mode, the value in database.external.sslMode has no effect.

🔧 Proposed fix
         command:
         - /app/hyperfleet-api
         - migrate
+        {{- if .Values.database.external.enabled }}
+        - --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
+        {{- end }}
         {{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
         - --db-host-file={{ .Values.database.external.secretMountPath }}/db.host
         - --db-port-file={{ .Values.database.external.secretMountPath }}/db.port
         - --db-name-file={{ .Values.database.external.secretMountPath }}/db.name
         - --db-user-file={{ .Values.database.external.secretMountPath }}/db.user
         - --db-password-file={{ .Values.database.external.secretMountPath }}/db.password
-        - --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
         {{- end }}
@@
         - --api-server-bindaddress={{ .Values.server.bindAddress | default ":8000" }}
         - --health-server-bindaddress={{ .Values.server.healthBindAddress | default ":8080" }}
         - --metrics-server-bindaddress={{ .Values.server.metricsBindAddress | default ":9090" }}
+        {{- if .Values.database.external.enabled }}
+        - --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
+        {{- end }}
         {{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
         - --db-host-file={{ .Values.database.external.secretMountPath }}/db.host
         - --db-port-file={{ .Values.database.external.secretMountPath }}/db.port
         - --db-name-file={{ .Values.database.external.secretMountPath }}/db.name
         - --db-user-file={{ .Values.database.external.secretMountPath }}/db.user
         - --db-password-file={{ .Values.database.external.secretMountPath }}/db.password
-        - --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
         {{- end }}

Also applies to: 68-75

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/templates/deployment.yaml` around lines 43 - 50, The --db-sslmode flag
is only rendered inside the pod-identity branch so
.Values.database.external.sslMode is ignored when using external DB with secret
mount mode; update charts/templates/deployment.yaml to ensure the
--db-sslmode={{ .Values.database.external.sslMode | default "require" }}
argument is emitted whenever .Values.database.external.enabled is true (either
move it outside the usePodIdentity conditional or add a separate conditional for
external enabled and not usePodIdentity), referencing the existing conditional
keys .Values.database.external.enabled and
.Values.database.external.usePodIdentity and the flag name --db-sslmode to
locate where to add/move the line.

volumeMounts:
- name: secrets
mountPath: /build/secrets
mountPath: {{ if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}{{ .Values.database.external.secretMountPath }}{{ else }}/build/secrets{{ end }}
readOnly: true
{{- end }}
containers:
Expand All @@ -55,6 +65,14 @@ spec:
- --api-server-bindaddress={{ .Values.server.bindAddress | default ":8000" }}
- --health-server-bindaddress={{ .Values.server.healthBindAddress | default ":8080" }}
- --metrics-server-bindaddress={{ .Values.server.metricsBindAddress | default ":9090" }}
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
- --db-host-file={{ .Values.database.external.secretMountPath }}/db.host
- --db-port-file={{ .Values.database.external.secretMountPath }}/db.port
- --db-name-file={{ .Values.database.external.secretMountPath }}/db.name
- --db-user-file={{ .Values.database.external.secretMountPath }}/db.user
- --db-password-file={{ .Values.database.external.secretMountPath }}/db.password
- --db-sslmode={{ .Values.database.external.sslMode | default "require" }}
{{- end }}
ports:
- name: http
containerPort: 8000
Expand Down Expand Up @@ -113,7 +131,7 @@ spec:
mountPath: /tmp
{{- if or .Values.database.external.enabled .Values.database.postgresql.enabled }}
- name: secrets
mountPath: /build/secrets
mountPath: {{ if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}{{ .Values.database.external.secretMountPath }}{{ else }}/build/secrets{{ end }}
readOnly: true
{{- end }}
{{- if .Values.extraVolumeMounts }}
Expand All @@ -124,13 +142,21 @@ spec:
emptyDir: {}
{{- if or .Values.database.external.enabled .Values.database.postgresql.enabled }}
- name: secrets
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: {{ ternary (printf "%s-db-secrets" (include "hyperfleet-api.fullname" .)) .Values.database.external.secretProviderClass .Values.database.external.createSecretProviderClass | quote }}
{{- else }}
Comment on lines +145 to +151
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add a render-time guard for empty secretProviderClass.

At Line 150, if createSecretProviderClass=false and database.external.secretProviderClass is empty, the pod renders with an invalid CSI config and fails at startup.

🔧 Proposed fix
       - name: secrets
       {{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity }}
+        {{- $spcName := ternary (printf "%s-db-secrets" (include "hyperfleet-api.fullname" .)) .Values.database.external.secretProviderClass .Values.database.external.createSecretProviderClass }}
+        {{- if empty $spcName }}
+        {{- fail "database.external.secretProviderClass is required when usePodIdentity=true and createSecretProviderClass=false" }}
+        {{- end }}
         csi:
           driver: secrets-store.csi.k8s.io
           readOnly: true
           volumeAttributes:
-            secretProviderClass: {{ ternary (printf "%s-db-secrets" (include "hyperfleet-api.fullname" .)) .Values.database.external.secretProviderClass .Values.database.external.createSecretProviderClass | quote }}
+            secretProviderClass: {{ $spcName | quote }}
       {{- else }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/templates/deployment.yaml` around lines 145 - 151, The CSI
volumeAttributes currently always renders a secretProviderClass even when
.Values.database.external.createSecretProviderClass is false and
.Values.database.external.secretProviderClass is empty; update the template
around the csi block to conditionally render the secretProviderClass key only
when the computed value is non-empty (check
.Values.database.external.createSecretProviderClass OR
.Values.database.external.secretProviderClass) so the CSI config is omitted if
no provider class is provided; locate the ternary expression that builds the
name (uses include "hyperfleet-api.fullname",
.Values.database.external.secretProviderClass,
.Values.database.external.createSecretProviderClass) and wrap or gate the
secretProviderClass output with an if that ensures the rendered string is not
empty.

secret:
{{- if .Values.database.external.enabled }}
secretName: {{ .Values.database.external.secretName }}
{{- else }}
secretName: {{ include "hyperfleet-api.fullname" . }}-db-secrets
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.extraVolumes }}
{{- toYaml .Values.extraVolumes | nindent 6 }}
{{- end }}
Expand Down
28 changes: 28 additions & 0 deletions charts/templates/secretproviderclass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: {{ include "hyperfleet-api.fullname" . }}-db-secrets
namespace: {{ .Release.Namespace }}
labels:
{{- include "hyperfleet-api.labels" . | nindent 4 }}
spec:
provider: aws
parameters:
usePodIdentity: "true"
region: {{ .Values.database.external.aws.region | quote }}
objects: |
- objectName: {{ .Values.database.external.aws.secretName | quote }}
objectType: "secretsmanager"
Comment on lines +13 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fail fast when AWS SecretProviderClass inputs are empty.

At Line 13 and Line 15, empty region or objectName can render successfully but fail later at pod mount/runtime. Guard these with required so misconfiguration is caught during template rendering.

🔧 Proposed fix
 {{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
+{{- $awsRegion := required "database.external.aws.region is required when createSecretProviderClass=true" .Values.database.external.aws.region }}
+{{- $awsSecretName := required "database.external.aws.secretName is required when createSecretProviderClass=true" .Values.database.external.aws.secretName }}
 apiVersion: secrets-store.csi.x-k8s.io/v1
 kind: SecretProviderClass
 metadata:
@@
 spec:
   provider: aws
   parameters:
     usePodIdentity: "true"
-    region: {{ .Values.database.external.aws.region | quote }}
+    region: {{ $awsRegion | quote }}
     objects: |
-      - objectName: {{ .Values.database.external.aws.secretName | quote }}
+      - objectName: {{ $awsSecretName | quote }}
         objectType: "secretsmanager"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
region: {{ .Values.database.external.aws.region | quote }}
objects: |
- objectName: {{ .Values.database.external.aws.secretName | quote }}
objectType: "secretsmanager"
{{- if and .Values.database.external.enabled .Values.database.external.usePodIdentity .Values.database.external.createSecretProviderClass }}
{{- $awsRegion := required "database.external.aws.region is required when createSecretProviderClass=true" .Values.database.external.aws.region }}
{{- $awsSecretName := required "database.external.aws.secretName is required when createSecretProviderClass=true" .Values.database.external.aws.secretName }}
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: {{ .Values.database.external.secretProviderClassName }}
spec:
provider: aws
parameters:
usePodIdentity: "true"
region: {{ $awsRegion | quote }}
objects: |
- objectName: {{ $awsSecretName | quote }}
objectType: "secretsmanager"
{{- end }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/templates/secretproviderclass.yaml` around lines 13 - 16, The
SecretProviderClass template currently renders potentially empty values for
region and objectName which defers failure to runtime; update the template to
validate and fail fast by wrapping .Values.database.external.aws.region and
.Values.database.external.aws.secretName with the Helm required function (e.g.,
required "aws.region is required" .Values.database.external.aws.region) so
template rendering fails when those inputs are empty; ensure the required checks
are applied where region and objectName are inserted in the SecretProviderClass
objects block to prevent creating a pod-mount-time error.

jmesPath:
- path: "username"
objectAlias: "db.user"
- path: "password"
objectAlias: "db.password"
- path: "host"
objectAlias: "db.host"
- path: "port"
objectAlias: "db.port"
- path: "database"
objectAlias: "db.name"
{{- end }}
32 changes: 22 additions & 10 deletions charts/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ database:
enabled: false
# Name of existing secret with db.host, db.port, db.name, db.user, db.password keys
secretName: ""
# Use AWS Pod Identity / Secrets Store CSI driver for DB credentials (no Kubernetes Secret)
usePodIdentity: false
# Mount path for CSI secrets-store volume (when usePodIdentity is true)
secretMountPath: /mnt/secrets-store
# Name of SecretProviderClass for CSI secrets-store driver (required when usePodIdentity is true and createSecretProviderClass is false)
secretProviderClass: ""
# Create a SecretProviderClass from the chart (uses database.external.aws when true)
createSecretProviderClass: false
# AWS Secrets Manager config when createSecretProviderClass is true
aws:
region: ""
# Secrets Manager secret name or ARN (objectName in SecretProviderClass)
secretName: "hyperfleet/db-credentials"
# PostgreSQL SSL mode: disable | require | verify-ca | verify-full
sslMode: require

# Built-in PostgreSQL for development/testing
postgresql:
Expand Down Expand Up @@ -126,15 +141,12 @@ auth:

# Adapter configuration (REQUIRED)
# Configure which adapters must be ready for resources to be marked as "Ready"
# Both cluster and nodepool adapters MUST be specified - the application will not start without them
# Empty arrays [] are valid if you want no adapters required for the Ready state
# Both cluster and nodepool MUST be specified (empty arrays [] are valid)
adapters:
# Required adapters for cluster "Ready" state (REQUIRED)
# Example: ["validation", "dns", "pullsecret", "hypershift"]
# cluster: []
# Required adapters for nodepool "Ready" state (REQUIRED)
# Example: ["validation", "hypershift"]
# nodepool: []
# Required adapters for cluster "Ready" state. Example: ["validation", "dns", "pullsecret", "hypershift"]
cluster: []
# Required adapters for nodepool "Ready" state. Example: ["validation", "hypershift"]
nodepool: []

# ServiceMonitor for Prometheus Operator
# Enables automatic metrics discovery in clusters with Prometheus Operator
Expand All @@ -155,8 +167,8 @@ serviceMonitor:
# Additional environment variables
# You can override adapters by setting HYPERFLEET_*_ADAPTERS here
env: []
# - name: GLOG_V
# value: "10"
# - name: GLOG_V
# value: "10"

# Volume mounts for additional configs
extraVolumeMounts: []
Expand Down