diff --git a/docs/design/linux-ebpf-enforcement.md b/docs/design/linux-ebpf-enforcement.md index 5a1767f..a8515e1 100644 --- a/docs/design/linux-ebpf-enforcement.md +++ b/docs/design/linux-ebpf-enforcement.md @@ -529,11 +529,19 @@ Do not bind `0.0.0.0`. The state file would record `0.0.0.0`, which is not a val properly needs `bpf_get_netns_cookie()` in the hook to select a target per namespace. - **A non loopback bind exposes the MITM proxy.** Acceptable on an isolated runner, otherwise it needs a firewall rule. -- **CA trust inside the container is unsolved and may be unsolvable from the host.** A container has - its own trust store, and nothing on the host reaches into it. Injecting the CA requires the - process that starts the container to mount it. So for containers the guarantee degrades to fail - closed: traffic is mediated, the install fails, nothing unanalysed enters. That is the correct - security outcome and a poor usability one. +- **CA trust inside the container cannot be arranged from the host.** A container has its own trust + store and nothing on the host reaches into it. With the certificate mounted and the runtime told + to read it, the full flow works: `npm i is-odd` succeeded inside `node:20-slim` and + `safedep-test-pkg` was blocked with 403. But that requires the process starting the container to + cooperate, which is the assumption the whole layer exists to remove. Without it the guarantee + degrades to fail closed: traffic is mediated, the install fails, nothing unanalysed enters. That + is the correct security outcome and a poor usability one. + + Mounting over the image's CA bundle path is not sufficient on its own. Tested against + `curlimages/curl`: the mount lands and the file is correct, but curl does not read + `/etc/ssl/certs/ca-certificates.crt` by default and still fails. The runtime has to be pointed at + the file explicitly, through `NODE_EXTRA_CA_CERTS`, `CURL_CA_BUNDLE` or `--cacert`. Per runtime + again, which is the same shape as the host side problem. Note `docker pull` was already covered before any of this, since the daemon runs on the host. diff --git a/ebpf-poc/SETUP.md b/ebpf-poc/SETUP.md index ac2c7f2..d3437f1 100644 --- a/ebpf-poc/SETUP.md +++ b/ebpf-poc/SETUP.md @@ -535,6 +535,9 @@ The state file would then hold `0.0.0.0`, which is not a valid destination. ### Test it +Run this from an account that can use `sudo`. +The `testuser` account cannot. + ```bash sudo docker run --rm curlimages/curl:latest \ -4 -sS -m 20 -o /dev/null https://registry.npmjs.org/is-odd @@ -562,17 +565,51 @@ It fails at trust, not at the address. ### To make a container succeed -The person who starts the container must pass the certificate in: +The person who starts the container must pass the certificate in. +Mount the bundle, then tell the program where it is. + +For a Node image, such as `node:20-slim`: ```bash sudo docker run --rm \ - -v /var/lib/pmg-ebpf-poc/pmg-ca-bundle.pem:/etc/ssl/certs/ca-certificates.crt:ro \ + -v /var/lib/pmg-ebpf-poc/pmg-ca-bundle.pem:/ca.pem:ro \ + -e NODE_EXTRA_CA_CERTS=/ca.pem \ + -w /tmp node:20-slim sh -c "npm i is-odd" +``` + +For a curl image: + +```bash +sudo docker run --rm \ + -v /var/lib/pmg-ebpf-poc/pmg-ca-bundle.pem:/ca.pem:ro \ + -e CURL_CA_BUNDLE=/ca.pem \ curlimages/curl:latest -4 -sS https://registry.npmjs.org/is-odd ``` +Mounting the file alone is not enough. +The program must also be told to read it. + +A mount over `/etc/ssl/certs/ca-certificates.crt` does not work for every image. +It was tested and it failed with `curlimages/curl`. +That image does not read that file by default, even though the file is there. +Always set the environment variable, or pass `--cacert`. + There is no way to do this from the host. A container cannot be given a certificate it was not started to accept. +### A blocked package inside a container + +With the certificate passed in, PMG blocks as it does on the host: + +```bash +sudo docker run --rm \ + -v /var/lib/pmg-ebpf-poc/pmg-ca-bundle.pem:/ca.pem:ro \ + -e NODE_EXTRA_CA_CERTS=/ca.pem \ + -w /tmp node:20-slim sh -c "npm i safedep-test-pkg" +``` + +This prints `npm ERR! code E403`. + ### Limits - Only the default bridge network works.