Docker refactoring, tls setup (#1869)

This commit is contained in:
mmetc 2022-11-28 10:35:12 +01:00 committed by GitHub
parent c5079ac15e
commit fde9640364
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 377 additions and 156 deletions

View file

@ -1,21 +1,60 @@
#!/bin/bash
# Set the crowdsec config file
CS_CONFIG_FILE="/etc/crowdsec/config.yaml"
if [ "$CONFIG_FILE" != "" ]; then
CS_CONFIG_FILE="$CONFIG_FILE"
fi
# shellcheck disable=SC2292 # allow [ test ] syntax
# shellcheck disable=SC2310 # allow "if function..." syntax with -e
# TLS defaults
CERT_FILE="${CERT_FILE:-/etc/ssl/cert.pem}"
KEY_FILE="${KEY_FILE:-/etc/ssl/key.pem}"
set -e
shopt -s inherit_errexit
# Plugins directory default
PLUGIN_DIR="${PLUGIN_DIR:-/usr/local/lib/crowdsec/plugins/}"
#- HELPER FUNCTIONS ----------------#
# Check & prestage databases
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
}
# 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" "$@"
}
conf_get() {
if [ $# -ge 2 ]; then
yq e "$1" "$2"
else
yq e "$1" "$CONFIG_FILE"
fi
}
conf_set() {
if [ $# -ge 2 ]; then
yq e "$1" -i "$2"
else
yq e "$1" -i "$CONFIG_FILE"
fi
}
#-----------------------------------#
# Check and prestage databases
for geodb in GeoLite2-ASN.mmdb GeoLite2-City.mmdb; do
# We keep the pre-populated geoib databases in /staging instead of /var,
# We keep the pre-populated geoip databases in /staging instead of /var,
# because if the data directory is bind-mounted from the host, it will be
# empty and the files will be out of reach, requiring a runtime download.
# We link to them to save about 80Mb compared to cp/mv.
@ -25,132 +64,158 @@ for geodb in GeoLite2-ASN.mmdb GeoLite2-City.mmdb; do
fi
done
#Check & prestage /etc/crowdsec
# Check and prestage /etc/crowdsec
if [ ! -e "/etc/crowdsec/local_api_credentials.yaml" ] && [ ! -e "/etc/crowdsec/config.yaml" ]; then
mkdir -p /etc/crowdsec
cp -r /staging/etc/* /etc/
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
cp -an /staging/etc/crowdsec/* /etc/crowdsec/
fi
fi
# regenerate local agent credentials (ignore if agent is disabled)
if [ "$DISABLE_AGENT" == "" ] ; then
echo "Regenerate local agent credentials"
cscli -c "$CS_CONFIG_FILE" machines delete "${CUSTOM_HOSTNAME:-localhost}"
if [ "$LOCAL_API_URL" != "" ] ; then
cscli -c "$CS_CONFIG_FILE" machines add "${CUSTOM_HOSTNAME:-localhost}" --auto --url "$LOCAL_API_URL"
else
cscli -c "$CS_CONFIG_FILE" machines add "${CUSTOM_HOSTNAME:-localhost}" --auto
if isfalse "$DISABLE_AGENT"; then
if isfalse "$DISABLE_LOCAL_API"; then
echo "Regenerate local agent credentials"
cscli machines delete "$CUSTOM_HOSTNAME"
# shellcheck disable=SC2086
cscli machines add "$CUSTOM_HOSTNAME" --auto --url "$LOCAL_API_URL"
fi
if [ "$AGENT_USERNAME" != "" ] && [ "$AGENT_PASSWORD" != "" ] && [ "$LOCAL_API_URL" != "" ] ; then
echo "set up lapi credentials for agent"
CONFIG_PATH=$(yq eval '.api.client.credentials_path' "$CS_CONFIG_FILE" )
echo "url: $LOCAL_API_URL" > "$CONFIG_PATH"
echo "login: $AGENT_USERNAME" >> "$CONFIG_PATH"
echo "password: $AGENT_PASSWORD" >> "$CONFIG_PATH"
lapi_credentials_path=$(conf_get '.api.client.credentials_path')
if istrue "$USE_TLS"; then
install -m 0600 /dev/null "$lapi_credentials_path"
conf_set '
.url = strenv(LOCAL_API_URL) |
.ca_cert_path = strenv(CACERT_FILE) |
.key_path = strenv(KEY_FILE) |
.cert_path = strenv(CERT_FILE)
' "$lapi_credentials_path"
elif [ "$AGENT_USERNAME" != "" ]; then
install -m 0600 /dev/null "$lapi_credentials_path"
conf_set '
.url = strenv(LOCAL_API_URL) |
.login = strenv(AGENT_USERNAME) |
.password = strenv(AGENT_PASSWORD)
' "$lapi_credentials_path"
fi
fi
# Check if lapi needs to automatically register an agent
echo "Check if lapi need to register automatically an agent"
if [ "$DISABLE_LOCAL_API" == "" ] && [ "$AGENT_USERNAME" != "" ] && [ "$AGENT_PASSWORD" != "" ] ; then
if [ "$LOCAL_API_URL" != "" ] ; then
cscli -c "$CS_CONFIG_FILE" machines add "$AGENT_USERNAME" --password "$AGENT_PASSWORD" --url "$LOCAL_API_URL"
else
cscli -c "$CS_CONFIG_FILE" machines add "$AGENT_USERNAME" --password "$AGENT_PASSWORD"
if isfalse "$DISABLE_LOCAL_API"; then
echo "Check if lapi needs to automatically register an agent"
# pre-registration is not needed with TLS
if isfalse "$USE_TLS" && [ "$AGENT_USERNAME" != "" ] && [ "$AGENT_PASSWORD" != "" ] ; then
# shellcheck disable=SC2086
cscli machines add "$AGENT_USERNAME" --password "$AGENT_PASSWORD" --url "$LOCAL_API_URL"
echo "Agent registered to lapi"
fi
echo "Agent registered to lapi"
fi
# registration to online API for signal push
if [ "${DISABLE_ONLINE_API,,}" != "true" ] && [ "$CONFIG_FILE" == "" ] ; then
CONFIG_EXIST=$(yq eval '.api.server.online_client | has("credentials_path")' "$CS_CONFIG_FILE")
if [ "$CONFIG_EXIST" != "true" ]; then
yq eval '.api.server.online_client = {"credentials_path": "/etc/crowdsec/online_api_credentials.yaml"}' "$CS_CONFIG_FILE" > /etc/crowdsec/config2.yaml
mv /etc/crowdsec/config2.yaml "$CS_CONFIG_FILE"
cscli -c "$CS_CONFIG_FILE" capi register > /etc/crowdsec/online_api_credentials.yaml
echo "registration to online API done"
if isfalse "$DISABLE_ONLINE_API" && [ "$CONFIG_FILE" == "/etc/crowdsec/config.yaml" ] ; then
config_exists=$(conf_get '.api.server.online_client | has("credentials_path")')
if isfalse "$config_exists"; then
conf_set '.api.server.online_client = {"credentials_path": "/etc/crowdsec/online_api_credentials.yaml"}'
cscli capi register > /etc/crowdsec/online_api_credentials.yaml
echo "Registration to online API done"
fi
fi
## Enroll instance if enroll key is provided
if [ "${DISABLE_ONLINE_API,,}" != "true" ] && [ "$ENROLL_KEY" != "" ] ; then
# Enroll instance if enroll key is provided
if isfalse "$DISABLE_ONLINE_API" && [ "$ENROLL_KEY" != "" ]; then
enroll_args=""
if [ "$ENROLL_INSTANCE_NAME" != "" ] ; then
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
if [ "$ENROLL_TAGS" != "" ]; then
# shellcheck disable=SC2086
for tag in ${ENROLL_TAGS}; do
enroll_args="$enroll_args --tags $tag"
done
fi
#shellcheck disable=SC2086
# shellcheck disable=SC2086
cscli console enroll $enroll_args "$ENROLL_KEY"
fi
# crowdsec sqlite database permissions
if [ "$GID" != "" ]; then
IS_SQLITE=$(yq eval '.db_config.type == "sqlite"' "$CS_CONFIG_FILE")
DB_PATH=$(yq eval '.db_config.db_path' "$CS_CONFIG_FILE")
if [ "$IS_SQLITE" == "true" ]; then
chown ":$GID" "$DB_PATH"
if istrue "$(conf_get '.db_config.type == "sqlite"')"; then
chown ":$GID" "$(conf_get '.db_config.db_path')"
echo "sqlite database permissions updated"
fi
fi
if [ "${USE_TLS,,}" == "true" ]; then
yq -i eval ".api.server.tls.cert_file = \"$CERT_FILE\"" "$CS_CONFIG_FILE"
yq -i eval ".api.server.tls.key_file = \"$KEY_FILE\"" "$CS_CONFIG_FILE"
yq -i eval '... comments=""' "$CS_CONFIG_FILE"
if istrue "$USE_TLS"; then
agents_allowed_yaml=$(csv2yaml "$AGENTS_ALLOWED_OU") \
bouncers_allowed_yaml=$(csv2yaml "$BOUNCERS_ALLOWED_OU") \
conf_set '
.api.server.tls.ca_cert_path = strenv(CACERT_FILE) |
.api.server.tls.cert_file = strenv(CERT_FILE) |
.api.server.tls.key_file = strenv(KEY_FILE) |
.api.server.tls.bouncers_allowed_ou = env(bouncers_allowed_yaml) |
.api.server.tls.agents_allowed_ou = env(agents_allowed_yaml) |
... comments=""
'
fi
if [ "$PLUGIN_DIR" != "/usr/local/lib/crowdsec/plugins/" ]; then
yq -i eval ".config_paths.plugin_dir = \"$PLUGIN_DIR\"" "$CS_CONFIG_FILE"
fi
conf_set ".config_paths.plugin_dir = strenv(PLUGIN_DIR)"
## Install collections, parsers, scenarios & postoverflows
cscli -c "$CS_CONFIG_FILE" hub update
cscli -c "$CS_CONFIG_FILE" collections upgrade crowdsecurity/linux || true
cscli -c "$CS_CONFIG_FILE" parsers upgrade crowdsecurity/whitelists || true
cscli -c "$CS_CONFIG_FILE" parsers install crowdsecurity/docker-logs || true
cscli hub update
cscli collections upgrade crowdsecurity/linux || true
cscli parsers upgrade crowdsecurity/whitelists || true
cscli parsers install crowdsecurity/docker-logs || true
if [ "$COLLECTIONS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" collections install $COLLECTIONS
# shellcheck disable=SC2086
cscli collections install $COLLECTIONS
fi
if [ "$PARSERS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" parsers install $PARSERS
# shellcheck disable=SC2086
cscli parsers install $PARSERS
fi
if [ "$SCENARIOS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" scenarios install $SCENARIOS
# shellcheck disable=SC2086
cscli scenarios install $SCENARIOS
fi
if [ "$POSTOVERFLOWS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" postoverflows install $POSTOVERFLOWS
# shellcheck disable=SC2086
cscli postoverflows install $POSTOVERFLOWS
fi
## Remove collections, parsers, scenarios & postoverflows
if [ "$DISABLE_COLLECTIONS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" collections remove $DISABLE_COLLECTIONS
fi
if [ "$DISABLE_PARSERS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" parsers remove $DISABLE_PARSERS
fi
if [ "$DISABLE_SCENARIOS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" scenarios remove $DISABLE_SCENARIOS
fi
if [ "$DISABLE_POSTOVERFLOWS" != "" ]; then
#shellcheck disable=SC2086
cscli -c "$CS_CONFIG_FILE" postoverflows remove $DISABLE_POSTOVERFLOWS
# shellcheck disable=SC2086
cscli collections remove $DISABLE_COLLECTIONS
fi
function register_bouncer {
if ! cscli -c "$CS_CONFIG_FILE" bouncers list -o json | sed '/^ *"name"/!d;s/^ *"name": "\(.*\)",/\1/' | grep -q "^${NAME}$"; then
if cscli -c "$CS_CONFIG_FILE" bouncers add "${NAME}" -k "${KEY}" > /dev/null; then
if [ "$DISABLE_PARSERS" != "" ]; then
# shellcheck disable=SC2086
cscli parsers remove $DISABLE_PARSERS
fi
if [ "$DISABLE_SCENARIOS" != "" ]; then
# shellcheck disable=SC2086
cscli scenarios remove $DISABLE_SCENARIOS
fi
if [ "$DISABLE_POSTOVERFLOWS" != "" ]; then
# shellcheck disable=SC2086
cscli postoverflows remove $DISABLE_POSTOVERFLOWS
fi
register_bouncer() {
if ! cscli bouncers list -o json | sed '/^ *"name"/!d;s/^ *"name": "\(.*\)",/\1/' | grep -q "^${NAME}$"; then
if cscli bouncers add "${NAME}" -k "${KEY}" > /dev/null; then
echo "Registered bouncer for ${NAME}"
else
echo "Failed to register bouncer for ${NAME}"
@ -182,6 +247,7 @@ ARGS=""
if [ "$CONFIG_FILE" != "" ]; then
ARGS="-c $CONFIG_FILE"
fi
if [ "$DSN" != "" ]; then
ARGS="$ARGS -dsn ${DSN}"
fi
@ -189,24 +255,32 @@ fi
if [ "$TYPE" != "" ]; then
ARGS="$ARGS -type $TYPE"
fi
if [ "${TEST_MODE,,}" == "true" ]; then
if istrue "$TEST_MODE"; then
ARGS="$ARGS -t"
fi
if [ "${DISABLE_AGENT,,}" == "true" ]; then
if istrue "$DISABLE_AGENT"; then
ARGS="$ARGS -no-cs"
fi
if [ "${DISABLE_LOCAL_API,,}" == "true" ]; then
if istrue "$DISABLE_LOCAL_API"; then
ARGS="$ARGS -no-api"
fi
if [ "${LEVEL_TRACE,,}" == "true" ]; then
if istrue "$LEVEL_TRACE"; then
ARGS="$ARGS -trace"
fi
if [ "${LEVEL_DEBUG,,}" == "true" ]; then
if istrue "$LEVEL_DEBUG"; then
ARGS="$ARGS -debug"
fi
if [ "${LEVEL_INFO,,}" == "true" ]; then
if istrue "$LEVEL_INFO"; then
ARGS="$ARGS -info"
fi
#shellcheck disable=SC2086
conf_set '.prometheus.listen_port=env(METRICS_PORT)'
# shellcheck disable=SC2086
exec crowdsec $ARGS