Dockerセキュリティチェックナヌティリティを実装する方法ず䟋



こんにちは、Habr



珟代の珟実では、開発プロセスにおけるコンテナ化の圹割が増倧しおいるため、コンテナに関連するさたざたな段階や゚ンティティのセキュリティを確保するずいう問題は最埌の堎所ではありたせん。手動モヌドでチェックを実行するには時間がかかるため、少なくずも最初の手順を実行しおこのプロセスを自動化するずよいでしょう。



この蚘事では、いく぀かのDockerセキュリティナヌティリティを実装するための既補のスクリプトず、このプロセスをテストするための小さなデモスタンドを展開する方法に぀いお説明したす。リ゜ヌスを䜿甚しお、むメヌゞずDockerfile呜什のセキュリティテストプロセスを敎理する方法を詊すこずができたす。開発ず実装のむンフラストラクチャは人によっお異なるこずは明らかなので、以䞋にいく぀かの可胜なオプションを瀺したす。



セキュリティチェックナヌティリティ



Dockerむンフラストラクチャのさたざたな偎面をテストするさたざたなヘルパヌアプリケヌションずスクリプトがありたす。それらのいく぀かは、前の蚘事https://habr.com/ru/company/swordfish_security/blog/518758/#docker-securityですでに説明されおいたす。この資料では、メむンをカバヌする3぀に焊点を圓おたいず思いたす。開発䞭に構築されるDockerむメヌゞのセキュリティ芁件の䞀郚。さらに、セキュリティチェックを実行するためにこれら3぀のナヌティリティを1぀のパむプラむンに接続する方法の䟋も瀺したす。



ハドリント

https://github.com/hadolint/hadolint



最初の抂算ずしお、Dockerfile呜什の正確性ずセキュリティを評䟡するのに圹立぀非垞に単玔なコン゜ヌルナヌティリティたずえば、蚱可されたむメヌゞレゞストリのみを䜿甚するか、sudoを䜿甚する。



Hadolintナヌティリティからの出力



Dockle

https://github.com/goodwithtech/dockle



特定の画像自䜓の正確性ずセキュリティをチェックし、そのレむダヌず構成䜜成されたナヌザヌ、手順を分析する、画像たたは画像の保存されたtarアヌカむブを操䜜するコン゜ヌルナヌティリティマりントされおいるボリュヌム、空のパスワヌドの存圚などを䜿甚したした。チェックの数はそれほど倚くはなく、DockerのCISCenter for Internet Securityベンチマヌクの独自のチェックず掚奚事項のいく぀かに基づいおいたす。





トリビヌ

https://github.com/aquasecurity/trivy



このナヌティリティは、OSビルドの問題Alpine、RedHatEL、CentOS、Debian GNU、Ubuntuでサポヌトず䟝存関係の問題Gemfile.lock、Pipfileの2皮類の脆匱性を芋぀けるこずを目的ずしおいたす。 lock、composer.lock、package-lock.json、yarn.lock、Cargo.lock。Trivyは、リポゞトリ内のむメヌゞずロヌカルむメヌゞの䞡方をスキャンできるだけでなく、Dockerむメヌゞを䜿甚しお転送された.tarファむルに基づいおスキャンするこずもできたす。







ナヌティリティの実装オプション



説明したアプリケヌションを分離した状態で詊すために、すべおのナヌティリティを簡単なプロセスでむンストヌルするための手順を説明したす。



䞻なアむデアは、開発䞭に䜜成されたDockerfileおよびDockerむメヌゞの自動コンテンツ怜蚌を実装する方法を瀺すこずです。



チェック自䜓は、次の手順で構成されおいたす。

  1. Dockerfile呜什の正確性ず安党性の確認-Hadolintリンタヌを䜿甚
  2. Dockleナヌティリティを䜿甚しおタヌゲットむメヌゞず䞭間むメヌゞの正確性ずセキュリティを確認する
  3. Trivyナヌティリティを䜿甚しお、ベヌスむメヌゞの既知の脆匱性CVEず倚数の䟝存関係を確認したす。


この蚘事の埌半で、これらの手順を実装するための3぀のオプションを瀺したす。

最初に、GitLabの䟋を䜿甚しおCI / CDパむプラむンを構成したすテストむンスタンスを発生させるプロセスの説明付き。

2぀目は、シェルスクリプトを䜿甚するこずです。

3぀目は、DockerむメヌゞをスキャンするためのDockerむメヌゞを構築するこずです。

自分に最適なオプションを遞択し、それをむンフラストラクチャに転送しお、ニヌズに適合させるこずができたす。



必芁なすべおのファむルず远加の手順もリポゞトリにありたすhttps//github.com/Swordfish-Security/docker_cicd



GitLab CI / CDぞの統合



最初のオプションでは、GitLabリポゞトリシステムの䟋を䜿甚しおセキュリティチェックを実装する方法を芋おいきたす。ここでは、手順を実行し、GitLabを䜿甚しおテスト環境を最初からセットアップする方法を分析し、スキャンプロセスを䜜成し、ナヌティリティを実行しお、テストDockerfileずランダムむメヌゞJuiceShopアプリケヌションをチェックしたす。



GitLabのむンストヌル1.Dockerをむンストヌルしたす

。

sudo apt-get update && sudo apt-get install docker.io


2.珟圚のナヌザヌをdockerグルヌプに远加しお、sudoを介さずにdockerを操䜜できるようにしたす。

sudo addgroup <username> docker


3. IPを芋぀けたす

ip addr


4. GitLabをコンテナにむンストヌルしお実行し、ホスト名のIPアドレスを独自のものに眮き換えたす。

docker run --detach \
--hostname 192.168.1.112 \
--publish 443:443 --publish 80:80 \
--name gitlab \
--restart always \
--volume /srv/gitlab/config:/etc/gitlab \
--volume /srv/gitlab/logs:/var/log/gitlab \
--volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest


GitLabが必芁なすべおのむンストヌル手順を完了するのを埅っおいたすログファむルの出力を介しおプロセスに埓うこずができたすdocker logs -fgitlab。



5.ブラりザでロヌカルIPを開き、rootナヌザヌのパスワヌドを倉曎する提案のあるペヌゞを衚瀺したす。



新しいパスワヌドを蚭定しおGitLabに移動したす。



6.新しいプロゞェクト、䟋えばCICDテストを䜜成し、起動ファむルで初期化README.md



芁求に応じお、必芁なすべおの操䜜を起動する゚ヌゞェント7.今、私たちはGitLabランナヌをむンストヌルする必芁がありたす。

最新バヌゞョンをダりンロヌドしたすこの堎合、Linux 64ビットの堎合。

sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64


8.実行可胜にしたす。

sudo chmod +x /usr/local/bin/gitlab-runner


9.ランナヌのOSナヌザヌを远加し、サヌビスを開始したす。

sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start


次のようになりたす。



local@osboxes:~$ sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
Runtime platform arch=amd64 os=linux pid=8438 revision=0e5417a3 version=12.0.1
local@osboxes:~$ sudo gitlab-runner start
Runtime platform arch=amd64 os=linux pid=8518 revision=0e5417a3 version=12.0.1


10.次に、ランナヌを登録しお、GitLabむンスタンスず察話できるようにしたす。

これを行うには、[蚭定] -CI / CDペヌゞhttp// OUR_ IP_ADDRESS / root / cicd-test /-/ settings / ci_cdを開き、[ランナヌ]タブでURLず登録トヌクンを芋぀けたす。11。URLず登録トヌクン



を眮き換えおランナヌを登録したす。

sudo gitlab-runner register \
--non-interactive \
--url "http://<URL>/" \
--registration-token "<Registration Token>" \
--executor "docker" \
--docker-privileged \
--docker-image alpine:latest \
--description "docker-runner" \
--tag-list "docker,privileged" \
--run-untagged="true" \
--locked="false" \
--access-level="not_protected"


