Skip to content

Commit 69e7da4

Browse files
BlackDarkCopilot
andcommitted
feat: robust agent registration with credential persistence
Solve the 'already registered' error when agent gets SIGKILL'd and restarts. The init container now: 1. Checks if existing credentials on PVC (if enabled) are still valid 2. Falls back to checking emptyDir credentials 3. If valid, skips registration entirely (instant restart) 4. If invalid or missing, registers fresh Also adds: - agent.lapiRegistration.machineName: fixed identity across restarts - PVC mount on init container: reads existing credentials from PVC - Works seamlessly with and without PVC persistence Applied to: DaemonSet, Deployment, and AppSec templates. Inspired by PR crowdsecurity#266 with improvements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent fec4322 commit 69e7da4

5 files changed

Lines changed: 138 additions & 4 deletions

File tree

charts/crowdsec/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type: application
1414
# This is the chart version. This version number should be incremented each time you make changes
1515
# to the chart and its templates, including the app version.
1616
# Versions are expected to follow Semantic Versioning (https://semver.org/)
17-
version: 0.24.0
17+
version: 0.25.0
1818

1919
# This is the version number of the application being deployed. This version number should be
2020
# incremented each time you make changes to the application. Versions are not expected to

charts/crowdsec/templates/agent-daemonSet.yaml

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,39 @@ spec:
5656
- name: wait-for-lapi-and-register
5757
image: "{{ .Values.image.repository | default "crowdsecurity/crowdsec" }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
5858
imagePullPolicy: {{ .Values.image.pullPolicy }}
59-
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']
59+
command:
60+
- sh
61+
- "-c"
62+
- |
63+
until nc "$LAPI_HOST" "$LAPI_PORT" -z; do
64+
echo "waiting for lapi to start"
65+
sleep 5
66+
done
67+
68+
ln -s /staging/etc/crowdsec /etc/crowdsec
69+
70+
# Try to re-use existing credentials (PVC or emptyDir)
71+
CRED_FILE=""
72+
if [ -f "$PVC_CRED_PATH" ]; then
73+
CRED_FILE="$PVC_CRED_PATH"
74+
elif [ -f /tmp_config/local_api_credentials.yaml ]; then
75+
CRED_FILE="/tmp_config/local_api_credentials.yaml"
76+
fi
77+
78+
if [ -n "$CRED_FILE" ]; then
79+
cp "$CRED_FILE" /etc/crowdsec/local_api_credentials.yaml
80+
if cscli lapi status >/dev/null 2>&1; then
81+
echo "Existing credentials valid, skipping registration"
82+
cp "$CRED_FILE" /tmp_config/local_api_credentials.yaml
83+
exit 0
84+
fi
85+
echo "Existing credentials invalid, re-registering"
86+
fi
87+
88+
# Register with LAPI
89+
set -e
90+
cscli lapi register --machine "$USERNAME" -u "$LAPI_URL" --token "$REGISTRATION_TOKEN"
91+
cp /etc/crowdsec/local_api_credentials.yaml /tmp_config/local_api_credentials.yaml
6092
{{- else }}
6193
- name: wait-for-lapi
6294
image: "{{ .Values.agent.wait_for_lapi.image.repository }}:{{ .Values.agent.wait_for_lapi.image.tag }}"
@@ -75,18 +107,35 @@ spec:
75107
volumeMounts:
76108
- name: crowdsec-config
77109
mountPath: /tmp_config
110+
{{- if .Values.agent.persistentVolume.config.enabled }}
111+
- name: crowdsec-agent-config
112+
mountPath: /etc/crowdsec_data
113+
{{- if .Values.agent.persistentVolume.config.subPath }}
114+
subPath: {{ .Values.agent.persistentVolume.config.subPath }}
115+
{{- end }}
116+
{{- end }}
78117
{{- end }}
79118
env:
80119
{{- if or (not .Values.tls.enabled) (not .Values.tls.agent.tlsClientAuth) }}
120+
- name: PVC_CRED_PATH
121+
{{- if .Values.agent.persistentVolume.config.enabled }}
122+
value: "/etc/crowdsec_data/local_api_credentials.yaml"
123+
{{- else }}
124+
value: ""
125+
{{- end }}
81126
- name: REGISTRATION_TOKEN
82127
valueFrom:
83128
secretKeyRef:
84129
name: {{ include "lapi.secretName" . }}
85130
key: {{ include "lapi.registrationTokenKey" . }}
86131
- name: USERNAME
132+
{{- if .Values.agent.lapiRegistration.machineName }}
133+
value: {{ .Values.agent.lapiRegistration.machineName | quote }}
134+
{{- else }}
87135
valueFrom:
88136
fieldRef:
89137
fieldPath: metadata.name
138+
{{- end }}
90139
- name: LAPI_URL
91140
value: "{{ .Values.agent.lapiURL | default (printf "http://%s-service.%s:8080" .Release.Name .Release.Namespace) }}"
92141
{{- end }}

