Bläddra i källkod

Docker: don't re-register local agent if not needed (#2141)

mmetc 2 år sedan
förälder
incheckning
f39fbf07fa
5 ändrade filer med 108 tillägg och 30 borttagningar
  1. 3 0
      Dockerfile
  2. 3 1
      Dockerfile.debian
  3. 15 8
      docker/docker_start.sh
  4. 87 0
      docker/test/tests/test_agent.py
  5. 0 21
      docker/test/tests/test_noagent.py

+ 3 - 0
Dockerfile

@@ -19,6 +19,9 @@ RUN apk add --no-cache git gcc libc-dev make bash gettext binutils-gold coreutil
     cscli parsers install crowdsecurity/whitelists && \
     go install github.com/mikefarah/yq/v4@v4.31.2
 
+    # In case we need to remove agents here..
+    # cscli machines list -o json | yq '.[].machineId' | xargs -r cscli machines delete
+
 FROM alpine:latest as slim
 
 RUN apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community tzdata bash && \

+ 3 - 1
Dockerfile.debian

@@ -23,6 +23,9 @@ RUN apt-get update && \
     cscli parsers install crowdsecurity/whitelists && \
     go install github.com/mikefarah/yq/v4@v4.31.2
 
+    # In case we need to remove agents here..
+    # cscli machines list -o json | yq '.[].machineId' | xargs -r cscli machines delete
+
 FROM debian:bullseye-slim as slim
 
 ENV DEBIAN_FRONTEND=noninteractive
@@ -50,7 +53,6 @@ COPY --from=build /go/src/crowdsec/docker/config.yaml /staging/etc/crowdsec/conf
 RUN yq -n '.url="http://0.0.0.0:8080"' | install -m 0600 /dev/stdin /staging/etc/crowdsec/local_api_credentials.yaml && \
     yq eval -i ".plugin_config.group = \"nogroup\"" /staging/etc/crowdsec/config.yaml
 
-
 ENTRYPOINT /bin/bash docker_start.sh
 
 FROM slim as plugins

+ 15 - 8
docker/docker_start.sh

@@ -185,13 +185,22 @@ elif [ -n "$USE_WAL" ] && isfalse "$USE_WAL"; then
     conf_set '.db_config.use_wal = false'
 fi
 
-# regenerate local agent credentials (even if agent is disabled, cscli needs a
-# connection to the API)
-cscli machines delete "$CUSTOM_HOSTNAME" 2>/dev/null || true
+lapi_credentials_path=$(conf_get '.api.client.credentials_path')
+
+
 if isfalse "$DISABLE_LOCAL_API"; then
-    if isfalse "$USE_TLS" || [ "$CLIENT_CERT_FILE" = "" ]; then
-        echo "Regenerate local agent credentials"
-        cscli machines add "$CUSTOM_HOSTNAME" --auto
+    # 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" && ( 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
+        fi
     fi
 
     echo "Check if lapi needs to register an additional agent"
@@ -205,8 +214,6 @@ fi
 
 # ----------------
 
-lapi_credentials_path=$(conf_get '.api.client.credentials_path')
-
 conf_set_if "$LOCAL_API_URL" '.url = strenv(LOCAL_API_URL)' "$lapi_credentials_path"
 
 if istrue "$DISABLE_LOCAL_API"; then

+ 87 - 0
docker/test/tests/test_agent.py

