Restrict access to root volume in Docker containers
- Dominant language
- Java
- Stars
- 107
- Forks
- 29
- Avg merge
- 19h 46m
- Merged PRs (30d)
- 141
Description
### User Story
As a user of Sleeper, I want Docker containers running in my instance to be immutable, so that an attacker inside the container cannot modify anything in the file system.
### Description / Background
Currently all the Docker containers in an instance of Sleeper run as the root user. That is not the case for the Sleeper Docker tools, which use a separate "sleeper" user.
We'd like to update all our Docker images that run in an instance of Sleeper to use a non-root user, which does not have access to edit most of the file system.
### Acceptance Criteria
**Given** any Docker image that runs in a Sleeper instance
**When** I find a way to inject my own code into a running container in the instance
**Then** the code will not run as root
**And** the code cannot modify most of the file system in the container
### Technical Notes / Implementation Details
This will include all Docker images covered in the following documentation:
https://github.com/gchq/sleeper/blob/develop/docs/deployment/docker-images.md
All of these except for the bulk import on EKS image use the same base image. We could consider putting the non-root user setup in the base image. The image for bulk import on EKS already runs as a non-root user, so won't need changing. This may mean that the only change that needs to happen is in the base image. This is at `java/common/docker-base/docker/Dockerfile`.
The new non-root user will still need any necessary permissions to run the code that's in the container, but the actual contents of the container should not be editable by the user. Some containers still need to be able to write files, e.g. a local working directory in standard ingest. This can generally be done in the /tmp directory.
#### Docker tools
We already create a non-root user in the Docker images used in the Docker tools, i.e. the builder image and the environment image. We can use this as an example to replicate this setup. We won't need a lot of the configuration this uses, e.g. sudoer group, disable password prompting for sudo.
See `scripts/cli/builder/Dockerfile` and `scripts/cli/environment/Dockerfile`.
#### Testing
We can test this by running the container with a different command, like this:
```bash
docker run --rm -it --entrypoint /bin/sh
```
That will create a container and start a shell inside the container. You can then check what permissions you have. You can try creating or editing a file in the file system, e.g. the jar file, to make sure it's refused.
```bash
./scripts/dev/buildDockerImage.sh base sleeper-base:test --builder sleeper --load
./scripts/dev/buildDockerImage.sh ingest ingest:test --build-arg BASE_IMAGE=sleeper-base:test
docker run --rm -it --entrypoint /bin/sh ingest:test
ls -lah /
# Shows e.g.
# drwxr-xr-x 1 root root 4.0K May 28 14:24 .
# -rw-rw-r-- 1 root root 123M May 28 12:47 ingest.jar
```
The whole system test suite will also need running in order to tell whether there are permissions problems.
#### Potential splitting
We have the option to apply this as a new base image initially, which would not be used by default. We could then split out separate issues to ensure that this works as an override for each of the other images.
This would be partly blocked on the following bug that lets us apply a base image override per-image:
- https://github.com/gchq/sleeper/issues/7753
Even with that bug still present, we could still override the whole base image just for testing (with `--override-base-image-dir` rather than `--override-base-image-dir-by-image` in `setDeployConfig.sh`). We could then merge a PR to introduce the alternative base image so that we can test against it.
Contributor guide
Assessment
This issue has not been assessed yet.