Skip to content

Commit 32c5f72

Browse files
committed
Support re-using LAPI credentials in Agent and AppSec
- Stores credentials as an encrypted POD annotation - Retries registration even if credentials exist, but are not valid anymore - Uses additional containers to supply extra tools needed rather than using apk* *Using apk at runtime is not a good practice and won't work in air-gapped environments Fixes: #252 /kind enhancement /area configuration Signed-off-by: Armin Krezović <krezovic.armin@gmail.com>
1 parent f003eb1 commit 32c5f72

9 files changed

Lines changed: 539 additions & 5 deletions

charts/crowdsec/templates/_helpers.tpl

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,34 @@ csLapiSecret
139139
{{- else -}}
140140
registrationToken
141141
{{- end -}}
142-
{{- end -}}
142+
{{- end -}}
143+
144+
{{/**
145+
Provide an external secret for Credential Encryption
146+
*/}}
147+
{{ define "config.encryptionSecretName" }}
148+
{{- if .Values.secrets.encryption.name -}}
149+
{{- .Values.secrets.encryption.name -}}
150+
{{- else -}}
151+
{{ .Release.Name }}-config
152+
{{- end -}}
153+
{{- end -}}
154+
155+
{{/*
156+
Generate ENCRYPTION_SECRET if not specified in values
157+
*/}}
158+
{{ define "config.encryptionSecretValue" }}
159+
{{- if .Values.secrets.encryption.value }}
160+
{{- .Values.secrets.encryption.value -}}
161+
{{- else if (lookup "v1" "Secret" .Release.Namespace (include "config.encryptionSecretName" .)).data }}
162+
{{- $obj := (lookup "v1" "Secret" .Release.Namespace (include "config.encryptionSecretName" .)).data -}}
163+
{{- $val := index $obj "encryptionSecret" -}}
164+
{{- if empty $val }}
165+
{{- randAlphaNum 32 -}}
166+
{{- else }}
167+
{{- $val | b64dec -}}
168+
{{- end -}}
169+
{{- else -}}
170+
{{- randAlphaNum 32 -}}
171+
{{- end -}}
172+
{{- end -}}