@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+
+from http import HTTPStatus
+
+import pytest
+
+pytestmark = pytest.mark.docker
+
+
+def test_no_agent(crowdsec, flavor):
+    """Test DISABLE_AGENT=true"""
+    env = {
+        'DISABLE_AGENT': 'true',
+    }
+    with crowdsec(flavor=flavor, environment=env) as cs:
+        cs.wait_for_log("*CrowdSec Local API listening on 0.0.0.0:8080*")
+        cs.wait_for_http(8080, '/health', want_status=HTTPStatus.OK)
+        res = cs.cont.exec_run('cscli lapi status')
+        assert res.exit_code == 0
+        stdout = res.output.decode()
+        assert "You can successfully interact with Local API (LAPI)" in stdout
+
+
+def test_machine_register(crowdsec, flavor, tmp_path_factory):
+    """A local agent is always registered for use by cscli"""
+
+    data_dir = tmp_path_factory.mktemp('data')
+
+    env = {
+        'DISABLE_AGENT': 'true',
+    }
+
+    volumes = {
+        data_dir: {'bind': '/var/lib/crowdsec/data', 'mode': 'rw'},
+    }
+
+    with crowdsec(flavor=flavor, environment=env, volumes=volumes) as cs:
+        cs.wait_for_log([
+                "*Generate local agent credentials*",
+                "*CrowdSec Local API listening on 0.0.0.0:8080*",
+            ])
+        cs.wait_for_http(8080, '/health', want_status=HTTPStatus.OK)
+        res = cs.cont.exec_run('cscli lapi status')
+        assert res.exit_code == 0
+        stdout = res.output.decode()
+        assert "You can successfully interact with Local API (LAPI)" in stdout
+
+    # The local agent is not registered, because we didn't persist local_api_credentials.yaml
+
+    with crowdsec(flavor=flavor, environment=env, volumes=volumes) as cs:
+        cs.wait_for_log([
+                "*Generate local agent credentials*",
+                "*CrowdSec Local API listening on 0.0.0.0:8080*",
+            ])
+        cs.wait_for_http(8080, '/health', want_status=HTTPStatus.OK)
+        res = cs.cont.exec_run('cscli lapi status')
+        assert res.exit_code == 0
+        stdout = res.output.decode()
+        assert "You can successfully interact with Local API (LAPI)" in stdout
+
+    config_dir = tmp_path_factory.mktemp('config')
+
+    volumes[config_dir] = {'bind': '/etc/crowdsec', 'mode': 'rw'}
+
+    with crowdsec(flavor=flavor, environment=env, volumes=volumes) as cs:
+        cs.wait_for_log([
+                "*Generate local agent credentials*",
+                "*CrowdSec Local API listening on 0.0.0.0:8080*",
+            ])
+        cs.wait_for_http(8080, '/health', want_status=HTTPStatus.OK)
+        res = cs.cont.exec_run('cscli lapi status')
+        assert res.exit_code == 0
+        stdout = res.output.decode()
+        assert "You can successfully interact with Local API (LAPI)" in stdout
+
+    # The local agent is now already registered
+
+    with crowdsec(flavor=flavor, environment=env, volumes=volumes) as cs:
+        cs.wait_for_log([
+                "*Local agent already registered*",
+                "*CrowdSec Local API listening on 0.0.0.0:8080*",
+            ])
+        cs.wait_for_http(8080, '/health', want_status=HTTPStatus.OK)
+        res = cs.cont.exec_run('cscli lapi status')
+        assert res.exit_code == 0
+        stdout = res.output.decode()
+        assert "You can successfully interact with Local API (LAPI)" in stdout

+ 0 - 21
docker/test/tests/test_noagent.py

@@ -1,21 +0,0 @@
-#!/usr/bin/env python
-
-from http import HTTPStatus
-
-import pytest
-
-pytestmark = pytest.mark.docker
-
-
-def test_no_agent(crowdsec, flavor):
-    """Test DISABLE_AGENT=true"""
-    env = {
-        'DISABLE_AGENT': 'true',
-    }
-    with crowdsec(flavor=flavor, environment=env) as cs:
-        cs.wait_for_log("*CrowdSec Local API listening on 0.0.0.0:8080*")
-        cs.wait_for_http(8080, '/health', want_status=HTTPStatus.OK)
-        res = cs.cont.exec_run('cscli lapi status')
-        assert res.exit_code == 0
-        stdout = res.output.decode()
-        assert "You can successfully interact with Local API (LAPI)" in stdout