これは、なにをしたくて書いたもの?
Dockerイメージのセキュリティ診断ツールのひとつとして、「Dockle」というものがあるのを知りまして。
こちらをちょっと試してみようかな、と。
Dockle?
コンテナイメージに含まれるパッケージ等の脆弱性診断ツールとして、ClairやTrivyが有名です。
GitHub - quay/clair: Vulnerability Static Analysis for Containers
Dockleはこういうものとはちょっと違って、CIS BenchmarkのDockerに関する項目(Container Images and Build File)や
DockerfileのBest Practiceで重要なものをチェックしてくれるツールのようです。
CIで簡単につかえるコンテナのセキュリティ診断「Dockle」 - Qiita
Best practices for writing Dockerfiles | Docker Documentation
実際のチェック内容は、こちら。
dockle/CHECKPOINT.md at v0.3.1 · goodwithtech/dockle · GitHub
ざっくり書いていってみましょう。
- Dockerイメージ用のチェックポイント
- Create a user for the container … コンテナ用のユーザーを作成しているか
- Use trusted base images for containers … 信頼されたベースイメージを使っているか
- Enable Content trust for Docker … Docker Content Trustが有効化されているか
- Add HEALTHCHECK instruction to the container image … コンテナイメージに HEALTHCHECK が指定されているか
- Do not use update instructions alone in the Dockerfile … パッケージマネージャーのupdateコマンドを、単一のコマンドで実行していないか
- Confirm safety of setuid and setgid files … setuid、setgidファイルの安全性を確認しているか
- Use COPY instead of ADD in Dockerfile … ADDの代わりにCOPYを使っているか
- Do not store secrets in Dockerfiles … Dockerfileに機密情報を書き込んでいないか
- Docker用のチェックポイント
- Avoid sudo command … sudoコマンドを使っていないか
- Avoid sensitive directory mounting … センシティブなディレクトリのマウントを使っていないか
- Avoid apt-get upgrade, apk upgrade, dist-upgrade … パッケージマネージャーのupgradeコマンドを使っていないか
- Use apk add with --no-cache … apk addには--no-cacheオプションを使っているか
- Clear apt-get caches … パッケージマネージャーのキャッシュをクリアしているか
- Avoid latest tag … latestタグを使っていないか
- Linux用のチェックポイント
- Avoid empty password … 空のパスワードを使っていないか
- Be unique UID/GROUPs … UIDおよびグループはユニークか
- Only put necessary files … 必要なファイルのみが置かれているか
使い方の例は、こちら。
CIへの統合例は、こちら。
こんな感じですね。では、使っていってみましょう。
環境
今回の環境は、こちら。
$ uname -srvmpio Linux 5.4.0-47-generic #51-Ubuntu SMP Fri Sep 4 19:50:52 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.1 LTS Release: 20.04 Codename: focal $ docker version Client: Docker Engine - Community Version: 19.03.12 API version: 1.40 Go version: go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:45:44 2020 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.12 API version: 1.40 (minimum version 1.12) Go version: go1.13.10 Git commit: 48a66213fe Built: Mon Jun 22 15:44:15 2020 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.2.13 GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc: Version: 1.0.0-rc10 GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd docker-init: Version: 0.18.0 GitCommit: fec3683
インストール
まずは、インストールしてみます。
Ubuntu Linuxの場合の手順はこちら。
$ VERSION=$( curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \ grep '"tag_name":' | \ sed -E 's/.*"v([^"]+)".*/\1/' \ ) && curl -L -o dockle.deb https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.deb $ sudo dpkg -i dockle.deb && rm dockle.deb
今回インストールしたDockleは、0.3.1です。
$ dockle -v dockle version 0.3.1
オプションを確認。
$ dockle -h NAME: dockle - Container Image Linter for Security, Helping build the Best-Practice Docker Image, Easy to start USAGE: dockle [options] image_name VERSION: 0.3.1 OPTIONS: --input value input file path instead of image name --ignore value, -i value checkpoints to ignore. You can use .dockleignore too. --format value, -f value format (json) --output value, -o value output file name --exit-code value, -c value exit code when alert were found (default: 0) --exit-level value, -l value change ABEND level when use exit-code=1 (default: "WARN") --debug, -d debug mode --timeout value, -t value docker timeout. e.g) 5s, 5m... (default: 1m30s) --authurl value registry authenticate url --username value registry login username --password value registry login password. Using --password via CLI is insecure. --insecure registry connect insecure --nonssl registry connect without ssl --cache-dir value cache directory --help, -h show help --version, -v print the version
Dockleの実行自体には、Dockerは不要なようです。
使ってみる
では、使ってみましょう。
試しに、Apache MavenのDockerイメージをPull。
$ docker image pull maven:3.6-adoptopenjdk-11
Dockleを実行してみます。
$ dockle maven:3.6-adoptopenjdk-11
こんな結果になりました。
WARN - CIS-DI-0001: Create a user for the container * Last user should not be root INFO - CIS-DI-0005: Enable Content trust for Docker * export DOCKER_CONTENT_TRUST=1 before docker pull/build INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image * not found HEALTHCHECK statement INFO - CIS-DI-0008: Confirm safety of setuid/setgid files * setuid file: usr/bin/newgrp urwxr-xr-x * setgid file: usr/bin/expiry grwxr-xr-x * setuid file: bin/umount urwxr-xr-x * setgid file: sbin/pam_extrausers_chkpwd grwxr-xr-x * setgid file: usr/bin/wall grwxr-xr-x * setgid file: usr/bin/ssh-agent grwxr-xr-x * setuid file: usr/bin/passwd urwxr-xr-x * setuid file: usr/bin/gpasswd urwxr-xr-x * setuid file: bin/su urwxr-xr-x * setuid file: usr/bin/chsh urwxr-xr-x * setuid file: usr/bin/chfn urwxr-xr-x * setgid file: usr/bin/chage grwxr-xr-x * setuid file: usr/lib/openssh/ssh-keysign urwxr-xr-x * setuid file: bin/mount urwxr-xr-x * setgid file: sbin/unix_chkpwd grwxr-xr-x
もうひとつ、Apacheで試してみましょう。
$ docker image pull httpd:2.4
結果。
$ dockle httpd:2.4 WARN - CIS-DI-0001: Create a user for the container * Last user should not be root INFO - CIS-DI-0005: Enable Content trust for Docker * export DOCKER_CONTENT_TRUST=1 before docker pull/build INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image * not found HEALTHCHECK statement INFO - CIS-DI-0008: Confirm safety of setuid/setgid files * setgid file: usr/bin/expiry grwxr-xr-x * setuid file: usr/bin/gpasswd urwxr-xr-x * setuid file: bin/su urwxr-xr-x * setuid file: usr/bin/chsh urwxr-xr-x * setgid file: sbin/unix_chkpwd grwxr-xr-x * setgid file: usr/bin/chage grwxr-xr-x * setgid file: usr/bin/wall grwxr-xr-x * setuid file: usr/bin/passwd urwxr-xr-x * setuid file: usr/bin/chfn urwxr-xr-x * setuid file: usr/local/apache2/bin/suexec urwxr-xr-x * setuid file: bin/umount urwxr-xr-x * setuid file: bin/mount urwxr-xr-x * setuid file: usr/bin/newgrp urwxr-xr-x
今回選んだイメージでは、引っかかるチェックポイントは変わりませんでした…。
なお、「コンテナ内のプロセスがrootで実行されてるよ」というチェックポイントですが、Apacheの場合は子プロセスはrootで
動作しないので、ここは許容してもよいかも?という気がします。
ここをさらに木にする場合は、User namespaceを使うのだとか。
Isolate containers with a user namespace | Docker Documentation
余談でした。
実行時間は、こんな感じ。
$ time dockle maven:3.6-adoptopenjdk-11 real 0m16.873s user 0m2.095s sys 0m0.944s $ time dockle httpd:2.4 real 0m4.910s user 0m0.658s sys 0m0.212s
あとは、指定のレベル以上のアラートが出た場合の終了コードを指定したり、特定のチェックポイントを無視したり、
結果をJSONで出力したりできるようです。
$ dockle -f json maven:3.6-adoptopenjdk-11 { "summary": { "fatal": 0, "warn": 1, "info": 3, "skip": 0, "pass": 12 }, "details": [ { "code": "CIS-DI-0001", "title": "Create a user for the container", "level": "WARN", "alerts": [ "Last user should not be root" ] }, { "code": "CIS-DI-0005", "title": "Enable Content trust for Docker", "level": "INFO", "alerts": [ "export DOCKER_CONTENT_TRUST=1 before docker pull/build" ] }, { "code": "CIS-DI-0006", "title": "Add HEALTHCHECK instruction to the container image", "level": "INFO", "alerts": [ "not found HEALTHCHECK statement" ] }, { "code": "CIS-DI-0008", "title": "Confirm safety of setuid/setgid files", "level": "INFO", "alerts": [ "setuid file: usr/bin/passwd urwxr-xr-x", "setgid file: usr/bin/wall grwxr-xr-x", "setuid file: bin/mount urwxr-xr-x", "setgid file: sbin/unix_chkpwd grwxr-xr-x", "setgid file: usr/bin/chage grwxr-xr-x", "setuid file: usr/bin/chsh urwxr-xr-x", "setgid file: usr/bin/ssh-agent grwxr-xr-x", "setuid file: usr/lib/openssh/ssh-keysign urwxr-xr-x", "setuid file: usr/bin/chfn urwxr-xr-x", "setuid file: usr/bin/newgrp urwxr-xr-x", "setgid file: usr/bin/expiry grwxr-xr-x", "setuid file: usr/bin/gpasswd urwxr-xr-x", "setuid file: bin/umount urwxr-xr-x", "setuid file: bin/su urwxr-xr-x", "setgid file: sbin/pam_extrausers_chkpwd grwxr-xr-x" ] } ] }
良いですね、コンテナイメージのBest Practiceに従っているかどうかなどを確認してみるといいのかなーと思います。