Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker
Pozdravljeni, Habr!

V sodobni realnosti, zaradi vse večje vloge kontejnerizacije v razvojnih procesih, vprašanje zagotavljanja varnosti različnih faz in entitet, povezanih s kontejnerji, ni najmanj pomembno vprašanje. Izvajanje ročnih pregledov je zamudno, zato bi bilo dobro narediti vsaj prve korake k avtomatizaciji tega procesa.

V tem članku bom delil že pripravljene skripte za implementacijo več varnostnih pripomočkov Docker in navodila za namestitev majhnega predstavitvenega stojala za testiranje tega postopka. Materiale lahko uporabite za eksperimentiranje s tem, kako organizirati postopek testiranja varnosti slik in navodil Dockerfile. Jasno je, da je razvojna in implementacijska infrastruktura za vsakogar drugačna, zato bom spodaj navedel več možnih možnosti.

Pripomočki za varnostno preverjanje

Obstaja veliko število različnih pomožnih aplikacij in skriptov, ki izvajajo preverjanja različnih vidikov infrastrukture Docker. Nekatere izmed njih smo že opisali v prejšnjem članku (https://habr.com/ru/company/swordfish_security/blog/518758/#docker-security), v tem gradivu pa bi se rad osredotočil na tri izmed njih, ki pokrivajo večino varnostnih zahtev za slike Docker, zgrajene med razvojnim procesom. Poleg tega bom pokazal tudi primer, kako je mogoče te tri pripomočke povezati v en cevovod za izvajanje varnostnih pregledov.

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

Precej preprost konzolni pripomoček, ki pomaga, kot prvi približek, oceniti pravilnost in varnost navodil Dockerfile (na primer uporaba samo pooblaščenih registrov slik ali uporaba sudo).

Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

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

Konzolni pripomoček, ki deluje s sliko (ali s shranjenim tar arhivom slike), ki preverja pravilnost in varnost določene slike kot take, analizira njene plasti in konfiguracijo – kateri uporabniki so ustvarjeni, katera navodila so uporabljena, katera nosilci so nameščeni, prisotnost praznega gesla itd. d. Zaenkrat število preverjanj ni zelo veliko in temelji na več naših lastnih preverjanjih in priporočilih CIS (Center za internetno varnost) Benchmark za Docker.
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

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

Ta pripomoček je namenjen iskanju dveh vrst ranljivosti - težave z različicami operacijskega sistema (podprto s strani Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) in težave z odvisnostmi (Gemfile.lock, Pipfile.lock, composer.lock, package -lock.json, yarn.lock, cargo.lock). Trivy lahko skenira sliko v repozitoriju in lokalno sliko ter lahko skenira tudi na podlagi prenesene datoteke .tar s sliko Docker.

Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

Možnosti za izvajanje pripomočkov

Da bi opisane aplikacije preizkusili v izoliranem okolju, bom podal navodila za namestitev vseh pripomočkov v nekoliko poenostavljenem postopku.

Glavna ideja je pokazati, kako lahko implementirate samodejno preverjanje vsebine datotek Docker in slik Docker, ki so ustvarjene med razvojem.

Samo preverjanje je sestavljeno iz naslednjih korakov:

  1. Preverjanje pravilnosti in varnosti navodil Dockerfile z uporabo pripomočka linter Hadolint
  2. Preverjanje pravilnosti in varnosti končne in vmesne slike s pomočjo pripomočka Dockle
  3. Preverjanje prisotnosti javno znanih ranljivosti (CVE) v osnovni sliki in številnih odvisnosti - z uporabo pripomočka Trivy

Kasneje v članku bom podal tri možnosti za izvedbo teh korakov:
Prvi je s konfiguriranjem cevovoda CI/CD z uporabo GitLaba kot primera (z opisom postopka dvigovanja testne instance).
Drugi je uporaba lupinskega skripta.
Tretja vključuje izdelavo slike Docker za skeniranje slik Docker.
Izberete lahko možnost, ki vam najbolj ustreza, jo prenesete na svojo infrastrukturo in prilagodite svojim potrebam.

Vse potrebne datoteke in dodatna navodila se nahajajo tudi v repozitoriju: https://github.com/Swordfish-Security/docker_cicd

Integracija v GitLab CI/CD

V prvi možnosti si bomo ogledali, kako lahko implementirate varnostne preglede na primeru sistema repozitorija GitLab. Tukaj bomo šli skozi korake in ugotovili, kako namestiti testno okolje z GitLabom iz nič, ustvariti postopek skeniranja in zagnati pripomočke za preverjanje testne Dockerfile in naključne slike - aplikacije JuiceShop.

Namestitev GitLaba
1. Namestite Docker:

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

2. Dodajte trenutnega uporabnika v skupino dockerjev, da boste lahko delali z dockerjem brez uporabe sudo:

sudo addgroup <username> docker

3. Poiščite svoj IP:

ip addr

4. Namestite in zaženite GitLab v vsebniku, tako da naslov IP v imenu gostitelja zamenjate s svojim:

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

Počakamo, da GitLab dokonča vse potrebne namestitvene postopke (postopek lahko spremljate prek izhodne datoteke dnevnika: docker logs -f gitlab).

5. Odprite svoj lokalni IP v brskalniku in si oglejte stran, ki zahteva, da spremenite geslo za uporabnika root:
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker
Nastavite novo geslo in pojdite na GitLab.

6. Ustvarite nov projekt, na primer cicd-test in ga inicializirajte z začetno datoteko PREBERITE.md:
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker
7. Zdaj moramo namestiti GitLab Runner: agenta, ki bo izvajal vse potrebne operacije na zahtevo.
Prenesite najnovejšo različico (v tem primeru za 64-bitni Linux):

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

8. Naj bo izvršljivo:

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

9. Dodajte uporabnika OS za Runner in zaženite storitev:

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

Videti bi moralo nekako takole:

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. Sedaj registriramo Runner, da lahko komunicira z našim primerkom GitLab.
Če želite to narediti, odprite stran Settings-CI/CD (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) in na zavihku Runners poiščite URL in registracijski žeton:
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker
11. Registrirajte Runner tako, da zamenjate URL in registracijski žeton:

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"

Kot rezultat dobimo že pripravljen delujoč GitLab, v katerega moramo dodati navodila za zagon naših pripomočkov. V tej predstavitvi nimamo korakov za gradnjo aplikacije in njeno shranjevanje v vsebnike, toda v resničnem okolju bi bili ti pred koraki skeniranja in bi ustvarili slike in Dockerfile za analizo.

konfiguracijo cevovoda

1. Dodajte datoteke v repozitorij mydockerfile.df (to je testna datoteka Docker, ki jo bomo preverili) in konfiguracijska datoteka procesa GitLab CI/CD .gitlab-cicd.yml, ki navaja navodila za optične bralnike (upoštevajte piko v imenu datoteke).

Konfiguracijska datoteka YAML vsebuje navodila za zagon treh pripomočkov (Hadolint, Dockle in Trivy), ki bodo analizirali izbrano datoteko Dockerfile in sliko, navedeno v spremenljivki DOCKERFILE. Vse potrebne datoteke lahko vzamete iz repozitorija: https://github.com/Swordfish-Security/docker_cicd/

Odlomek iz mydockerfile.df (to je abstraktna datoteka z nizom poljubnih navodil samo za prikaz delovanja pripomočka). Neposredna povezava do datoteke: mydockerfile.df

Vsebina 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

Konfiguracija YAML je videti tako (samo datoteko najdete preko neposredne povezave tukaj: .gitlab-ci.yml):

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

Po potrebi lahko skenirate tudi shranjene slike v obliki arhiva .tar (vendar boste morali spremeniti vhodne parametre za pripomočke v datoteki YAML)

Opomba: Trivy zahteva nameščen rpm и git. V nasprotnem primeru bo ustvaril napake pri skeniranju slik, ki temeljijo na RedHat, in prejemanju posodobitev baze podatkov ranljivosti.

2. Po dodajanju datotek v repozitorij bo GitLab v skladu z navodili v naši konfiguracijski datoteki samodejno začel postopek gradnje in skeniranja. Na zavihku CI/CD → Cevovodi si lahko ogledate potek navodil.

Kot rezultat imamo štiri naloge. Trije se ukvarjajo neposredno s skeniranjem, zadnji (Poročilo) pa zbira preprosto poročilo iz razpršenih datotek z rezultati skeniranja.
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker
Privzeto se Trivy preneha izvajati, če so v sliki ali odvisnostih odkrite KRITIČNE ranljivosti. Hkrati Hadolint vedno vrne kodo uspeha, ker vedno povzroči komentarje, kar povzroči zaustavitev gradnje.

Glede na vaše specifične zahteve lahko konfigurirate izhodno kodo, tako da ko ti pripomočki zaznajo težave določene kritičnosti, prav tako ustavijo postopek gradnje. V našem primeru se bo gradnja ustavila samo, če Trivy zazna ranljivost s kritičnostjo, ki smo jo podali v spremenljivki SHOWSTOPPER v .gitlab-ci.yml.
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

Rezultat vsakega pripomočka si lahko ogledate v dnevniku vsakega opravila skeniranja, neposredno v datotekah json v razdelku artefaktov ali v preprostem poročilu HTML (več o tem spodaj):
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

3. Za predstavitev poročil o pripomočkih v nekoliko bolj berljivi obliki se uporabi majhen skript Python za pretvorbo treh datotek JSON v eno datoteko HTML s tabelo napak.
Ta skript se zažene z ločeno nalogo Report, njegov končni artefakt pa je datoteka HTML s poročilom. Izvor skripte je tudi v repozitoriju in ga je mogoče prilagoditi vašim potrebam, barvam itd.
Metode in primeri implementacije pripomočkov za preverjanje varnosti Docker

Lupinski skript

Druga možnost je primerna za primere, ko morate preveriti slike Docker zunaj sistema CI/CD ali morate imeti vsa navodila v obliki, ki jo je mogoče izvesti neposredno na gostitelju. To možnost pokriva že pripravljen lupinski skript, ki ga je mogoče zagnati na čistem virtualnem (ali celo resničnem) računalniku. Skript izvaja ista navodila kot gitlab-runner, opisan zgoraj.

Za uspešno izvajanje skripta mora biti Docker nameščen v sistemu in trenutni uporabnik mora biti v skupini dockerjev.

Sam scenarij najdete tukaj: docker_sec_check.sh

Na začetku datoteke spremenljivke določajo, katero sliko je treba skenirati in katere kritične napake bodo povzročile izhod pripomočka Trivy z navedeno kodo napake.

Med izvajanjem skripta bodo vsi pripomočki preneseni v imenik docker_tools, rezultati njihovega dela so v imeniku docker_tools/json, in HTML s poročilom bo v datoteki rezultati.html.

Primer izpisa skripta

~/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 slika z vsemi pripomočki

Kot tretjo možnost sem sestavil dve preprosti datoteki Dockerfile za ustvarjanje slike z varnostnimi pripomočki. En Dockerfile bo pomagal zgraditi nabor za skeniranje slike iz repozitorija, drugi (Dockerfile_tar) pa bo pomagal zgraditi nabor za skeniranje datoteke tar s sliko.

1. Vzemite ustrezno datoteko Docker in skripte iz repozitorija https://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfile.
2. Zaženemo ga za montažo:

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

3. Po končani montaži iz slike izdelamo posodo. Hkrati posredujemo spremenljivko okolja DOCKERIMAGE z imenom slike, ki nas zanima, in priklopimo datoteko Dockerfile, ki jo želimo analizirati iz našega stroja v datoteko /Dockerfile (upoštevajte, da je potrebna absolutna pot do te datoteke):

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

Ugotovitve

Ogledali smo si le en osnovni nabor pripomočkov za skeniranje artefaktov Docker, ki po mojem mnenju zelo učinkovito pokriva spodoben del varnostnih zahtev slike. Obstaja tudi veliko število plačljivih in brezplačnih orodij, ki lahko izvajajo iste preglede, rišejo čudovita poročila ali delujejo izključno v konzolnem načinu, pokrivajo sisteme za upravljanje vsebnikov itd. Pregled teh orodij in kako jih integrirati se lahko pojavi malo kasneje .

Dobra stvar nabora orodij, opisanih v članku, je, da so vsa zgrajena na odprtokodni kodi in lahko eksperimentirate z njimi in drugimi podobnimi orodji, da najdete tisto, kar ustreza vašim zahtevam in infrastrukturnim funkcijam. Seveda je treba vse najdene ranljivosti preučiti glede uporabnosti v določenih pogojih, vendar je to tema za prihodnji večji članek.

Upam, da vam bodo ta vodnik, skripte in pripomočki pomagali in postali izhodišče za ustvarjanje varnejše infrastrukture na področju kontejnerizacije.

Vir: www.habr.com

Dodaj komentar