Skip to content

Commit 145e524

Browse files
tkargerTim Karger
authored andcommitted
feat: enable secret injection by sidecar
1 parent 2f9be3b commit 145e524

9 files changed

Lines changed: 175 additions & 3 deletions

valkey/templates/_helpers.tpl

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ Validate auth configuration
136136
*/}}
137137
{{- define "valkey.validateAuthConfig" -}}
138138
{{- if .Values.auth.enabled }}
139-
{{- if not (or .Values.auth.aclUsers .Values.auth.aclConfig) }}
139+
{{- if not (or .Values.auth.aclUsers .Values.auth.aclConfig .Values.auth.injectSecret.enabled) }}
140140
{{- fail "auth.enabled is true but no authentication method is configured. Please provide auth.aclUsers or auth.aclConfig" }}
141141
{{- end }}
142142
{{- if .Values.auth.aclUsers }}
@@ -156,6 +156,17 @@ Validate auth configuration
156156
{{- end }}
157157
{{- end }}
158158
{{- end }}
159+
{{- if .Values.auth.injectSecret.enabled }}
160+
{{- if not .Values.auth.injectSecret.permissions }}
161+
{{- fail "auth.injectSecret.enabled is true but no permissions is configured." }}
162+
{{- end }}
163+
{{- if not .Values.auth.injectSecret.username }}
164+
{{- fail "auth.injectSecret.enabled is true but no username is configured." }}
165+
{{- end }}
166+
{{- if not .Values.auth.injectSecret.mountPath }}
167+
{{- fail "auth.injectSecret.enabled is true but no mountPath is configured." }}
168+
{{- end }}
169+
{{- end }}
159170
{{- end }}
160171
{{- end -}}
161172

@@ -181,7 +192,7 @@ Validate replica persistence configuration
181192
Validate replica authentication configuration
182193
*/}}
183194
{{- define "valkey.validateReplicaAuth" -}}
184-
{{- if and .Values.replica.enabled .Values.auth.enabled }}
195+
{{- if and .Values.replica.enabled .Values.auth.enabled (not .Values.auth.injectSecret.enabled)}}
185196
{{- if not (hasKey .Values.auth.aclUsers .Values.replica.replicationUser) }}
186197
{{- fail (printf "Replication user '%s' (replica.replicationUser) must be defined in auth.aclUsers. The chart requires this to retrieve the password for replica authentication." .Values.replica.replicationUser) }}
187198
{{- end }}

valkey/templates/deploy_valkey.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ spec:
8282
mountPath: /valkey-auth-secret
8383
readOnly: true
8484
{{- end }}
85+
{{- if .Values.auth.injectSecret.enabled }}
86+
{{ $dir := regexReplaceAll "/[^/]+$" .Values.auth.injectSecret.mountPath "/" }}
87+
- name: inject-secret
88+
mountPath: "{{ $dir }}"
89+
{{- end }}
8590
{{- end }}
8691
{{- with .Values.extraVolumeMounts }}
8792
{{- toYaml . | nindent 12 }}
@@ -141,6 +146,11 @@ spec:
141146
{{- if .Values.auth.enabled }}
142147
- name: valkey-acl
143148
mountPath: /etc/valkey
149+
{{- if and .Values.auth.injectSecret.enabled }}
150+
{{ $dir := regexReplaceAll "/[^/]+$" .Values.auth.injectSecret.mountPath "/" }}
151+
- name: inject-secret
152+
mountPath: "{{ $dir }}"
153+
{{- end }}
144154
{{- end }}
145155
{{- range $secret := .Values.extraValkeySecrets }}
146156
- name: {{ $secret.name }}-valkey
@@ -252,6 +262,10 @@ spec:
252262
secretName: {{ include "valkey.fullname" . }}-auth
253263
defaultMode: 0400
254264
{{- end }}
265+
{{- if .Values.auth.injectSecret.enabled }}
266+
- name: inject-secret
267+
emptyDir: {}
268+
{{- end }}
255269
{{- end }}
256270
- name: {{ $storage.volumeName }}
257271
{{- if $storage.persistentVolumeClaimName }}

valkey/templates/init_config.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,14 @@ data:
138138
fi
139139
{{- end }}
140140