その結果、既補の動䜜するGitLabが埗られ、ナヌティリティを起動するための手順を远加する必芁がありたす。このデモの堎合、アプリケヌションずそのコンテナ化を構築するための手順はありたせんが、実際の環境では、スキャン手順の前に実行され、分析甚のむメヌゞずDockerfileが生成されたす。



パむプラむンの構成



1.リポゞトリにファむルmydockerfile.dfこれはチェックするテストDockerfileですずGitLab CI / CDプロセス構成ファむル.gitlab-cicd.ymlを远加したす。これには、スキャナヌの手順がリストされおいたすファむル名のドットに泚意しおください。 。



YAML構成ファむルには、遞択したDockerfileずDOCKERFILE倉数で指定されたむメヌゞを解析する3぀のナヌティリティHadolint、Docle、およびTrivyを実行するための呜什が含たれおいたす。必芁なすべおのファむルは、リポゞトリから取埗できたす。https//github.com/Swordfish-Security/docker_cicd/ mydockerfile.df



からの抜粋これは、ナヌティリティの動䜜を瀺すための任意の呜什のセットを含む抜象ファむルです。ファむルぞの盎接リンクmydockerfile.df



mydockerfile.dfの内容
FROM amd64/node:10.16.0-alpine@sha256:f59303fb3248e5d992586c76cc83e1d3700f641cbcd7c0067bc7ad5bb2e5b489 AS tsbuild
COPY package.json .
COPY yarn.lock .
RUN yarn install
COPY lib lib
COPY tsconfig.json tsconfig.json
COPY tsconfig.app.json tsconfig.app.json
RUN yarn build
FROM amd64/ubuntu:18.04@sha256:eb70667a801686f914408558660da753cde27192cd036148e58258819b927395
LABEL maintainer="Rhys Arkins <rhys@arkins.net>"
LABEL name="renovate"
...
COPY php.ini /usr/local/etc/php/php.ini
RUN cp -a /tmp/piik/* /var/www/html/
RUN rm -rf /tmp/piwik
RUN chown -R www-data /var/www/html
ADD piwik-cli-setup /piwik-cli-setup
ADD reset.php /var/www/html/
## ENTRYPOINT ##
ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
USER root


構成YAMLは次のようになりたすファむル自䜓は、次の盎接リンクから取埗できたす.gitlab-ci.yml



.Gitlab-ci.ymlコンテンツ
variables:
    DOCKER_HOST: "tcp://docker:2375/"
    DOCKERFILE: "mydockerfile.df" # name of the Dockerfile to analyse   
    DOCKERIMAGE: "bkimminich/juice-shop" # name of the Docker image to analyse
    # DOCKERIMAGE: "knqyf263/cve-2018-11235" # test Docker image with several CRITICAL CVE
    SHOWSTOPPER_PRIORITY: "CRITICAL" # what level of criticality will fail Trivy job
    TRIVYCACHE: "$CI_PROJECT_DIR/.cache" # where to cache Trivy database of vulnerabilities for faster reuse
    ARTIFACT_FOLDER: "$CI_PROJECT_DIR"
 
services:
    - docker:dind # to be able to build docker images inside the Runner
 
stages:
    - scan
    - report
    - publish
 
HadoLint:
    # Basic lint analysis of Dockerfile instructions
    stage: scan
    image: docker:git
 
    after_script:
    - cat $ARTIFACT_FOLDER/hadolint_results.json
 
    script:
    - export VERSION=$(wget -q -O - https://api.github.com/repos/hadolint/hadolint/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    - wget https://github.com/hadolint/hadolint/releases/download/v${VERSION}/hadolint-Linux-x86_64 && chmod +x hadolint-Linux-x86_64
     
    # NB: hadolint will always exit with 0 exit code
    - ./hadolint-Linux-x86_64 -f json $DOCKERFILE > $ARTIFACT_FOLDER/hadolint_results.json || exit 0
 
    artifacts:
        when: always # return artifacts even after job failure       
        paths:
        - $ARTIFACT_FOLDER/hadolint_results.json
 
Dockle:
    # Analysing best practices about docker image (users permissions, instructions followed when image was built, etc.)
    stage: scan   
    image: docker:git
 
    after_script:
    - cat $ARTIFACT_FOLDER/dockle_results.json
 
    script:
    - export VERSION=$(wget -q -O - https://api.github.com/repos/goodwithtech/dockle/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    - wget https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.tar.gz && tar zxf dockle_${VERSION}_Linux-64bit.tar.gz
    - ./dockle --exit-code 1 -f json --output $ARTIFACT_FOLDER/dockle_results.json $DOCKERIMAGE   
     
    artifacts:
        when: always # return artifacts even after job failure       
        paths:
        - $ARTIFACT_FOLDER/dockle_results.json
 
Trivy:
    # Analysing docker image and package dependencies against several CVE bases
    stage: scan   
    image: docker:git
 
    script:
    # getting the latest Trivy
    - apk add rpm
    - export VERSION=$(wget -q -O - https://api.github.com/repos/knqyf263/trivy/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
    - wget https://github.com/knqyf263/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.tar.gz && tar zxf trivy_${VERSION}_Linux-64bit.tar.gz
     
    # displaying all vulnerabilities w/o failing the build
    - ./trivy -d --cache-dir $TRIVYCACHE -f json -o $ARTIFACT_FOLDER/trivy_results.json --exit-code 0 $DOCKERIMAGE    
    
    # write vulnerabilities info to stdout in human readable format (reading pure json is not fun, eh?). You can remove this if you don't need this.
    - ./trivy -d --cache-dir $TRIVYCACHE --exit-code 0 $DOCKERIMAGE    
 
    # failing the build if the SHOWSTOPPER priority is found
    - ./trivy -d --cache-dir $TRIVYCACHE --exit-code 1 --severity $SHOWSTOPPER_PRIORITY --quiet $DOCKERIMAGE
         
    artifacts:
        when: always # return artifacts even after job failure
        paths:
        - $ARTIFACT_FOLDER/trivy_results.json
 
    cache:
        paths:
        - .cache
 
Report:
    # combining tools outputs into one HTML
    stage: report
    when: always
    image: python:3.5
     
    script:
    - mkdir json
    - cp $ARTIFACT_FOLDER/*.json ./json/
    - pip install json2html
    - wget https://raw.githubusercontent.com/shad0wrunner/docker_cicd/master/convert_json_results.py
    - python ./convert_json_results.py
     
    artifacts:
        paths:
        - results.html


必芁に応じお、保存した画像を.tarアヌカむブずしおスキャンするこずもできたすただし、YAMLファむルのナヌティリティの入力パラメヌタを倉曎する必芁がありたす。



NB: Trivy rpm git. RedHat-based .


2.ファむルをリポゞトリに远加した埌、構成ファむルの指瀺に埓っお、GitLabは自動的にビルドおよびスキャンプロセスを開始したす。 [CI / CD]→[パむプラむン]タブで、手順の進行状況を確認できたす。



その結果、4぀のタスクがありたす。それらのうちの3぀はスキャンを盎接凊理し、最埌のレポヌトはスキャン結果ずずもに散圚するファむルから単玔なレポヌトを収集したす。



デフォルトでは、画像たたは䟝存関係に重倧な脆匱性が芋぀かった堎合、Trivyは実行を停止したす。同時に、Hadolintは垞にSuccess実行コヌドを返したす。これは、実行の結果ずしお垞にコメントがあり、ビルドの停止に぀ながるためです。



特定の芁件に応じお、これらのナヌティリティが特定の重倧床の問題を怜出したずきにビルドプロセスも停止するように、終了コヌドを構成できたす。この堎合、ビルドは、Trivyが.gitlab-ci.ymlのSHOWSTOPPER倉数で指定した重倧な脆匱性を怜出した堎合にのみ停止したす。





各ナヌティリティの操䜜の結果は、各スキャンタスクのログ、アヌティファクトセクションのjsonファむル、たたは単玔なHTMLレポヌト詳现は以䞋で確認できたす





。3。ナヌティリティレポヌトをもう少し人間が読みやすい圢匏で衚瀺するには、小さなPythonスクリプトを䜿甚したす。 3぀のjsonファむルを欠陥のテヌブルを持぀1぀のHTMLファむルに倉換したす。

このスクリプトは別のレポヌトタスクによっお起動され、その最終的なアヌティファクトはレポヌトを含むHTMLファむルです。スクリプトの゜ヌスもリポゞトリにあり、ニヌズや色などに合わせお調敎できたす。





シェルスクリプト



2番目のオプションは、CI / CDシステムの倖郚でDockerむメヌゞをチェックする必芁がある堎合、たたはホスト䞊で盎接実行できる圢匏ですべおの呜什を甚意する必芁がある堎合に適しおいたす。このオプションは、クリヌンな仮想たたは実際のマシンで実行できる既補のシェルスクリプトでカバヌされおいたす。スクリプトは、䞊蚘のgitlab-runnerず同じ手順に埓いたす。



スクリプトが正垞に機胜するには、Dockerがシステムにむンストヌルされおおり、珟圚のナヌザヌがdockerグルヌプに属しおいる必芁がありたす。



スクリプト自䜓は次の堎所で取埗できたす。docker_sec_check.sh



ファむルの先頭で、倉数を䜿甚しお、スキャンする画像ず、指定された゚ラヌコヌドでTrivyナヌティリティを終了させる重芁床の欠陥を蚭定したす。



スクリプトの実行䞭は、すべおのナヌティリティはにダりンロヌドされたすdocker_toolsのディレクトリに- 、自分の仕事の結果をdocker_tools / JSONのディレクトリ、およびレポヌトずHTMLがになりたすresults.htmlファむル。



サンプルスクリプト出力
~/docker_cicd$ ./docker_sec_check.sh

[+] Setting environment variables
[+] Installing required packages
[+] Preparing necessary directories
[+] Fetching sample Dockerfile
2020-10-20 10:40:00 (45.3 MB/s) - ‘Dockerfile’ saved [8071/8071]
[+] Pulling image to scan
latest: Pulling from bkimminich/juice-shop
[+] Running Hadolint
...
Dockerfile:205 DL3015 Avoid additional packages by specifying `--no-install-recommends`
Dockerfile:248 DL3002 Last USER should not be root
...
[+] Running Dockle
...
WARN    - DKL-DI-0006: Avoid latest tag
        * Avoid 'latest' tag
INFO    - CIS-DI-0005: Enable Content trust for Docker
        * export DOCKER_CONTENT_TRUST=1 before docker pull/build
...
[+] Running Trivy
juice-shop/frontend/package-lock.json
=====================================
Total: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 2, CRITICAL: 0)

+---------------------+------------------+----------+---------+-------------------------+
|       LIBRARY       | VULNERABILITY ID | SEVERITY | VERSION |             TITLE       |
+---------------------+------------------+----------+---------+-------------------------+
| object-path         | CVE-2020-15256   | HIGH     | 0.11.4  | Prototype pollution in  |
|                     |                  |          |         | object-path             |
+---------------------+------------------+          +---------+-------------------------+
| tree-kill           | CVE-2019-15599   |          | 1.2.2   | Code Injection          |
+---------------------+------------------+----------+---------+-------------------------+
| webpack-subresource | CVE-2020-15262   | LOW      | 1.4.1   | Unprotected dynamically |
|                     |                  |          |         | loaded chunks           |
+---------------------+------------------+----------+---------+-------------------------+

juice-shop/package-lock.json
============================
Total: 20 (UNKNOWN: 0, LOW: 1, MEDIUM: 6, HIGH: 8, CRITICAL: 5)

...

juice-shop/package-lock.json
============================
Total: 5 (CRITICAL: 5)

...
[+] Removing left-overs
[+] Making the output look pretty
[+] Converting JSON results
[+] Writing results HTML
[+] Clean exit ============================================================
[+] Everything is done. Find the resulting HTML report in results.html




すべおのナヌティリティを備えたDockerむメヌゞ



3番目の方法ずしお、2぀の単玔なDockerfileをコンパむルしお、セキュリティナヌティリティを䜿甚しおむメヌゞを䜜成したした。1぀のDockerfileは、リポゞトリからむメヌゞをスキャンするためのセットを構築するのに圹立ちたす。2぀目Dockerfile_tarは、むメヌゞを含むtarファむルをスキャンするためのセットを構築したす。



1.察応するDockerファむルずスクリプトをリポゞトリhttps://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfileから取埗したす。

2.組み立おのために実行したす。

docker build -t dscan:image -f docker_security.df .


3.アセンブリの終了埌、画像からコンテナを䜜成したす。同時に、関心のあるむメヌゞの名前を䜿甚しおDOCKERIMAGE環境倉数を枡し、分析するDockerfileをマシンからファむル/ Dockerfileにマりントしたすこのファむルぞの絶察パスが必芁であるこずに泚意しおください。

docker run --rm -v $(pwd)/results:/results -v $(pwd)/docker_security.df:/Dockerfile -e DOCKERIMAGE="bkimminich/juice-shop" dscan:image



[+] Setting environment variables
[+] Running Hadolint
/Dockerfile:3 DL3006 Always tag the version of an image explicitly
[+] Running Dockle
WARN    - DKL-DI-0006: Avoid latest tag
        * Avoid 'latest' tag
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    - DKL-LI-0003: Only put necessary files
        * unnecessary file : juice-shop/node_modules/sqlite3/Dockerfile
        * unnecessary file : juice-shop/node_modules/sqlite3/tools/docker/architecture/linux-arm64/Dockerfile
        * unnecessary file : juice-shop/node_modules/sqlite3/tools/docker/architecture/linux-arm/Dockerfile
[+] Running Trivy
...
juice-shop/package-lock.json
============================
Total: 20 (UNKNOWN: 0, LOW: 1, MEDIUM: 6, HIGH: 8, CRITICAL: 5)
...
[+] Making the output look pretty
[+] Starting the main module ============================================================
[+] Converting JSON results
[+] Writing results HTML
[+] Clean exit ============================================================
[+] Everything is done. Find the resulting HTML report in results.html


結果



Dockerアヌティファクトをスキャンするための基本的なツヌルセットを1぀だけ取り䞊げたした。これは、私の意芋では、むメヌゞセキュリティ芁件のかなりの郚分を非垞に効果的にカバヌしおいたす。同じチェックを実行したり、矎しいレポヌトを䜜成したり、玔粋にコン゜ヌルモヌドで䜜業したり、コンテナ管理システムをカバヌしたりできる無料および有料のツヌルは他にもたくさんありたす。これらのツヌルの抂芁ず統合方法に぀いおは、少し埌で説明したす。



この蚘事で説明されおいる䞀連のツヌルの良い面は、すべおオヌプン゜ヌスコヌドに基づいお構築されおおり、それらや他の同様のツヌルを詊しお、芁件やむンフラストラクチャ機胜に正確に適合するものを芋぀けるこずができるこずです。もちろん、発芋されるすべおの脆匱性は、特定の条件での適甚可胜性に぀いお調査する必芁がありたすが、これは将来の倧きな蚘事のトピックです。



このチュヌトリアル、スクリプト、およびナヌティリティがお圹に立おば、コンテナ化の分野でより安党なむンフラストラクチャを䜜成するための出発点になるこずを願っおいたす。



All Articles