charts/crowdsec/templates/agent-deployment.yaml

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,39 @@ spec:
5757
- name: wait-for-lapi-and-register
5858
image: "{{ .Values.image.repository | default "crowdsecurity/crowdsec" }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
5959
imagePullPolicy: {{ .Values.image.pullPolicy }}
60-
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']
60+
command:
61+
- sh
62+
- "-c"
63+
- |
64+
until nc "$LAPI_HOST" "$LAPI_PORT" -z; do
65+
echo "waiting for lapi to start"
66+
sleep 5
67+
done
68+
69+
ln -s /staging/etc/crowdsec /etc/crowdsec
70+
71+
# Try to re-use existing credentials (PVC or emptyDir)
72+
CRED_FILE=""
73+
if [ -f "$PVC_CRED_PATH" ]; then
74+
CRED_FILE="$PVC_CRED_PATH"
75+
elif [ -f /tmp_config/local_api_credentials.yaml ]; then
76+
CRED_FILE="/tmp_config/local_api_credentials.yaml"
77+
fi
78+
79+
if [ -n "$CRED_FILE" ]; then
80+
cp "$CRED_FILE" /etc/crowdsec/local_api_credentials.yaml
81+
if cscli lapi status >/dev/null 2>&1; then
82+
echo "Existing credentials valid, skipping registration"
83+
cp "$CRED_FILE" /tmp_config/local_api_credentials.yaml
84+
exit 0
85+
fi
86+
echo "Existing credentials invalid, re-registering"
87+
fi
88+
89+
# Register with LAPI
90+
set -e
91+
cscli lapi register --machine "$USERNAME" -u "$LAPI_URL" --token "$REGISTRATION_TOKEN"
92+
cp /etc/crowdsec/local_api_credentials.yaml /tmp_config/local_api_credentials.yaml
6193
{{- else }}
6294
- name: wait-for-lapi
6395
image: "{{ .Values.agent.wait_for_lapi.image.repository }}:{{ .Values.agent.wait_for_lapi.image.tag }}"
@@ -76,18 +108,35 @@ spec:
76108
volumeMounts:
77109
- name: crowdsec-config
78110
mountPath: /tmp_config
111+
{{- if .Values.agent.persistentVolume.config.enabled }}
112+
- name: crowdsec-agent-config
113+
mountPath: /etc/crowdsec_data
114+
{{- if .Values.agent.persistentVolume.config.subPath }}
115+
subPath: {{ .Values.agent.persistentVolume.config.subPath }}
116+
{{- end }}
117+
{{- end }}
79118
{{- end }}
80119
env:
81120
{{- if or (not .Values.tls.enabled) (not .Values.tls.agent.tlsClientAuth) }}
121+
- name: PVC_CRED_PATH
122+
{{- if .Values.agent.persistentVolume.config.enabled }}
123+
value: "/etc/crowdsec_data/local_api_credentials.yaml"
124+
{{- else }}
125+
value: ""
126+
{{- end }}
82127
- name: REGISTRATION_TOKEN
83128
valueFrom:
84129
secretKeyRef:
85130
name: {{ include "lapi.secretName" . }}
86131
key: {{ include "lapi.registrationTokenKey" . }}
87132
- name: USERNAME
133+
{{- if .Values.agent.lapiRegistration.machineName }}
134+
value: {{ .Values.agent.lapiRegistration.machineName | quote }}
135+
{{- else }}
88136
valueFrom:
89137
fieldRef:
90138
fieldPath: metadata.name
139+
{{- end }}
91140
- name: LAPI_URL
92141
value: "{{ .Values.agent.lapiURL | default (printf "http://%s-service.%s:8080" .Release.Name .Release.Namespace) }}"
93142
{{- end }}

charts/crowdsec/templates/appsec-deployment.yaml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,31 @@ spec:
5555
- name: wait-for-lapi-and-register
5656
image: "{{ .Values.image.repository | default "crowdsecurity/crowdsec" }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
5757
imagePullPolicy: {{ .Values.image.pullPolicy }}
58-
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']
58+
command:
59+
- sh
60+
- "-c"
61+
- |
62+
until nc "$LAPI_HOST" "$LAPI_PORT" -z; do
63+
echo "waiting for lapi to start"
64+
sleep 5
65+
done
66+
67+
ln -s /staging/etc/crowdsec /etc/crowdsec
68+
69+
# Re-use existing credentials if they are still valid
70+
if [ -f /tmp_config/local_api_credentials.yaml ]; then
71+
cp /tmp_config/local_api_credentials.yaml /etc/crowdsec/local_api_credentials.yaml
72+
if cscli lapi status >/dev/null 2>&1; then
73+
echo "Existing credentials valid, skipping registration"
74+
exit 0
75+
fi
76+
echo "Existing credentials invalid, re-registering"
77+
fi
78+
79+
# Register with LAPI
80+
set -e
81+
cscli lapi register --machine "$USERNAME" -u "$LAPI_URL" --token "$REGISTRATION_TOKEN"
82+
cp /etc/crowdsec/local_api_credentials.yaml /tmp_config/local_api_credentials.yaml
5983
{{- else }}
6084
- name: wait-for-lapi
6185
image: "{{ .Values.appsec.wait_for_lapi.image.repository }}:{{ .Values.appsec.wait_for_lapi.image.tag }}"

charts/crowdsec/values.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,18 @@ agent:
714714
allowPrivilegeEscalation: false
715715
privileged: false
716716

717+
# -- LAPI registration settings for the agent
718+
lapiRegistration:
719+
# -- Enable LAPI registration init container (auto-register on startup)
720+
## @param agent.lapiRegistration.enabled [default: true] Enable LAPI auto-registration init container
721+
enabled: true
722+
# -- Fixed machine name for the agent (persists across pod restarts).
723+
# If empty, defaults to metadata.name (pod name). Set this to a stable
724+
# name when using Deployments with PVC persistence so the agent re-uses
725+
# the same identity after restarts/rescheduling.
726+
## @param agent.lapiRegistration.machineName [string] Fixed machine name for agent LAPI registration
727+
machineName: ""
728+
717729
# -- Enable AppSec (https://docs.crowdsec.net/docs/next/appsec/intro)
718730
appsec:
719731
# -- Enable AppSec (by default disabled)

0 commit comments

Comments
 (0)