Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

Metody a příklady implementace utilit pro kontrolu zabezpečení Docker
Čau Habr!

V moderní realitě, vzhledem k rostoucí roli kontejnerizace ve vývojových procesech, není otázka zajištění bezpečnosti různých fází a entit spojených s kontejnery tím nejméně důležitým problémem. Provádění ručních kontrol je časově náročné, proto by bylo dobré podniknout alespoň počáteční kroky k automatizaci tohoto procesu.

V tomto článku se podělím o hotové skripty pro implementaci několika bezpečnostních nástrojů Docker a pokyny, jak nasadit malý ukázkový stojan pro testování tohoto procesu. Materiály můžete použít k experimentování s tím, jak organizovat proces testování bezpečnosti obrazů a pokynů Dockerfile. Je jasné, že každý má jinou vývojovou a implementační infrastrukturu, proto níže uvedu několik možných možností.

Nástroje pro kontrolu zabezpečení

Existuje velké množství různých pomocných aplikací a skriptů, které provádějí kontroly různých aspektů infrastruktury Docker. Některé z nich již byly popsány v předchozím článku (https://habr.com/ru/company/swordfish_security/blog/518758/#docker-security), a v tomto materiálu bych se rád zaměřil na tři z nich, které pokrývají většinu bezpečnostních požadavků na obrazy Docker vytvořené během procesu vývoje. Kromě toho také ukážu příklad, jak lze tyto tři nástroje propojit do jednoho potrubí pro provádění bezpečnostních kontrol.

Hadolint
https://github.com/hadolint/hadolint

Poměrně jednoduchá konzolová utilita, která pomáhá jako první přiblížení vyhodnotit správnost a bezpečnost instrukcí Dockerfile (například pomocí pouze autorizovaných registrů obrázků nebo pomocí sudo).

Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

Dockle
https://github.com/goodwithtech/dockle

Konzolová utilita pracující s obrázkem (nebo s uloženým tar archivem obrázku), která kontroluje správnost a bezpečnost konkrétního obrázku jako takového, analyzuje jeho vrstvy a konfiguraci - kteří uživatelé jsou vytvářeni, jaké instrukce se používají, které svazky jsou připojeny, přítomnost prázdného hesla atd. d. Počet kontrol zatím není příliš velký a je založen na několika našich vlastních kontrolách a doporučeních Benchmark CIS (Centrum pro internetovou bezpečnost). pro Docker.
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

Trivy
https://github.com/aquasecurity/trivy

Tato utilita je zaměřena na nalezení dvou typů zranitelností – problémy se sestavováním OS (podporované Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) a problémy se závislostmi (Gemfile.lock, Pipfile.lock, skladatel.lock, package -lock.json , yarn.lock, cargo.lock). Trivy může skenovat jak obrázek v úložišti, tak místní obrázek a může také skenovat na základě přeneseného souboru .tar s obrázkem Docker.

Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

Možnosti implementace utilit

Abychom si popsané aplikace vyzkoušeli v izolovaném prostředí, poskytnu návod na instalaci všech utilit v poněkud zjednodušeném procesu.

Hlavní myšlenkou je ukázat, jak můžete implementovat automatické ověřování obsahu souborů Dockerfiles a obrázků Docker, které jsou vytvořeny během vývoje.

Samotná kontrola se skládá z následujících kroků:

  1. Kontrola správnosti a bezpečnosti pokynů Dockerfile pomocí nástroje linter Hadolint
  2. Kontrola správnosti a bezpečnosti finálních a přechodných snímků pomocí utility Dockle
  3. Kontrola přítomnosti veřejně známých chyb zabezpečení (CVE) v základním obrazu a řady závislostí - pomocí nástroje Trivy

Dále v článku uvedu tři možnosti implementace těchto kroků:
První je konfigurace kanálu CI/CD pomocí GitLab jako příkladu (s popisem procesu vytváření testovací instance).
Druhým je použití skriptu shellu.
Třetí zahrnuje vytvoření obrazu Docker pro skenování obrázků Docker.
Můžete si vybrat možnost, která vám nejvíce vyhovuje, přenést ji do vaší infrastruktury a přizpůsobit ji svým potřebám.

Všechny potřebné soubory a další pokyny jsou také umístěny v úložišti: https://github.com/Swordfish-Security/docker_cicd

Integrace do GitLab CI/CD

V první možnosti se podíváme na to, jak můžete jako příklad implementovat bezpečnostní kontroly pomocí systému úložiště GitLab. Zde si projdeme kroky a zjistíme, jak nainstalovat testovací prostředí s GitLab od začátku, vytvořit proces skenování a spustit nástroje pro kontrolu testovacího Dockerfile a náhodného obrázku – aplikaci JuiceShop.

Instalace GitLab
1. Nainstalujte Docker:

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

2. Přidejte aktuálního uživatele do skupiny docker, abyste mohli pracovat s dockerem bez použití sudo:

sudo addgroup <username> docker

3. Najděte svou IP:

ip addr

4. Nainstalujte a spusťte GitLab v kontejneru a nahraďte IP adresu v názvu hostitele svou vlastní:

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

Čekáme, až GitLab dokončí všechny potřebné instalační procedury (proces můžete sledovat prostřednictvím výstupu souboru protokolu: docker logs -f gitlab).

5. Otevřete v prohlížeči svou místní IP adresu a zobrazte stránku s výzvou ke změně hesla pro uživatele root:
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker
Nastavte si nové heslo a přejděte na GitLab.

6. Vytvořte nový projekt, například cicd-test, a inicializujte jej pomocí startovacího souboru README.md:
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker
7. Nyní potřebujeme nainstalovat GitLab Runner: agenta, který na požádání spustí všechny potřebné operace.
Stáhněte si nejnovější verzi (v tomto případě pro 64bitový Linux):

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

8. Vytvořte jej spustitelný:

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

9. Přidejte uživatele operačního systému pro Runner a spusťte službu:

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

Mělo by to vypadat nějak takto:

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. Nyní zaregistrujeme Runner, aby mohl interagovat s naší instancí GitLab.
Chcete-li to provést, otevřete stránku Settings-CI/CD (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) a na kartě Runners najděte adresu URL a registrační token:
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker
11. Zaregistrujte Runner nahrazením adresy URL a registračního tokenu:

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"

Výsledkem je, že dostaneme hotový funkční GitLab, do kterého musíme přidat instrukce pro spuštění našich utilit. V této ukázce nemáme kroky k sestavení aplikace a její kontejnerizaci, ale v reálném prostředí by tyto kroky předcházely skenovacím krokům a generovaly obrázky a Dockerfile pro analýzu.

konfigurace potrubí

1. Přidejte soubory do úložiště mydockerfile.df (toto je testovací soubor Dockerfile, který zkontrolujeme) a konfigurační soubor procesu GitLab CI/CD .gitlab-cicd.yml, kde jsou uvedeny pokyny pro skenery (všimněte si tečky v názvu souboru).

Konfigurační soubor YAML obsahuje pokyny ke spuštění tří nástrojů (Hadolint, Dockle a Trivy), které analyzují vybraný soubor Dockerfile a obrázek zadaný v proměnné DOCKERFILE. Všechny potřebné soubory lze převzít z úložiště: https://github.com/Swordfish-Security/docker_cicd/

Výpis z mydockerfile.df (toto je abstraktní soubor se sadou libovolných instrukcí pouze pro demonstraci činnosti nástroje). Přímý odkaz na soubor: mydockerfile.df

Obsah souboru 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 <[email protected]>"
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

Konfigurace YAML vypadá takto (samotný soubor najdete přes přímý odkaz zde: .gitlab-ci.yml):

Obsah .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

V případě potřeby můžete také skenovat uložené obrázky ve formě archivu .tar (budete však muset změnit vstupní parametry pro utility v souboru YAML)

Poznámka: Trivy vyžaduje instalaci min и git. V opačném případě bude generovat chyby při skenování obrázků založených na RedHat a přijímání aktualizací databáze zranitelnosti.

2. Po přidání souborů do úložiště, podle pokynů v našem konfiguračním souboru, GitLab automaticky zahájí proces sestavování a skenování. Na záložce CI/CD → Pipelines můžete vidět průběh instrukcí.

Ve výsledku máme čtyři úkoly. Tři z nich se zabývají přímo skenováním a poslední (Report) shromažďuje jednoduchou zprávu z rozptýlených souborů s výsledky skenování.
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker
Ve výchozím nastavení se Trivy zastaví, pokud jsou v obrazu nebo závislostech detekovány KRITICKÉ zranitelnosti. Zároveň Hadolint vždy vrací úspěšný kód, protože vždy vede k komentářům, což způsobí zastavení sestavení.

V závislosti na vašich konkrétních požadavcích můžete nakonfigurovat ukončovací kód tak, že když tyto obslužné programy zjistí problémy s určitou kritickostí, zastaví také proces sestavení. V našem případě se sestavování zastaví pouze v případě, že Trivy detekuje zranitelnost s kritičností, kterou jsme zadali v proměnné SHOWSTOPPER v .gitlab-ci.yml.
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

Výsledek každého nástroje lze zobrazit v protokolu každé úlohy skenování, přímo v souborech json v sekci artefaktů nebo v jednoduché zprávě HTML (více níže):
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

3. Chcete-li prezentovat zprávy o nástroji v trochu čitelnější podobě, používá se malý skript Python pro převod tří souborů JSON do jednoho souboru HTML s tabulkou defektů.
Tento skript se spouští samostatnou úlohou Report a jeho konečným artefaktem je soubor HTML s reportem. Zdroj skriptu je také v úložišti a lze jej upravit tak, aby vyhovoval vašim potřebám, barvám atd.
Metody a příklady implementace utilit pro kontrolu zabezpečení Docker

Shell skript

Druhá možnost je vhodná pro případy, kdy potřebujete zkontrolovat obrazy Dockeru mimo CI/CD systém nebo potřebujete mít všechny instrukce ve formě, kterou lze spustit přímo na hostiteli. Tuto možnost zastřešuje již hotový shell skript, který lze spustit na čistém virtuálním (nebo i skutečném) stroji. Skript provádí stejné instrukce jako výše popsaný gitlab-runner.

Aby skript úspěšně běžel, musí být v systému nainstalován Docker a aktuální uživatel musí být ve skupině dockerů.

Samotný skript najdete zde: docker_sec_check.sh

Na začátku souboru proměnné určují, který obrázek je třeba naskenovat a které závady v kritickosti způsobí ukončení obslužného programu Trivy se zadaným chybovým kódem.

Během provádění skriptu budou všechny nástroje staženy do adresáře docker_tools, výsledky jejich práce jsou v adresáři docker_tools/jsona HTML s přehledem bude v souboru výsledky.html.

Příklad výstupu skriptu

~/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 image se všemi nástroji

Jako třetí alternativu jsem zkompiloval dva jednoduché soubory Dockerfiles pro vytvoření obrazu s bezpečnostními nástroji. Jeden Dockerfile pomůže sestavit sadu pro skenování obrázku z úložiště, druhý (Dockerfile_tar) pomůže sestavit sadu pro skenování souboru tar s obrázkem.

1. Vezměte odpovídající soubor Docker a skripty z úložiště https://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfile.
2. Spustíme jej k montáži:

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

3. Po dokončení montáže vytvoříme z obrázku kontejner. Zároveň předáme proměnnou prostředí DOCKERIMAGE s názvem obrázku, který nás zajímá, a do souboru připojíme Dockerfile, který chceme analyzovat z našeho stroje. /Dockerfile (všimněte si, že je vyžadována absolutní cesta k tomuto souboru):

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

výsledky

Podívali jsme se pouze na jednu základní sadu utilit pro skenování artefaktů Dockeru, která dle mého názoru velmi efektivně pokrývá slušnou část požadavků na bezpečnost obrazu. Existuje také velké množství placených i bezplatných nástrojů, které dokážou provádět stejné kontroly, kreslit krásné sestavy nebo pracovat čistě v konzolovém režimu, pokrývají systémy pro správu kontejnerů atd. Přehled těchto nástrojů a jejich integrace se může objevit o něco později .

Dobrá věc na sadě nástrojů popsaných v tomto článku je, že všechny jsou open source a můžete s nimi a dalšími podobnými nástroji experimentovat, abyste našli to, co vyhovuje vašim potřebám a infrastruktuře. Všechny nalezené zranitelnosti by samozřejmě měly být prostudovány z hlediska použitelnosti v konkrétních podmínkách, ale to je téma na budoucí velký článek.

Doufám, že vám tato příručka, skripty a nástroje pomohou a stanou se výchozím bodem pro vytvoření bezpečnější infrastruktury v oblasti kontejnerizace.

Zdroj: www.habr.com

Přidat komentář