Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace alpine with chainguard distroless images #7

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

adrlsx
Copy link
Contributor

@adrlsx adrlsx commented Feb 13, 2024

The aim of this pull request is to migrate the repeater's Docker image from an Alpine-based image to a distroless image. The main advantages are as follows:

  • Reduced image size
  • Reduced attack surface
  • Makes a hacker's job more difficult by removing commonly used tools (e.g. shell / curl)
  • Reduced scanner noise, so you know exactly which vulnerabilities are present in the image

The first distroless images were produced by GoogleContainerTools, which has distroless images designed to run C, Go, Java, Node.js and Python images. Google's images are produced using a custom process orchestrated by their construction tool Bazel. Here are the benefits highlighted on their GitHub:

Restricting what's in your runtime container to precisely what's necessary for your app is a best practice employed by Google and other tech giants that have used containers in production for many years. It improves the signal to noise of scanners (e.g. CVE) and reduces the burden of establishing provenance to just what you need.

However, this pull request is based on distroless images from Chainguard. Chainguard distroless images are hardened and up-to-date distroless images. These images are easier to customize as there a build using apko and melange instead of Bazel. Here are the benefits highlighted on their website:

A key benefit of minimal images, which we reported on previously, is that the smaller surface can lead to a substantial reduction in the rate at which images accumulate CVEs [...]. We also see minimal images as a key mitigation for the growing evasion technique known as “living off the land,” which attackers are using to avoid intrusion detection software. Another benefit of minimal images is that they are small (comparing a crude sampling with official images, the average is 79% smaller).

In terms of hardening, they use a nonroot user by default, which reduces the risk of container breakout. Chainguard images are built automatically every night to ensure that they are completely up to date and contain all available security patches. More details can be found on their blog post.

While not a panacea, the use of distroless images is good practice for sensitive, long-term containers such as Escape's repeater agent.

@QuentinN42
Copy link
Contributor

Hello, thanks for this contribution.

It seems nice to improve security for this container, but I'm not convinced that it will not break any features.

You can find here our officially advertised features : https://docs.escape.tech/enterprise/repeater#setup-a-repeater

The distroless switch drops the update-ca-certificates command, but we have some clients that mount their private certificates into the docker image. This command must be run as root so that's why we are currently using alpine and a privileged user.

Do you know if it's possible to import the thrust chain directly inside the golang application ? If yes, we surely want to do that before dropping the alpine image.

I'm also wondering what are the advantages of distroless with compiled language. As we are building a static binary, we must be able to switch to busybox or even scratch right ? Or did I miss something?

@adrlsx
Copy link
Contributor Author

adrlsx commented Feb 20, 2024

I had indeed overlooked this feature. As you suggest, we can manage CA certificates directly in the Golang application. To do this, we would first need to import the CA certificates from the system using the x509.SystemCertPool() function. We could then use AppendCertsFromPEM() to add custom CA certificates. Examples can be found in this BastionXP blog post, in this quic-go example and in this Stack Overflow question.

I'm not a Golang expert and I'm not yet familiar with the whole code base, so I probably won't be writing the pull request myself in the near future, but I'd be happy to help.

As for the distroless choice, you're right that we could start from scratch for a static binary. However, that would be a bit more laborious. The static distroless image is actually an image from scratch with :

  • Root certificate data
  • /etc/passwd and /tmp
  • An unprivileged nonroot user and group by default, running with uid and gid 65532
  • tzdata (time zone and daylight-saving time data)

Most of the time, it's easier to start with these data. In this case, we're mainly interested in the root certificate data, as well as the default user and group.

Chisel is a similar tunneling project, also written in Golang. You can take a look at Chisel Dockerfile, which is a good example of an image built from scratch. However, the resulting container will still run as root.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants