diff --git a/.github/workflows/docker-tests.yml b/.github/workflows/docker-tests.yml index 2887166c4..6476d9f0a 100644 --- a/.github/workflows/docker-tests.yml +++ b/.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: diff --git a/docker/docker_start.sh b/docker/docker_start.sh index 92600b275..c89734022 100755 --- a/docker/docker_start.sh +++ b/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)' diff --git a/docker/test/Pipfile.lock b/docker/test/Pipfile.lock index 220871015..ec03981db 100644 --- a/docker/test/Pipfile.lock +++ b/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": [ diff --git a/docker/test/tests/test_tls.py b/docker/test/tests/test_tls.py index 9b35ca060..2e26d55f7 100644 --- a/docker/test/tests/test_tls.py +++ b/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