141+
# Set user from injected secret with permissions
142+
{{- if and .Values.auth.injectSecret.enabled .Values.auth.injectSecret.mountPath }}
143+
INJECTED_PASSWORD=$(cat {{ .Values.auth.injectSecret.mountPath }})
144+
PASSHASH=$(echo -n "$INJECTED_PASSWORD" | sha256sum | cut -f 1 -d " ")
145+
echo "user {{ .Values.auth.injectSecret.username }} on #$PASSHASH {{ .Values.auth.injectSecret.permissions }}" >> /etc/valkey/users.acl
146+
log "Set user {{ .Values.auth.injectSecret.username }} by injected secret"
147+
{{- end }}
148+
141149
# Set final permissions
142150
chmod 0400 /etc/valkey/users.acl
143151
log "ACL file created with 0400 permissions"
@@ -185,10 +193,16 @@ data:
185193

186194
{{- if .Values.auth.enabled }}
187195
# Get the password for the replication user
188-
{{- $replUsername := .Values.replica.replicationUser }}
196+
{{- $replUsername := ""}}
197+
{{- if .Values.auth.injectSecret.enabled }}
198+
{{- $replUsername = .Values.auth.injectSecret.username }}
199+
REPL_PASSWORD=$(cat {{ .Values.auth.injectSecret.mountPath }})
200+
{{- else }}
201+
{{- $replUsername = .Values.replica.replicationUser }}
189202
{{- $replUser := index .Values.auth.aclUsers $replUsername }}
190203
{{- $replPasswordKey := $replUser.passwordKey | default $replUsername }}
191204
REPL_PASSWORD=$(get_user_password "{{ $replUsername }}" "{{ $replPasswordKey }}") || exit 1
205+
{{- end }}
192206

193207
# Write masterauth configuration
194208
echo "masterauth $REPL_PASSWORD" >>"$VALKEY_CONFIG"

valkey/templates/statefulset.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ spec:
9898
mountPath: /valkey-auth-secret
9999
readOnly: true
100100
{{- end }}
101+
{{- if .Values.auth.injectSecret.enabled }}
102+
{{ $dir := regexReplaceAll "/[^/]+$" .Values.auth.injectSecret.mountPath "/" }}
103+
- name: inject-secret
104+
mountPath: "{{ $dir }}"
105+
{{- end }}
101106
{{- end }}
102107
{{- with .Values.initResources }}
103108
resources:
@@ -155,6 +160,11 @@ spec:
155160
{{- if .Values.auth.enabled }}
156161
- name: valkey-acl
157162
mountPath: /etc/valkey
163+
{{- if and .Values.auth.injectSecret.enabled }}
164+
{{ $dir := regexReplaceAll "/[^/]+$" .Values.auth.injectSecret.mountPath "/" }}
165+
- name: inject-secret
166+
mountPath: "{{ $dir }}"
167+
{{- end }}
158168
{{- end }}
159169
{{- range $secret := .Values.extraValkeySecrets }}
160170
- name: {{ $secret.name }}-valkey
@@ -266,6 +276,10 @@ spec:
266276
secretName: {{ include "valkey.fullname" . }}-auth
267277
defaultMode: 0400
268278
{{- end }}
279+
{{- if .Values.auth.injectSecret.enabled }}
280+
- name: inject-secret
281+
emptyDir: {}
282+
{{- end }}
269283
{{- end }}
270284
{{- with .Values.extraVolumes }}
271285
{{- toYaml . | nindent 8 }}

valkey/tests/deployment_test.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ tests:
1818
path: spec.template.spec.initContainers[0].volumeMounts[?(@.name == "valkey-users-secret")]
1919
- notExists:
2020
path: spec.template.spec.initContainers[0].volumeMounts[?(@.name == "valkey-auth-secret")]
21+
- notExists:
22+
path: spec.template.spec.initContainers[0].volumeMounts[?(@.name == "inject-secret")]
2123

2224
- it: should have generated volume with inline passwords
2325
set:
@@ -114,6 +116,33 @@ tests:
114116
secretName: RELEASE-NAME-valkey-auth
115117
defaultMode: 0400
116118

119+
- it: should have generated a volume with emptyDir and mount it
120+
set:
121+
auth.enabled: true
122+
auth.injectSecret.enabled: true
123+
auth.injectSecret.username: default
124+
auth.injectSecret.permissions: "~* &* +@all"
125+
auth.injectSecret.mountPath: "/test/path"
126+
template: templates/deploy_valkey.yaml
127+
asserts:
128+
- isKind:
129+
of: Deployment
130+
- contains:
131+
path: spec.template.spec.initContainers[0].volumeMounts
132+
content:
133+
name: inject-secret
134+
mountPath: "/test/"
135+
- contains:
136+
path: spec.template.spec.containers[0].volumeMounts
137+
content:
138+
name: inject-secret
139+
mountPath: "/test/"
140+
- contains:
141+
path: spec.template.spec.volumes
142+
content:
143+
name: inject-secret
144+
emptyDir: { }
145+
117146
- it: should use custom image
118147
set:
119148
image.registry: custom-registry

valkey/tests/init_config_test.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,43 @@ tests:
138138
path: data["init.sh"]
139139
pattern: 'REPL_PASSWORD=\$\(get_user_password "default" "default"\)'
140140

141+
- it: should use injected secret for replica authentication
142+
set:
143+
replica.enabled: true
144+
replica.persistence.size: "5Gi"
145+
replica.replicationUser: "default"
146+
auth:
147+
enabled: true
148+
injectSecret:
149+
enabled: true
150+
username: default
151+
permissions: "~* &* +@all"
152+
mountPath: "/test/path"
153+
asserts:
154+
- isKind:
155+
of: ConfigMap
156+
- matchRegex:
157+
path: data["init.sh"]
158+
pattern: 'REPL_PASSWORD=\$\(cat /test/path\)'
159+
141160
- it: should have correct metadata
142161
asserts:
143162
- isKind:
144163
of: ConfigMap
145164
- equal:
146165
path: metadata.labels["app.kubernetes.io/name"]
147166
value: valkey
167+
168+
- it: should use password of injected secret
169+
set:
170+
auth.enabled: true
171+
auth.injectSecret.enabled: true
172+
auth.injectSecret.username: default
173+
auth.injectSecret.permissions: "~* &* +@all"
174+
auth.injectSecret.mountPath: "/test/path"
175+
asserts:
176+
- isKind:
177+
of: ConfigMap
178+
- matchRegex:
179+
path: data["init.sh"]
180+
pattern: 'INJECTED_PASSWORD=\$\(cat /test/path\)'

valkey/tests/statefulset_test.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,35 @@ tests:
237237
mountPath: /extra-config
238238
readOnly: true
239239

240+
- it: should have generated a volume with emptyDir and mount it
241+
set:
242+
replica.enabled: true
243+
replica.persistence.size: "5Gi"
244+
auth.enabled: true
245+
auth.injectSecret.enabled: true
246+
auth.injectSecret.username: default
247+
auth.injectSecret.permissions: "~* &* +@all"
248+
auth.injectSecret.mountPath: "/test/path"
249+
template: templates/statefulset.yaml
250+
asserts:
251+
- isKind:
252+
of: StatefulSet
253+
- contains:
254+
path: spec.template.spec.initContainers[0].volumeMounts
255+
content:
256+
name: inject-secret
257+
mountPath: "/test/"
258+
- contains:
259+
path: spec.template.spec.containers[0].volumeMounts
260+
content:
261+
name: inject-secret
262+
mountPath: "/test/"
263+
- contains:
264+
path: spec.template.spec.volumes
265+
content:
266+
name: inject-secret
267+
emptyDir: {}
268+
240269
- it: should include persistentVolumeClaimRetentionPolicy when configured
241270
set:
242271
replica.enabled: true

valkey/values.schema.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@
1919
},
2020
"usersExistingSecret": {
2121
"type": "string"
22+
},
23+
"injectSecret": {
24+
"type": "object",
25+
"properties": {
26+
"enabled": {
27+
"type": "boolean"
28+
},
29+
"username": {
30+
"type": "string"
31+
},
32+
"permissions": {
33+
"type": "string"
34+
},
35+
"mountPath": {
36+
"type": "string"
37+
}
38+
}
2239
}
2340
}
2441
},

valkey/values.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ auth:
172172
# Use an existing secret for user passwords. Key defaults to username.
173173
usersExistingSecret: ""
174174

175+
# Enable the secret injection by another container
176+
injectSecret:
177+
enabled: false
178+
# IMPORTANT: A duplication of a user would overwrite the definition of aclUsers or aclConfig
179+
username: ""
180+
# Same permission syntax as aclUsers
181+
permissions: ""
182+
# Path to secret e.g "/path/secret"
183+
mountPath: ""
184+
175185
# Map of users to create with ACL permissions.
176186
# If usersExistingSecret is set, passwords from the secret take priority over inline passwords.
177187
# NOTE: If using aclUsers, the 'default' user must be included here.
@@ -202,6 +212,7 @@ replica:
202212
# IMPORTANT: When auth.enabled is true, this user MUST be defined in auth.aclUsers.
203213
# The chart requires this to retrieve the password for replica authentication.
204214
# The user must have appropriate replication permissions: +psync +replconf +ping
215+
# When auth.injectSecret.enabled is true, the replicationUser gets ignored and the auth.injectSecret.username gets set.
205216
replicationUser: "default"
206217

207218
# Replication settings

0 commit comments

Comments
 (0)