charts/crowdsec/templates/agent-daemonSet.yaml

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ spec:
2121
annotations:
2222
checksum/agent-configmap: {{ include (print $.Template.BasePath "/agent-configmap.yaml") . | sha256sum }}
2323
checksum/acquis-configmap: {{ include (print $.Template.BasePath "/acquis-configmap.yaml") . | sha256sum }}
24+
{{- if or (not .Values.tls.enabled) (not .Values.tls.appsec.tlsClientAuth) }}
25+
internal/local-api-credentials: ""
26+
{{- end }}
2427
{{- if .Values.podAnnotations }}
2528
{{ toYaml .Values.podAnnotations | trim | indent 8 }}
2629
{{- end }}
@@ -37,6 +40,9 @@ spec:
3740
{{ toYaml .Values.agent.podLabels | trim | indent 8 }}
3841
{{- end }}
3942
spec:
43+
{{- if or (not .Values.tls.enabled) (not .Values.tls.appsec.tlsClientAuth) }}
44+
serviceAccountName: {{ .Release.Name }}-config
45+
{{- end }}
4046
{{- with .Values.agent.tolerations }}
4147
tolerations:
4248
{{- toYaml . | nindent 8 }}
@@ -47,10 +53,123 @@ spec:
4753
{{- end }}
4854
initContainers:
4955
{{- if or (not .Values.tls.enabled) (not .Values.tls.agent.tlsClientAuth) }}
56+
{{- if .Values.utils.kubectl.enabled }}
57+
- name: install-kubectl
58+
image: "{{ .Values.utils.kubectl.image.repository }}:{{ .Values.utils.kubectl.image.tag }}"
59+
imagePullPolicy: {{ .Values.utils.kubectl.image.pullPolicy }}
60+
command:
61+
- sh
62+
- "-c"
63+
- |
64+
for f in $FILES_TO_COPY; do
65+
f_name=$(basename "$f")
66+
67+
if test ! -f "$f"; then
68+
echo "File $f not found, ignoring"
69+
continue
70+
fi
71+
72+
rm -rf "/utils/$f_name"
73+
install -v -Dm755 "$f" "/utils/$f_name"
74+
done
75+
env:
76+
- name: FILES_TO_COPY
77+
value: {{ .Values.utils.kubectl.files | default "/usr/bin/kubectl" }}
78+
resources:
79+
limits:
80+
memory: 100Mi
81+
requests:
82+
cpu: 1m
83+
memory: 10Mi
84+
securityContext:
85+
allowPrivilegeEscalation: false
86+
privileged: false
87+
runAsUser: 65534
88+
runAsGroup: 65534
89+
volumeMounts:
90+
- name: crowdsec-utils
91+
mountPath: /utils
92+
{{- end }}
93+
{{- if .Values.utils.openssl.enabled }}
94+
- name: install-openssl
95+
image: "{{ .Values.utils.openssl.image.repository }}:{{ .Values.utils.openssl.image.tag }}"
96+
imagePullPolicy: {{ .Values.utils.openssl.image.pullPolicy }}
97+
command:
98+
- sh
99+
- "-c"
100+
- |
101+
for f in $FILES_TO_COPY; do
102+
f_name=$(basename "$f")
103+
104+
if test ! -f "$f"; then
105+
echo "File $f not found, ignoring"
106+
continue
107+
fi
108+
109+
rm -rf "/utils/$f_name"
110+
install -v -Dm755 "$f" "/utils/$f_name"
111+
done
112+
env:
113+
- name: FILES_TO_COPY
114+
value: {{ .Values.utils.openssl.files | default "/usr/bin/openssl /usr/lib/libcrypto.so.3 /usr/lib/libssl.so.3" }}
115+
resources:
116+
limits:
117+
memory: 100Mi
118+
requests:
119+
cpu: 1m
120+
memory: 10Mi
121+
securityContext:
122+
allowPrivilegeEscalation: false
123+
privileged: false
124+
runAsUser: 65534
125+
runAsGroup: 65534
126+
volumeMounts:
127+
- name: crowdsec-utils
128+
mountPath: /utils
129+
{{- end }}
50130
- name: wait-for-lapi-and-register
51131
image: "{{ .Values.image.repository | default "crowdsecurity/crowdsec" }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
52132
imagePullPolicy: {{ .Values.image.pullPolicy }}
53-
command: ['sh', '-c', 'until nc "$LAPI_HOST" "$LAPI_PORT" -z; do echo waiting for lapi to start; sleep 5; done; ln -s /staging/etc/crowdsec /etc/crowdsec && cscli lapi register --machine "$USERNAME" -u "$LAPI_URL" --token "$REGISTRATION_TOKEN" && cp /etc/crowdsec/local_api_credentials.yaml /tmp_config/local_api_credentials.yaml']
133+
command:
134+
- sh
135+
- "-c"
136+
- |
137+
until nc "$LAPI_HOST" "$LAPI_PORT" -z; do
138+
echo waiting for lapi to start
139+
sleep 5
140+
done
141+
142+
ln -s /staging/etc/crowdsec /etc/crowdsec
143+
144+
export PATH=/utils:$PATH
145+
export LD_LIBRARY_PATH=/utils
146+
147+
if test -n "$EXISTING_CREDENTIALS"; then
148+
set -e
149+
echo "$EXISTING_CREDENTIALS" | base64 -d > /tmp/local_api_credentials.yaml.enc
150+
openssl aes-256-cbc -d -pbkdf2 -pass env:ENCRYPTION_SECRET -in /tmp/local_api_credentials.yaml.enc -out /tmp/local_api_credentials.yaml
151+
install -Dm644 /tmp/local_api_credentials.yaml /etc/crowdsec/local_api_credentials.yaml
152+
set +e
153+
154+
cscli lapi status &>/dev/null
155+
val=$?
156+
157+
if test $val -eq 0
158+
then
159+
echo "Credentials found and valid"
160+
exit 0
161+
else
162+
echo "Credentials found but not valid, trying re-register"
163+
fi
164+
fi
165+
166+
set -e
167+
cscli lapi register --machine "$USERNAME" -u "$LAPI_URL" --token "$REGISTRATION_TOKEN"
168+
cp /etc/crowdsec/local_api_credentials.yaml /tmp_config/local_api_credentials.yaml
169+
170+
openssl aes-256-cbc -e -pbkdf2 -pass env:ENCRYPTION_SECRET -in /etc/crowdsec/local_api_credentials.yaml -out /tmp/local_api_credentials.yaml.enc
171+
SECRET=$(base64 -w0 /tmp/local_api_credentials.yaml.enc)
172+
kubectl annotate --overwrite pod $POD_NAME internal/local-api-credentials=$SECRET &>/dev/null
54173
{{- else }}
55174
- name: wait-for-lapi
56175
image: "{{ .Values.agent.wait_for_lapi.image.repository }}:{{ .Values.agent.wait_for_lapi.image.tag }}"
@@ -68,6 +187,8 @@ spec:
68187
privileged: false
69188
{{- if or (not .Values.tls.enabled) (not .Values.tls.agent.tlsClientAuth) }}
70189
volumeMounts:
190+
- name: crowdsec-utils
191+
mountPath: /utils
71192
- name: crowdsec-config
72193
mountPath: /tmp_config
73194
{{- end }}
@@ -84,6 +205,19 @@ spec:
84205
fieldPath: metadata.name
85206
- name: LAPI_URL
86207
value: "{{ .Values.agent.lapiURL | default (printf "http://%s-service.%s:8080" .Release.Name .Release.Namespace) }}"
208+
- name: ENCRYPTION_SECRET
209+
valueFrom:
210+
secretKeyRef:
211+
name: {{ include "config.encryptionSecretName" . }}
212+
key: encryptionSecret
213+
- name: POD_NAME
214+
valueFrom:
215+
fieldRef:
216+
fieldPath: metadata.name
217+
- name: EXISTING_CREDENTIALS
218+
valueFrom:
219+
fieldRef:
220+
fieldPath: metadata.annotations['internal/local-api-credentials']
87221
{{- end }}
88222
- name: LAPI_HOST
89223
value: "{{ .Values.agent.lapiHost | default (printf "%s-service.%s" .Release.Name .Release.Namespace) }}"
@@ -250,6 +384,8 @@ spec:
250384
{{- if or (not .Values.tls.enabled) (not .Values.tls.agent.tlsClientAuth) }}
251385
- name: crowdsec-config
252386
emptyDir: {}
387+
- name: crowdsec-utils
388+
emptyDir: {}
253389
{{- end }}
254390
{{- if .Values.agent.hostVarLog }}
255391
- name: varlog

0 commit comments

Comments
 (0)