diff --git a/charts/crowdsec/README.md b/charts/crowdsec/README.md index 71e75ba..cc483bb 100644 --- a/charts/crowdsec/README.md +++ b/charts/crowdsec/README.md @@ -59,6 +59,7 @@ lapi: # Specify your external DB password here extraSecrets: dbPassword: + storeCAPICredentialsInSecret: true persistentVolume: # When replicas for LAPI is greater than 1, two options, persistent volumes must be disabled, or in ReadWriteMany mode config: diff --git a/charts/crowdsec/files/docker-start-custom.sh b/charts/crowdsec/files/docker-start-custom.sh new file mode 100644 index 0000000..859bf10 --- /dev/null +++ b/charts/crowdsec/files/docker-start-custom.sh @@ -0,0 +1,511 @@ +#!/bin/bash + +# shellcheck disable=SC2292 # allow [ test ] syntax +# shellcheck disable=SC2310 # allow "if function..." syntax with -e + +set -e +shopt -s inherit_errexit + +# Note that "if function_name" in bash matches when the function returns 0, +# meaning successful execution. + +# match true, TRUE, True, tRuE, etc. +istrue() { + case "$(echo "$1" | tr '[:upper:]' '[:lower:]')" in + true) return 0 ;; + *) return 1 ;; + esac +} + +isfalse() { + if istrue "$1"; then + return 1 + else + return 0 + fi +} + +if istrue "$DEBUG"; then + set -x + export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' +fi + +if istrue "$CI_TESTING"; then + echo "githubciXXXXXXXXXXXXXXXXXXXXXXXX" >/etc/machine-id +fi + +#- DEFAULTS -----------------------# + +export CONFIG_FILE="${CONFIG_FILE:=/etc/crowdsec/config.yaml}" +export CUSTOM_HOSTNAME="${CUSTOM_HOSTNAME:=localhost}" + +#- HELPER FUNCTIONS ----------------# + +# csv2yaml +# generate a yaml list from a comma-separated string of values +csv2yaml() { + [ -z "$1" ] && return + echo "$1" | sed 's/,/\n- /g;s/^/- /g' +} + +# wrap cscli with the correct config file location +cscli() { + command cscli -c "$CONFIG_FILE" "$@" +} + +run_hub_update() { + index_modification_time=$(stat -c %Y /etc/crowdsec/hub/.index.json 2>/dev/null) + # Run cscli hub update if no date or if the index file is older than 24h + if [ -z "$index_modification_time" ] || [ $(( $(date +%s) - index_modification_time )) -gt 86400 ]; then + cscli hub update --with-content + else + echo "Skipping hub update, index file is recent" + fi +} + +is_mounted() { + path=$(readlink -f "$1") + mounts=$(awk '{print $2}' /proc/mounts) + while true; do + if grep -qE ^"$path"$ <<< "$mounts"; then + echo "$path was found in a volume" + return 0 + fi + path=$(dirname "$path") + if [ "$path" = "/" ]; then + return 1 + fi + done + return 1 #unreachable +} + +run_hub_update_if_from_volume() { + if is_mounted "/etc/crowdsec/hub/.index.json"; then + echo "Running hub update" + run_hub_update + else + echo "Skipping hub update, index file is not in a volume" + fi +} + +run_hub_upgrade_if_from_volume() { + isfalse "$NO_HUB_UPGRADE" || return 0 + if is_mounted "/var/lib/crowdsec/data"; then + echo "Running hub upgrade" + cscli hub upgrade + else + echo "Skipping hub upgrade, data directory is not in a volume" + fi + +} + +# conf_get [file_path] +# retrieve a value from a file (by default $CONFIG_FILE) +conf_get() { + if [ $# -ge 2 ]; then + yq e "$1" "$2" + else + cscli config show-yaml | yq e "$1" + fi +} + +# conf_set [file_path] +# evaluate a yq command (by default on $CONFIG_FILE), +# create the file if it doesn't exist +conf_set() { + if [ $# -ge 2 ]; then + YAML_FILE="$2" + else + YAML_FILE="$CONFIG_FILE" + fi + if [ ! -f "$YAML_FILE" ]; then + install -m 0600 /dev/null "$YAML_FILE" + fi + yq e "$1" -i "$YAML_FILE" +} + +# conf_set_if(): used to update the configuration +# only if a given variable is provided +# conf_set_if "$VAR" [file_path] +conf_set_if() { + if [ "$1" != "" ]; then + shift + conf_set "$@" + fi +} + +# register_bouncer +register_bouncer() { + if ! cscli bouncers list -o json | sed '/^ *"name"/!d;s/^ *"name": "\(.*\)",/\1/' | grep -q "^${1}$"; then + if cscli bouncers add "$1" -k "$2" > /dev/null; then + echo "Registered bouncer for $1" + else + echo "Failed to register bouncer for $1" + fi + fi +} + +# Call cscli to manage objects ignoring taint errors +# $1 can be collections, parsers, etc. +# $2 can be install, remove, upgrade +# $3 is a list of object names separated by space +cscli_if_clean() { + local itemtype="$1" + local action="$2" + local objs=$3 + shift 3 + # loop over all objects + for obj in $objs; do + if cscli "$itemtype" inspect "$obj" -o json | yq -e '.tainted // false' >/dev/null 2>&1; then + echo "Object $itemtype/$obj is tainted, skipping" + elif cscli "$itemtype" inspect "$obj" -o json | yq -e '.local // false' >/dev/null 2>&1; then + echo "Object $itemtype/$obj is local, skipping" + else +# # Too verbose? Only show errors if not in debug mode +# if [ "$DEBUG" != "true" ]; then +# error_only=--error +# fi + error_only="" + echo "Running: cscli $error_only $itemtype $action \"$obj\" $*" + # shellcheck disable=SC2086 + if ! cscli $error_only "$itemtype" "$action" "$obj" "$@"; then + echo "Failed to $action $itemtype/$obj, running hub update before retrying" + run_hub_update + # shellcheck disable=SC2086 + cscli $error_only "$itemtype" "$action" "$obj" "$@" + fi + fi + done +} + +# Output the difference between two lists +# of items separated by spaces +difference() { + list1="$1" + list2="$2" + + # split into words + # shellcheck disable=SC2086 + set -- $list1 + for item in "$@"; do + found=false + for i in $list2; do + if [ "$item" = "$i" ]; then + found=true + break + fi + done + if [ "$found" = false ]; then + echo "$item" + fi + done +} + +#-----------------------------------# + +if [ -n "$CERT_FILE" ] || [ -n "$KEY_FILE" ] ; then + printf '%b' '\033[0;33m' + echo "Warning: the variables CERT_FILE and KEY_FILE have been deprecated." >&2 + echo "Please use LAPI_CERT_FILE and LAPI_KEY_FILE insted." >&2 + echo "The old variables will be removed in a future release." >&2 + printf '%b' '\033[0m' + export LAPI_CERT_FILE=${LAPI_CERT_FILE:-$CERT_FILE} + export LAPI_KEY_FILE=${LAPI_KEY_FILE:-$KEY_FILE} +fi + +# Link the preloaded data files when the data dir is mounted (common case) +# The symlinks can be overridden by hub upgrade +for target in "/staging/var/lib/crowdsec/data"/*; do + fname="$(basename "$target")" + # skip the db and wal files + if [[ $fname == crowdsec.db* ]]; then + continue + fi + if [ ! -e "/var/lib/crowdsec/data/$fname" ]; then + ln -s "$target" "/var/lib/crowdsec/data/$fname" + fi +done + +# Check and prestage /etc/crowdsec +if [ ! -e "/etc/crowdsec/local_api_credentials.yaml" ] && [ ! -e "/etc/crowdsec/config.yaml" ]; then + echo "Populating configuration directory..." + # don't overwrite existing configuration files, which may come + # from bind-mount or even be read-only (configmaps) + if [ -e /staging/etc/crowdsec ]; then + mkdir -p /etc/crowdsec/ + # if you change this, check that it still works + # under alpine and k8s, with and without tls + rsync -av --ignore-existing /staging/etc/crowdsec/* /etc/crowdsec + fi +fi + +# do this as soon as we have a config.yaml, to avoid useless warnings +if istrue "$USE_WAL"; then + conf_set '.db_config.use_wal = true' +elif [ -n "$USE_WAL" ] && isfalse "$USE_WAL"; then + conf_set '.db_config.use_wal = false' +fi + +lapi_credentials_path=$(conf_get '.api.client.credentials_path') + +if isfalse "$DISABLE_LOCAL_API"; then + # generate local agent credentials (even if agent is disabled, cscli needs a + # connection to the API) + if ( isfalse "$USE_TLS" || [ "$CLIENT_CERT_FILE" = "" ] ); then + if yq -e '.login==strenv(CUSTOM_HOSTNAME)' "$lapi_credentials_path" >/dev/null && ( cscli machines list -o json | yq -e 'any_c(.machineId==strenv(CUSTOM_HOSTNAME))' >/dev/null ); then + echo "Local agent already registered" + else + echo "Generate local agent credentials" + # if the db is persistent but the credentials are not, we need to + # delete the old machine to generate new credentials + cscli machines delete "$CUSTOM_HOSTNAME" >/dev/null 2>&1 || true + cscli machines add "$CUSTOM_HOSTNAME" --auto --force + fi + fi + + echo "Check if lapi needs to register an additional agent" + # pre-registration is not needed with TLS authentication, but we can have TLS transport with user/pw + if [ "$AGENT_USERNAME" != "" ] && [ "$AGENT_PASSWORD" != "" ] ; then + # re-register because pw may have been changed + cscli machines add "$AGENT_USERNAME" --password "$AGENT_PASSWORD" -f /dev/null --force + echo "Agent registered to lapi" + fi +fi + +# ---------------- + +conf_set_if "$LOCAL_API_URL" '.url = strenv(LOCAL_API_URL)' "$lapi_credentials_path" + +if istrue "$DISABLE_LOCAL_API"; then + # we only use the envvars that are actually defined + # in case of persistent configuration + conf_set_if "$AGENT_USERNAME" '.login = strenv(AGENT_USERNAME)' "$lapi_credentials_path" + conf_set_if "$AGENT_PASSWORD" '.password = strenv(AGENT_PASSWORD)' "$lapi_credentials_path" +fi + +conf_set_if "$INSECURE_SKIP_VERIFY" '.api.client.insecure_skip_verify = env(INSECURE_SKIP_VERIFY)' + +# agent-only containers still require USE_TLS +if istrue "$USE_TLS"; then + # shellcheck disable=SC2153 + conf_set_if "$CACERT_FILE" '.ca_cert_path = strenv(CACERT_FILE)' "$lapi_credentials_path" + conf_set_if "$CLIENT_KEY_FILE" '.key_path = strenv(CLIENT_KEY_FILE)' "$lapi_credentials_path" + conf_set_if "$CLIENT_CERT_FILE" '.cert_path = strenv(CLIENT_CERT_FILE)' "$lapi_credentials_path" +else + conf_set ' + del(.ca_cert_path) | + del(.key_path) | + del(.cert_path) + ' "$lapi_credentials_path" +fi + +if istrue "$DISABLE_ONLINE_API"; then + conf_set 'del(.api.server.online_client)' +fi + +# Enroll instance if enroll key is provided +if isfalse "$DISABLE_LOCAL_API" && isfalse "$DISABLE_ONLINE_API" && [ "$ENROLL_KEY" != "" ]; then + enroll_args="" + if [ "$ENROLL_INSTANCE_NAME" != "" ]; then + enroll_args="--name $ENROLL_INSTANCE_NAME" + fi + if [ "$ENROLL_TAGS" != "" ]; then + # shellcheck disable=SC2086 + for tag in ${ENROLL_TAGS}; do + enroll_args="$enroll_args --tags $tag" + done + fi + # shellcheck disable=SC2086 + cscli console enroll $enroll_args "$ENROLL_KEY" +fi + +# crowdsec sqlite database permissions +if [ "$GID" != "" ]; then + if istrue "$(conf_get '.db_config.type == "sqlite"')"; then + # force the creation of the db file(s) + cscli machines inspect create-db --error >/dev/null 2>&1 || : + # don't fail if the db is not there yet + if chown -f ":$GID" "$(conf_get '.db_config.db_path')" 2>/dev/null; then + echo "sqlite database permissions updated" + fi + fi +fi + +if isfalse "$DISABLE_LOCAL_API" && istrue "$USE_TLS"; then + agents_allowed_yaml=$(csv2yaml "$AGENTS_ALLOWED_OU") + export agents_allowed_yaml + bouncers_allowed_yaml=$(csv2yaml "$BOUNCERS_ALLOWED_OU") + export bouncers_allowed_yaml + conf_set_if "$CACERT_FILE" '.api.server.tls.ca_cert_path = strenv(CACERT_FILE)' + conf_set_if "$LAPI_CERT_FILE" '.api.server.tls.cert_file = strenv(LAPI_CERT_FILE)' + conf_set_if "$LAPI_KEY_FILE" '.api.server.tls.key_file = strenv(LAPI_KEY_FILE)' + conf_set_if "$BOUNCERS_ALLOWED_OU" '.api.server.tls.bouncers_allowed_ou = env(bouncers_allowed_yaml)' + conf_set_if "$AGENTS_ALLOWED_OU" '.api.server.tls.agents_allowed_ou = env(agents_allowed_yaml)' +else + conf_set 'del(.api.server.tls)' +fi + +conf_set_if "$PLUGIN_DIR" '.config_paths.plugin_dir = strenv(PLUGIN_DIR)' + +## Install hub items + +run_hub_update_if_from_volume || true +run_hub_upgrade_if_from_volume || true + +cscli_if_clean parsers install crowdsecurity/docker-logs +cscli_if_clean parsers install crowdsecurity/cri-logs + +if [ "$COLLECTIONS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean collections install "$(difference "$COLLECTIONS" "$DISABLE_COLLECTIONS")" +fi + +if [ "$PARSERS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean parsers install "$(difference "$PARSERS" "$DISABLE_PARSERS")" +fi + +if [ "$SCENARIOS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean scenarios install "$(difference "$SCENARIOS" "$DISABLE_SCENARIOS")" +fi + +if [ "$POSTOVERFLOWS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean postoverflows install "$(difference "$POSTOVERFLOWS" "$DISABLE_POSTOVERFLOWS")" +fi + +if [ "$CONTEXTS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean contexts install "$(difference "$CONTEXTS" "$DISABLE_CONTEXTS")" +fi + +if [ "$APPSEC_CONFIGS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean appsec-configs install "$(difference "$APPSEC_CONFIGS" "$DISABLE_APPSEC_CONFIGS")" +fi + +if [ "$APPSEC_RULES" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean appsec-rules install "$(difference "$APPSEC_RULES" "$DISABLE_APPSEC_RULES")" +fi + +## Remove collections, parsers, scenarios & postoverflows +if [ "$DISABLE_COLLECTIONS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean collections remove "$DISABLE_COLLECTIONS" --force +fi + +if [ "$DISABLE_PARSERS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean parsers remove "$DISABLE_PARSERS" --force +fi + +if [ "$DISABLE_SCENARIOS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean scenarios remove "$DISABLE_SCENARIOS" --force +fi + +if [ "$DISABLE_POSTOVERFLOWS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean postoverflows remove "$DISABLE_POSTOVERFLOWS" --force +fi + +if [ "$DISABLE_CONTEXTS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean contexts remove "$DISABLE_CONTEXTS" --force +fi + +if [ "$DISABLE_APPSEC_CONFIGS" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean appsec-configs remove "$DISABLE_APPSEC_CONFIGS" --force +fi + +if [ "$DISABLE_APPSEC_RULES" != "" ]; then + # shellcheck disable=SC2086 + cscli_if_clean appsec-rules remove "$DISABLE_APPSEC_RULES" --force +fi + +## Register bouncers via env +for BOUNCER in $(compgen -A variable | grep -i BOUNCER_KEY); do + KEY=$(printf '%s' "${!BOUNCER}") + NAME=$(printf '%s' "$BOUNCER" | cut -d_ -f3-) + if [[ -n $KEY ]] && [[ -n $NAME ]]; then + register_bouncer "$NAME" "$KEY" + fi +done + +if [ "$ENABLE_CONSOLE_MANAGEMENT" != "" ]; then + # shellcheck disable=SC2086 + cscli console enable console_management +fi + +## Register bouncers via secrets (Swarm only) +shopt -s nullglob extglob +for BOUNCER in /run/secrets/@(bouncer_key|BOUNCER_KEY)* ; do + KEY=$(cat "${BOUNCER}") + NAME=$(echo "${BOUNCER}" | awk -F "/" '{printf $NF}' | cut -d_ -f2-) + if [[ -n $KEY ]] && [[ -n $NAME ]]; then + register_bouncer "$NAME" "$KEY" + fi +done +shopt -u nullglob extglob + +# set all options before validating the configuration + +conf_set_if "$CAPI_WHITELISTS_PATH" '.api.server.capi_whitelists_path = strenv(CAPI_WHITELISTS_PATH)' +conf_set_if "$METRICS_PORT" '.prometheus.listen_port=env(METRICS_PORT)' + +if istrue "$DISABLE_LOCAL_API"; then + conf_set '.api.server.enable=false' +else + conf_set '.api.server.enable=true' +fi + +ARGS="" +if [ "$CONFIG_FILE" != "" ]; then + ARGS="-c $CONFIG_FILE" +fi + +if [ "$DSN" != "" ]; then + ARGS="$ARGS -dsn ${DSN}" +fi + +if [ "$TYPE" != "" ]; then + ARGS="$ARGS -type $TYPE" +fi + +if istrue "$TEST_MODE"; then + ARGS="$ARGS -t" +fi + +if istrue "$DISABLE_AGENT"; then + ARGS="$ARGS -no-cs" +fi + +if istrue "$LEVEL_TRACE"; then + ARGS="$ARGS -trace" +fi + +if istrue "$LEVEL_DEBUG"; then + ARGS="$ARGS -debug" +fi + +if istrue "$LEVEL_INFO"; then + ARGS="$ARGS -info" +fi + +if istrue "$LEVEL_WARN"; then + ARGS="$ARGS -warning" +fi + +if istrue "$LEVEL_ERROR"; then + ARGS="$ARGS -error" +fi + +if istrue "$LEVEL_FATAL"; then + ARGS="$ARGS -fatal" +fi + +# shellcheck disable=SC2086 +exec crowdsec $ARGS \ No newline at end of file diff --git a/charts/crowdsec/templates/_helpers.tpl b/charts/crowdsec/templates/_helpers.tpl index 6aba98b..733df34 100644 --- a/charts/crowdsec/templates/_helpers.tpl +++ b/charts/crowdsec/templates/_helpers.tpl @@ -91,3 +91,16 @@ true true {{- end -}} {{- end -}} + +{{/* + Check if DISABLE_ONLINE_API is set in lapi.env and store it in a variable +*/}} +{{ define "IsOnlineAPIDisabled" }} +{{- $IsCAPIDisabled := false -}} +{{- range .Values.lapi.env }} + {{- if and (eq .name "DISABLE_ONLINE_API") (eq .value "true") }} + {{- $IsCAPIDisabled = true -}} + {{- end -}} +{{- end -}} +{{- $IsCAPIDisabled }} +{{- end }} \ No newline at end of file diff --git a/charts/crowdsec/templates/capi-credentials-secrets.yaml b/charts/crowdsec/templates/capi-credentials-secrets.yaml new file mode 100644 index 0000000..4d516f2 --- /dev/null +++ b/charts/crowdsec/templates/capi-credentials-secrets.yaml @@ -0,0 +1,20 @@ +{{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} +{{- if .Values.lapi.storeCAPICredentialsInSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Release.Name }}-capi-credentials + labels: + k8s-app: {{ .Release.Name }} + type: capi-credentials-job + version: v1 + annotations: + "helm.sh/hook": "pre-install" + "helm.sh/hook-weight": "-1" + "helm.sh/resource-policy": "keep" +type: Opaque +data: + online_api_credentials.yaml: | + {{ printf "url: \"placeholder\"\nlogin: \"placeholder\"\npassword: \"placeholder\"" | b64enc }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/crowdsec/templates/capi-register-job.yaml b/charts/crowdsec/templates/capi-register-job.yaml new file mode 100644 index 0000000..c301594 --- /dev/null +++ b/charts/crowdsec/templates/capi-register-job.yaml @@ -0,0 +1,59 @@ +{{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} +{{- if .Values.lapi.storeCAPICredentialsInSecret }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-capi-register-job + labels: + k8s-app: {{ .Release.Name }} + type: capi-register-job + version: v1 + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": "0" +spec: + template: + spec: + serviceAccountName: {{ .Release.Name }}-configmap-updater-sa + restartPolicy: OnFailure + volumes: + - name: {{ .Release.Name }}-capi-credentials-volume + secret: + secretName: {{ .Release.Name }}-capi-credentials + containers: + - name: capi-register + {{- if .Values.image.pullSecrets }} + imagePullSecrets: +{{ toYaml .Values.image.pullSecrets | indent 12 }} + {{- end }} + image: "{{ .Values.image.repository | default "crowdsecurity/crowdsec" }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: + - "/bin/bash" + - "-c" + - | + apk update && apk add curl jq kubectl + set -x + echo "check if the Central API credentials are already present" + cp /staging/etc/crowdsec/config.yaml /etc/crowdsec/config.yaml + cp /staging/etc/crowdsec/profiles.yaml /etc/crowdsec/profiles.yaml + sed -i /etc/crowdsec/config.yaml -e 's/#credentials_path/ credentials_path/' + if grep -q "placeholder" /etc/crowdsec/online_api_credentials.yaml; then + echo "Registering this instance to the Central API" + cscli capi register -f /tmp/online_api_credentials.yaml + SECRET_CONTENT="$(cat /tmp/online_api_credentials.yaml | yq '.papi_url = "https://papi.api.crowdsec.net/"' | base64 -w0)" + PATCH=$(jq -n --arg value "$(echo -e "$SECRET_CONTENT")" '[{op: "replace", path: "/data/online_api_credentials.yaml", value: $value}]') + + echo "Updating the Central API credentials in the secret" + kubectl -n {{ .Release.Namespace }} patch secret {{ .Release.Name }}-capi-credentials --type json -p "$PATCH" + else + echo "Central API credentials are already present, skipping registration" + exit 0 + fi + volumeMounts: + - name: {{ .Release.Name }}-capi-credentials-volume + mountPath: /etc/crowdsec/online_api_credentials.yaml + subPath: online_api_credentials.yaml +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/crowdsec/templates/docker-start-configmap.yaml b/charts/crowdsec/templates/docker-start-configmap.yaml new file mode 100644 index 0000000..bd9995c --- /dev/null +++ b/charts/crowdsec/templates/docker-start-configmap.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: crowdsec-docker-start-script-configmap + labels: + k8s-app: crowdsec + type: docker-start-script + version: v1 + +data: + docker_start.sh: |- +{{ (.Files.Get "files/docker-start-custom.sh") | indent 8 }} \ No newline at end of file diff --git a/charts/crowdsec/templates/lapi-deployment.yaml b/charts/crowdsec/templates/lapi-deployment.yaml index 0d951f5..7462806 100644 --- a/charts/crowdsec/templates/lapi-deployment.yaml +++ b/charts/crowdsec/templates/lapi-deployment.yaml @@ -1,6 +1,10 @@ # vim: set ft=gotmpl: --- - +{{- if .Values.lapi.persistentVolume.config.enabled }} +{{- if .Values.lapi.storeCAPICredentialsInSecret }} +{{- fail "lapi.persistentVolume.config.enabled and lapi.storeCAPICredentialsInSecret values are mutually exclusive" }} +{{- end }} +{{- end }} apiVersion: apps/v1 kind: Deployment metadata: @@ -189,14 +193,24 @@ spec: protocol: TCP {{- end }} {{ if .Values.lapi.persistentVolume.config.enabled }} - command: ['sh', '-c', 'mv -n /staging/etc/crowdsec/* /etc/crowdsec_data/ && rm -rf /staging/etc/crowdsec && ln -s /etc/crowdsec_data /etc/crowdsec && ./docker_start.sh'] + command: ['sh', '-c', 'cp -R /staging/etc/crowdsec/* /etc/crowdsec_data/ && ln -s /etc/crowdsec_data /etc/crowdsec && bash /docker_start.sh'] {{ end }} {{- if .Values.lapi.lifecycle }} lifecycle: {{- toYaml .Values.lapi.lifecycle | nindent 10 }} {{- end }} - {{- if or (.Values.tls.enabled) (.Values.lapi.persistentVolume.data.enabled) (.Values.lapi.persistentVolume.config.enabled) (.Values.lapi.dashboard.enabled) (include "lapiCustomConfigIsNotEmpty" .) (.Values.lapi.extraVolumeMounts) }} volumeMounts: + - name: crowdsec-docker-start-script + mountPath: /docker_start.sh + subPath: docker_start.sh + {{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} + {{- if .Values.lapi.storeCAPICredentialsInSecret }} + - name: {{ .Release.Name }}-capi-credentials-volume + mountPath: /staging/etc/crowdsec/online_api_credentials.yaml + subPath: online_api_credentials.yaml + {{- end }} + {{- end }} + {{- if or (.Values.tls.enabled) (.Values.lapi.persistentVolume.data.enabled) (.Values.lapi.persistentVolume.config.enabled) (.Values.lapi.dashboard.enabled) (include "lapiCustomConfigIsNotEmpty" .) (.Values.lapi.extraVolumeMounts) }} {{- if .Values.tls.enabled }} - name: crowdsec-lapi-tls mountPath: /etc/ssl/crowdsec-lapi @@ -312,8 +326,18 @@ spec: {{- end }} terminationGracePeriodSeconds: 30 - {{- if or (.Values.tls.enabled) (.Values.lapi.persistentVolume.data.enabled) (.Values.lapi.persistentVolume.config.enabled) (.Values.lapi.dashboard.enabled) (include "lapiCustomConfigIsNotEmpty" .) (.Values.lapi.extraVolumes) }} volumes: + - name: crowdsec-docker-start-script + configMap: + name: crowdsec-docker-start-script-configmap + {{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} + {{- if .Values.lapi.storeCAPICredentialsInSecret }} + - name: {{ .Release.Name }}-capi-credentials-volume + secret: + secretName: {{ .Release.Name }}-capi-credentials + {{- end }} + {{- end }} + {{- if or (.Values.tls.enabled) (.Values.lapi.persistentVolume.data.enabled) (.Values.lapi.persistentVolume.config.enabled) (.Values.lapi.dashboard.enabled) (include "lapiCustomConfigIsNotEmpty" .) (.Values.lapi.extraVolumes) }} {{- if .Values.lapi.persistentVolume.data.enabled }} - name: crowdsec-db persistentVolumeClaim: @@ -399,4 +423,4 @@ spec: topologySpreadConstraints: {{- toYaml . | nindent 8 }} {{- end }} - priorityClassName: {{ .Values.lapi.priorityClassName }} + priorityClassName: {{ .Values.lapi.priorityClassName }} \ No newline at end of file diff --git a/charts/crowdsec/templates/role.yaml b/charts/crowdsec/templates/role.yaml new file mode 100644 index 0000000..2b77b4d --- /dev/null +++ b/charts/crowdsec/templates/role.yaml @@ -0,0 +1,22 @@ +{{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} +{{- if .Values.lapi.storeCAPICredentialsInSecret }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-configmap-updater-role + labels: + k8s-app: {{ .Release.Name }} + type: capi-register-job + version: v1 + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": "-1" +rules: + - apiGroups: [""] + resources: ["secrets"] + resourceNames: ["{{ .Release.Name }}-capi-credentials"] + verbs: ["get", "patch"] +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/crowdsec/templates/rolebinding.yaml b/charts/crowdsec/templates/rolebinding.yaml new file mode 100644 index 0000000..530cc4a --- /dev/null +++ b/charts/crowdsec/templates/rolebinding.yaml @@ -0,0 +1,25 @@ +{{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} +{{- if .Values.lapi.storeCAPICredentialsInSecret }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-configmap-updater-binding + labels: + k8s-app: {{ .Release.Name }} + type: capi-register-job + version: v1 + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": "-1" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-configmap-updater-role +subjects: + - kind: ServiceAccount + name: {{ .Release.Name }}-configmap-updater-sa + namespace: {{ .Release.Namespace }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/crowdsec/templates/serviceaccount.yaml b/charts/crowdsec/templates/serviceaccount.yaml new file mode 100644 index 0000000..726e8c1 --- /dev/null +++ b/charts/crowdsec/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if not (eq (include "IsOnlineAPIDisabled" .) "true") }} +{{- if .Values.lapi.storeCAPICredentialsInSecret }} +apiVersion: v1 +kind: ServiceAccount +metadata: + namespace: {{ .Release.Namespace }} + name: {{ .Release.Name }}-configmap-updater-sa + labels: + k8s-app: {{ .Release.Name }} + type: capi-register-job + version: v1 + annotations: + "helm.sh/hook": "pre-install,pre-upgrade" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded + "helm.sh/hook-weight": "-1" +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/crowdsec/values.yaml b/charts/crowdsec/values.yaml index 35d5c27..261404f 100644 --- a/charts/crowdsec/values.yaml +++ b/charts/crowdsec/values.yaml @@ -300,6 +300,10 @@ lapi: # postStart: # exec: # command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] + + # -- storeCAPICredentialsInSecret + # -- If set to true, the Central API credentials will be stored in a secret (to use when lapi replicas > 1) + storeCAPICredentialsInSecret: false # agent will deploy pod on every node as daemonSet to read wanted pods logs agent: