Tool to scan a container image's rootfs
Перейти к файлу
Brian Goff e7041e47d1
Merge pull request #19 from Azure/dependabot/go_modules/github.com/sirupsen/logrus-1.9.0
Bump github.com/sirupsen/logrus from 1.8.1 to 1.9.0
2022-08-17 13:51:07 -07:00
.github Merge pull request #17 from Azure/dependabot/github_actions/actions/setup-go-3 2022-04-20 10:47:12 -07:00
.dockerignore update dockerignore for more uneccessary things 2021-07-16 22:10:50 +00:00
CODE_OF_CONDUCT.md CODE_OF_CONDUCT.md committed 2021-07-14 15:36:19 -07:00
Dockerfile Dockerfile: make binary output 2021-07-16 22:10:20 +00:00
LICENSE LICENSE committed 2021-07-14 15:36:21 -07:00
README.md Change matcher to use templates 2021-07-23 22:31:34 +00:00
SECURITY.md SECURITY.md committed 2021-07-14 15:36:20 -07:00
SUPPORT.md SUPPORT.md committed 2021-07-14 15:36:20 -07:00
containerd.go initial commit 2021-07-15 22:59:01 +00:00
go.mod Bump github.com/sirupsen/logrus from 1.8.1 to 1.9.0 2022-07-25 11:20:09 +00:00
go.sum Bump github.com/sirupsen/logrus from 1.8.1 to 1.9.0 2022-07-25 11:20:09 +00:00
main.go fix module name 2021-07-26 14:11:38 -07:00
result.go Change matcher to use templates 2021-07-23 22:31:34 +00:00
result_test.go Add basic unit tests for scanner 2021-07-23 23:17:19 +00:00
run.go Add support for dumping a continuity manifest 2021-07-23 00:21:00 +00:00

README.md

image-rootfs-scanner

A tool to pull and scan the rootfs of any container image for different binaries. It started out as a means of finding "restricted" binaries, e.g. binaries that we'd prefer not be in an image, such as shells, curl, etc, hence the defaults.

This project should only be used to scan trusted images. It is not designed to find things that someone is trying to hide, just as a safeguard to find things that were forgotten.

Note, this does not scan individual layers, only the final rootfs. Again, the intent is to limit what is available inside a container, not to prevent a binary from being on the host machine.

Out of the box it depends on a containerd daemon running to connect to, however you can configure it to run stand-alone with data being stored in the specified root location (default is in your home dir).

It currently requires a user with CAP_SYS_ADMIN (e.g. root) in order to mount things. I do have some work done to allow this to run as an unprivileged user and mount using fuse-overlayfs, but there is still some work to do to make that happen.

Usage

This assumes you have containerd up and running with the default socket location (/run/containerd/containerd.sock). You must provide the full canonical URL to an image, e.g. instead of ubuntu => docker.io/library/ubuntu:latest. It outputs a report which you can customize if needed (see the --format flag).

$ sudo image-rootfs-scanner docker.io/library/busybox:latest
docker.io/library/busybox:latest MATCH ["nc","sh","wget"]

The report has three columns, the image ref, the status, and a json encoded value of the data. If there is an error it will be in the report, example for running without the needed privileges:

docker.io/library/busybox:latest ERROR {"error": "error mounting rootfs: operation not permitted"}

Fields

The available template fields for the report (available to --format) are:

  • .Ref - The image reference used to fetch the image
  • .Found - An array of found binaries
  • .Status - Stringified status. ERROR if there was an error, MATCH there are found binaries, and NONE for no matches.
  • .Data - json representation of the data, such as an error or the matched binaries.
  • .HasMatches - Boolean for len(found) >= 1
  • .HasError - Boolean for if there is an error
  • .Manifest - Text marshalling of the continuity manifest
  • .ManifestProto - Protobuf marshalling of the continuity manifest

By default this scans for several different things such as bash, zsh, ssh, curl, and more. See --help for the full list. You can also customize it to only look in a specific location instead of / recursively.

Matching

There is a default template provided to match certain binaries in a bin/ directory. You can customize this by changing the --match flag. The value of this flag is a go-template which must evaluate to a boolean value which can be parsed by Go's strconv.ParseBool.

In addition to Go's builtin template functions, we provide:

  • regexp which takes two string arguments. The first argument is the value you want to evaluate. The second argument is the regular expression you want to use to match with. Example: {{ regexp .Path "bin/(bash|sh)$" }}
  • exec which runs whatever command+args you tell it to run. An exit code of 0 means true, exit code 1 means false. Any other exit code is an error condition. Stdin contains the json encoded resource. Anything you write to stdout/stderr will be used to write the error message. Example: {{ exec "/bin/sh", "-c", "[ \"$(jq .path <@0)\" = \"/bin/sh\" ]" }}. This evaluates if the path of the source is /bin/sh and signals a match if so. This is executed in the context of the scanner tool, not the image being processed.

Building

The tool is only able to work on Linux for now

Requires go with go modules support, then go build You can also build with Docker:

$ docker build --output=bin/ --platform=local .

or

$ docker build --output=bin/ --platform=local https://github.com/Azure/image-rootfs-scanner.git

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.