Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere
Hej Habr!

U savremenoj stvarnosti, zbog sve veće uloge kontejnerizacije u razvojnim procesima, pitanje osiguranja sigurnosti različitih faza i entiteta povezanih sa kontejnerima nije najmanje važno pitanje. Provođenje ručnih provjera je dugotrajno, pa bi bilo dobro poduzeti barem početne korake ka automatizaciji ovog procesa.

U ovom članku podijelit ću gotove skripte za implementaciju nekoliko Docker sigurnosnih uslužnih programa i upute o tome kako postaviti mali demo stalak za testiranje ovog procesa. Možete koristiti materijale za eksperimentiranje kako organizirati proces testiranja sigurnosti Dockerfile slika i uputa. Jasno je da je svačija infrastruktura razvoja i implementacije različita, pa ću u nastavku dati nekoliko mogućih opcija.

Uslužni programi za sigurnosnu provjeru

Postoji veliki broj različitih pomoćnih aplikacija i skripti koje vrše provjere na različitim aspektima Docker infrastrukture. Neki od njih su već opisani u prethodnom članku (https://habr.com/ru/company/swordfish_security/blog/518758/#docker-security), a u ovom materijalu bih se fokusirao na tri od njih, koji pokrivaju većinu sigurnosnih zahtjeva za Docker slike izgrađene tokom procesa razvoja. Osim toga, pokazat ću i primjer kako se ova tri uslužna programa mogu povezati u jedan cjevovod za obavljanje sigurnosnih provjera.

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

Prilično jednostavan uslužni program za konzolu koji pomaže, kao prvu aproksimaciju, procijeniti ispravnost i sigurnost Dockerfile instrukcija (na primjer, korištenje samo ovlaštenih registara slika ili korištenje sudo).

Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

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

Uslužni program za konzolu koji radi sa slikom (ili sa sačuvanom tar arhivom slike), koji provjerava ispravnost i sigurnost određene slike kao takve, analizirajući njene slojeve i konfiguraciju - koji su korisnici kreirani, koje upute se koriste, koje su montirani volumeni, prisustvo prazne lozinke itd. d. Do sada broj provjera nije jako velik i baziran je na nekoliko naših vlastitih provjera i preporuka CIS (Centar za Internet sigurnost) Benchmark za Docker.
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

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

Ovaj uslužni program ima za cilj pronalaženje dvije vrste ranjivosti - problemi s izgradnjom OS-a (podržani od Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) i problemi s ovisnostima (Gemfile.lock, Pipfile.lock, composer.lock, package -lock.json , yarn.lock, cargo.lock). Trivy može skenirati i sliku u spremištu i lokalnu sliku, a također može skenirati na osnovu prenesene .tar datoteke sa Docker slikom.

Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

Opcije za implementaciju komunalnih usluga

Kako bih isprobao opisane aplikacije u izoliranom okruženju, dat ću upute za instaliranje svih uslužnih programa u donekle pojednostavljenom procesu.

Glavna ideja je pokazati kako možete implementirati automatsku verifikaciju sadržaja Dockerfiles-a i Docker slika koje se kreiraju tokom razvoja.

Sama provjera se sastoji od sljedećih koraka:

  1. Provjera ispravnosti i sigurnosti Dockerfile instrukcija pomoću uslužnog programa linter Hadolint
  2. Provjera ispravnosti i sigurnosti konačnih i srednjih slika pomoću uslužnog programa Dockle
  3. Provjera prisutnosti javno poznatih ranjivosti (CVE) u osnovnoj slici i brojnih ovisnosti - pomoću uslužnog programa Trivy

Kasnije ću u članku dati tri opcije za implementaciju ovih koraka:
Prvi je konfigurisanjem CI/CD cevovoda koristeći GitLab kao primer (sa opisom procesa podizanja test instance).
Drugi je korištenje shell skripte.
Treći uključuje pravljenje Docker slike za skeniranje Docker slika.
Možete odabrati opciju koja vam najviše odgovara, prenijeti je na svoju infrastrukturu i prilagoditi je svojim potrebama.

Svi potrebni fajlovi i dodatna uputstva se takođe nalaze u spremištu: https://github.com/Swordfish-Security/docker_cicd

Integracija u GitLab CI/CD

U prvoj opciji ćemo pogledati kako možete implementirati sigurnosne provjere koristeći GitLab sistem spremišta kao primjer. Ovdje ćemo proći kroz korake i shvatiti kako da instaliramo testno okruženje sa GitLab-om od nule, kreiramo proces skeniranja i pokrenemo uslužne programe za provjeru testnog Dockerfile-a i nasumične slike - JuiceShop aplikaciju.

Instaliranje GitLaba
1. Instalirajte Docker:

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

2. Dodajte trenutnog korisnika u docker grupu tako da možete raditi s dockerom bez korištenja sudo:

sudo addgroup <username> docker

3. Pronađite svoju IP adresu:

ip addr

4. Instalirajte i pokrenite GitLab u kontejneru, zamjenjujući IP adresu u nazivu hosta svojom:

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

Čekamo dok GitLab ne završi sve potrebne instalacijske procedure (možete pratiti proces kroz izlaz datoteke dnevnika: docker logs -f gitlab).

5. Otvorite svoj lokalni IP u pretraživaču i vidite stranicu koja od vas traži da promijenite lozinku za root korisnika:
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere
Postavite novu lozinku i idite na GitLab.

6. Kreirajte novi projekat, na primjer cicd-test i inicijalizirajte ga sa start datotekom README.md:
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere
7. Sada moramo da instaliramo GitLab Runner: agent koji će izvoditi sve potrebne operacije na zahtev.
Preuzmite najnoviju verziju (u ovom slučaju za Linux 64-bit):

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

8. Učinite ga izvršnim:

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

9. Dodajte OS korisnika za Runner i pokrenite uslugu:

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

Trebalo bi izgledati otprilike ovako:

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. Sada registrujemo Runner tako da može komunicirati sa našom GitLab instancom.
Da biste to učinili, otvorite stranicu Settings-CI/CD (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) i na kartici Runners pronađite URL i token za registraciju:
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere
11. Registrirajte Runner zamjenom URL-a i registracijskog tokena:

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"

Kao rezultat, dobijamo gotov GitLab koji radi, u koji trebamo dodati upute za pokretanje naših uslužnih programa. U ovoj demonstraciji nemamo korake za izgradnju aplikacije i njeno spremanje u kontejner, ali u stvarnom okruženju oni bi prethodili koracima skeniranja i generirali slike i Dockerfile za analizu.

konfiguraciju cjevovoda

1. Dodajte datoteke u spremište mydockerfile.df (ovo je testni Dockerfile koji ćemo provjeriti) i GitLab CI/CD konfiguracijski fajl procesa .gitlab-cicd.yml, koji navodi uputstva za skenere (obratite pažnju na tačku u nazivu datoteke).

YAML konfiguracijska datoteka sadrži upute za pokretanje tri pomoćna programa (Hadolint, Dockle i Trivy) koji će analizirati odabrani Dockerfile i sliku specificiranu u varijabli DOCKERFILE. Sve potrebne datoteke možete preuzeti iz spremišta: https://github.com/Swordfish-Security/docker_cicd/

Ekstrakt iz mydockerfile.df (ovo je apstraktna datoteka sa skupom proizvoljnih instrukcija samo za demonstraciju rada uslužnog programa). Direktan link na fajl: mydockerfile.df

Sadržaj 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-a izgleda ovako (sama datoteka se može pronaći putem direktnog linka ovdje: .gitlab-ci.yml):

Sadržaj .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

Ako je potrebno, možete skenirati i sačuvane slike u obliku .tar arhive (međutim, morat ćete promijeniti ulazne parametre za uslužne programe u YAML datoteci)

Napomena: Trivy zahteva instaliran min и git. U suprotnom će generirati greške prilikom skeniranja slika baziranih na RedHat-u i primanja ažuriranja baze podataka ranjivosti.

2. Nakon dodavanja datoteka u spremište, prema uputama u našoj konfiguracijskoj datoteci, GitLab će automatski započeti proces izgradnje i skeniranja. Na kartici CI/CD → Cjevovodi možete vidjeti napredak instrukcija.

Kao rezultat, imamo četiri zadatka. Tri od njih se bave direktno skeniranjem, a posljednji (Izvještaj) prikuplja jednostavan izvještaj iz raštrkanih datoteka s rezultatima skeniranja.
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere
Podrazumevano, Trivy prestaje da radi ako se otkriju KRITIČNE ranjivosti na slici ili zavisnosti. U isto vrijeme, Hadolint uvijek vraća kod uspjeha jer uvijek rezultira komentarima, što uzrokuje zaustavljanje izgradnje.

Ovisno o vašim specifičnim zahtjevima, možete konfigurirati izlazni kod tako da kada ovi uslužni programi otkriju probleme određene kritičnosti, također zaustavljaju proces izgradnje. U našem slučaju, izgradnja će se zaustaviti samo ako Trivy otkrije ranjivost s kritičnošću koju smo naveli u varijabli SHOWSTOPPER u .gitlab-ci.yml.
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

Rezultat svakog uslužnog programa može se vidjeti u dnevniku svakog zadatka skeniranja, direktno u json datotekama u odjeljku artefakata ili u jednostavnom HTML izvještaju (više o tome u nastavku):
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

3. Da bi se izvještaji o korisnosti predstavili u malo čitljivijoj formi, koristi se mala Python skripta za pretvaranje tri JSON datoteke u jednu HTML datoteku sa tabelom nedostataka.
Ovu skriptu pokreće poseban zadatak Report, a njen konačni artefakt je HTML datoteka sa izvještajem. Izvor skripte je također u spremištu i može se prilagoditi vašim potrebama, bojama itd.
Metode i primjeri implementacije uslužnih programa Docker sigurnosne provjere

Shell skripta

Druga opcija je pogodna za slučajeve kada trebate provjeriti Docker slike izvan CI/CD sistema ili trebate imati sve instrukcije u obliku koji se može izvršiti direktno na hostu. Ovu opciju pokriva gotova shell skripta koja se može pokrenuti na čistoj virtuelnoj (ili čak stvarnoj) mašini. Skripta izvršava iste instrukcije kao gitlab-runner opisan gore.

Da bi se skripta uspješno pokrenula, Docker mora biti instaliran na sistemu i trenutni korisnik mora biti u docker grupi.

Samu skriptu možete pronaći ovdje: docker_sec_check.sh

Na početku datoteke, varijable određuju koju sliku treba skenirati i koji defekti kritičnosti će uzrokovati da uslužni program Trivy izađe sa navedenim kodom greške.

Tokom izvršavanja skripte, svi uslužni programi će biti preuzeti u direktorij docker_tools, rezultati njihovog rada su u imeniku docker_tools/json, a HTML sa izvještajem će biti u datoteci rezultati.html.

Primjer izlaza skripte

~/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 sa svim uslužnim programima

Kao treću alternativu, sastavio sam dva jednostavna Dockerfile-a za kreiranje slike sa sigurnosnim uslužnim programima. Jedan Dockerfile će pomoći u izgradnji skupa za skeniranje slike iz spremišta, drugi (Dockerfile_tar) će pomoći u izgradnji skupa za skeniranje tar datoteke sa slikom.

1. Uzmite odgovarajući Docker fajl i skripte iz spremišta https://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfile.
2. Pokrećemo ga na sklapanje:

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

3. Nakon što je montaža završena, kreiramo kontejner od slike. U isto vrijeme prosljeđujemo varijablu okruženja DOCKERIMAGE s imenom slike koja nas zanima i montiramo Dockerfile koji želimo analizirati sa našeg stroja u datoteku /Dockerfile (imajte na umu da je potrebna apsolutna putanja do ove 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

Rezulʹtaty

Pogledali smo samo jedan osnovni skup uslužnih programa za skeniranje Docker artefakata, koji, po mom mišljenju, vrlo efikasno pokriva pristojan dio zahtjeva za sigurnošću slike. Postoji i veliki broj plaćenih i besplatnih alata koji mogu obavljati iste provjere, crtati prekrasne izvještaje ili raditi isključivo u konzolnom modu, pokrivati ​​sisteme upravljanja kontejnerima, itd. Pregled ovih alata i načina na koji ih integrirati može se pojaviti malo kasnije .

Dobra stvar u vezi skupa alata opisanih u ovom članku je to što su svi otvorenog koda i možete eksperimentirati s njima i drugim sličnim alatima kako biste pronašli ono što odgovara vašim potrebama i infrastrukturi. Naravno, sve ranjivosti koje se pronađu treba proučiti za primenljivost u određenim uslovima, ali ovo je tema za budući veliki članak.

Nadam se da će vam ovaj vodič, skripte i uslužni programi pomoći i postati polazna tačka za stvaranje sigurnije infrastrukture u oblasti kontejnerizacije.

izvor: www.habr.com

Dodajte komentar