Browse Source

Docker: correct behavior of AGENTS_ALLOWED_OU, BOUNCERS_ALLOWED_OU (#2140)

mmetc 2 years ago
parent
commit
68d4bdc1bd
4 changed files with 82 additions and 17 deletions
  1. 12 0
      .github/workflows/docker-tests.yml
  2. 4 2
      docker/docker_start.sh
  3. 12 12
      docker/test/Pipfile.lock
  4. 54 3
      docker/test/tests/test_tls.py

+ 12 - 0
.github/workflows/docker-tests.yml

@@ -54,6 +54,18 @@ jobs:
           cache-from: type=gha
           cache-to: type=gha,mode=min
 
+      - name: "Build flavor: full"
+        uses: docker/build-push-action@v4
+        with:
+          context: .
+          file: ./Dockerfile
+          tags: crowdsecurity/crowdsec:test
+          target: full
+          platforms: linux/amd64
+          load: true
+          cache-from: type=gha
+          cache-to: type=gha,mode=min
+
       - name: "Build flavor: full (debian)"
         uses: docker/build-push-action@v4
         with:

+ 4 - 2
docker/docker_start.sh

@@ -274,8 +274,10 @@ fi
 
 # XXX only with LAPI
 if istrue "$USE_TLS"; then
-    agents_allowed_yaml=$(csv2yaml "$AGENTS_ALLOWED_OU") \
-    bouncers_allowed_yaml=$(csv2yaml "$BOUNCERS_ALLOWED_OU") \
+    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)'

+ 12 - 12
docker/test/Pipfile.lock

@@ -221,11 +221,11 @@
         },
         "exceptiongroup": {
             "hashes": [
-                "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e",
-                "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"
+                "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e",
+                "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"
             ],
             "markers": "python_version < '3.11'",
-            "version": "==1.1.0"
+            "version": "==1.1.1"
         },
         "execnet": {
             "hashes": [
@@ -324,11 +324,11 @@
         },
         "pytest-xdist": {
             "hashes": [
-                "sha256:336098e3bbd8193276867cc87db8b22903c3927665dff9d1ac8684c02f597b68",
-                "sha256:fa10f95a2564cd91652f2d132725183c3b590d9fdcdec09d3677386ecf4c1ce9"
+                "sha256:1849bd98d8b242b948e472db7478e090bf3361912a8fed87992ed94085f54727",
+                "sha256:37290d161638a20b672401deef1cba812d110ac27e35d213f091d15b8beb40c9"
             ],
             "index": "pypi",
-            "version": "==3.2.0"
+            "version": "==3.2.1"
         },
         "python-dotenv": {
             "hashes": [
@@ -409,11 +409,11 @@
         },
         "urllib3": {
             "hashes": [
-                "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72",
-                "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"
+                "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305",
+                "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"
             ],
             "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
-            "version": "==1.26.14"
+            "version": "==1.26.15"
         },
         "websocket-client": {
             "hashes": [
@@ -489,11 +489,11 @@
         },
         "ipdb": {
             "hashes": [
-                "sha256:c23b6736f01fd4586cc2ecbebdf79a5eb454796853e1cd8f2ed3b7b91d4a3e93",
-                "sha256:f74c2f741c18b909eaf89f19fde973f745ac721744aa1465888ce45813b63a9c"
+                "sha256:45529994741c4ab6d2388bfa5d7b725c2cf7fe9deffabdb8a6113aa5ed449ed4",
+                "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726"
             ],
             "index": "pypi",
-            "version": "==0.13.11"
+            "version": "==0.13.13"
         },
         "ipython": {
             "hashes": [

+ 54 - 3
docker/test/tests/test_tls.py

@@ -135,9 +135,6 @@ def test_tls_lapi_var(crowdsec, flavor, certs_dir):
 # TODO: bad lapi hostname
 # the cert is valid, but has a CN that doesn't match the hostname
 # we must set insecure_skip_verify to true to use it
-# TODO: bad client OU, auth failure
-# the client cert is valid, but the organization unit doesn't match the allowed
-# value and will be rejected by the lapi unless we set agents_allow_ou
 
 
 def test_tls_split_lapi_agent(crowdsec, flavor, certs_dir):
@@ -234,3 +231,57 @@ def test_tls_mutual_split_lapi_agent(crowdsec, flavor, certs_dir):
         assert res.exit_code == 0
         stdout = res.output.decode()
         assert "You can successfully interact with Local API (LAPI)" in stdout
+
+
+def test_tls_client_ou(crowdsec, certs_dir):
+    """Check behavior of client certificate vs AGENTS_ALLOWED_OU"""
+
+    rand = random.randint(0, 10000)
+    lapiname = 'lapi-' + str(rand)
+    agentname = 'agent-' + str(rand)
+
+    lapi_env = {
+        'USE_TLS': 'true',
+        'CACERT_FILE': '/etc/ssl/crowdsec/ca.crt',
+        'LAPI_CERT_FILE': '/etc/ssl/crowdsec/lapi.crt',
+        'LAPI_KEY_FILE': '/etc/ssl/crowdsec/lapi.key',
+        'LOCAL_API_URL': 'https://localhost:8080',
+    }
+
+    agent_env = {
+        'USE_TLS': 'true',
+        'CACERT_FILE': '/etc/ssl/crowdsec/ca.crt',
+        'CLIENT_CERT_FILE': '/etc/ssl/crowdsec/agent.crt',
+        'CLIENT_KEY_FILE': '/etc/ssl/crowdsec/agent.key',
+        'LOCAL_API_URL': f'https://{lapiname}:8080',
+        'DISABLE_LOCAL_API': 'true',
+        'CROWDSEC_FEATURE_DISABLE_HTTP_RETRY_BACKOFF': 'false',
+    }
+
+    volumes = {
+        certs_dir(lapi_hostname=lapiname, agent_ou='custom-client-ou'): {'bind': '/etc/ssl/crowdsec', 'mode': 'ro'},
+    }
+
+    with crowdsec(name=lapiname, environment=lapi_env, volumes=volumes) as lapi, crowdsec(name=agentname, environment=agent_env, volumes=volumes) as agent:
+        lapi.wait_for_log([
+            "*client certificate OU (?custom-client-ou?) doesn't match expected OU (?agent-ou?)*",
+        ])
+
+    lapi_env['AGENTS_ALLOWED_OU'] = 'custom-client-ou'
+
+    with crowdsec(name=lapiname, environment=lapi_env, volumes=volumes) as lapi, crowdsec(name=agentname, environment=agent_env, volumes=volumes) as agent:
+        lapi.wait_for_log([
+            "*(tls) Client Auth Type set to VerifyClientCertIfGiven*",
+            "*CrowdSec Local API listening on 0.0.0.0:8080*"
+        ])
+        # TODO: wait_for_https
+        lapi.wait_for_http(8080, '/health', want_status=None)
+        agent.wait_for_log("*Starting processing data*")
+        res = agent.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
+        res = lapi.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