Hej Habr!
U današnjoj stvarnosti, zbog sve veće uloge kontejnerizacije u razvojnim procesima, pitanje osiguranja sigurnosti različitih faza i entiteta povezanih s kontejnerima nije na posljednjem mjestu. Ručno obavljanje provjera je naporan zadatak, stoga bi bilo lijepo poduzeti barem početne korake prema automatizaciji ovog procesa.
U ovom ću članku podijeliti gotove skripte za implementaciju nekoliko Docker sigurnosnih uslužnih programa i upute o tome kako postaviti mali demo stalak za testiranje ovog procesa. Materijale možete koristiti za eksperimentiranje s načinom organiziranja procesa testiranja sigurnosti Dockerfile slika i uputa. Jasno je da je razvojna i implementacijska infrastruktura različita za svakoga, stoga ću u nastavku dati nekoliko mogućih opcija.
Uslužni programi sigurnosne provjere
Postoji veliki broj različitih pomoćnih aplikacija i skripti koje vrše provjere različitih aspekata Docker infrastrukture. Neki od njih već su opisani u prethodnom članku (
Hadolint
Prilično jednostavan konzolni uslužni program koji pomaže prvo procijeniti ispravnost i sigurnost uputa Dockerfilea (na primjer, korištenje samo dopuštenih registara slika ili korištenje sudoa).
Dockle
Konzolni uslužni program koji radi na slici (ili na spremljenoj arhivi slike) koja provjerava ispravnost i sigurnost određene slike kao takve analizirajući njezine slojeve i konfiguraciju - koji su korisnici stvoreni, koje se upute koriste, koji su volumeni montirani , prisutnost prazne lozinke itd. e. Dok broj provjera nije jako velik i temelji se na nekoliko vlastitih provjera i preporuka
Trivy
Ovaj uslužni program ima za cilj pronalaženje dvije vrste ranjivosti - probleme s verzijom OS-a (podržani su Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) i probleme ovisnosti (Gemfile.lock, Pipfile.lock, composer.lock, package-lock .json, yarn.lock, Cargo.lock). Trivy može skenirati i sliku u repozitoriju i lokalnu sliku, a također skenirati na temelju prenesene .tar datoteke s Docker slikom.
Mogućnosti implementacije uslužnih programa
Kako bismo isprobali opisane aplikacije u izoliranim uvjetima, dat ću upute za instaliranje svih pomoćnih programa kao dio pojednostavljenog postupka.
Glavna ideja je pokazati kako možete implementirati automatsku provjeru sadržaja za Docker datoteke i Docker slike koje su stvorene tijekom razvoja.
Sama verifikacija se sastoji od sljedećih koraka:
- Provjera ispravnosti i sigurnosti uputa Dockerfilea pomoću uslužnog programa linter Hadolint
- Provjera ispravnosti i sigurnosti završne i međuslike - pomoćni program Dockle
- Provjera općepoznatih ranjivosti (CVE) u osnovnoj slici i brojnih ovisnosti - od strane uslužnog programa Trivy
Kasnije u članku dat ću tri opcije za provedbu ovih koraka:
Prvi je konfiguriranjem CI/CD cjevovoda na primjeru GitLaba (s opisom procesa podizanja testne instance).
Drugi je korištenje shell skripte.
Treći je izrada Docker slike za skeniranje Docker slika.
Možete odabrati opciju koja vam najviše odgovara, prenijeti je na svoju infrastrukturu i prilagoditi svojim potrebama.
Sve potrebne datoteke i dodatne upute također se nalaze u repozitoriju:
GitLab CI/CD integracija
U prvoj opciji pogledat ćemo kako se sigurnosne provjere mogu implementirati koristeći GitLab sustav repozitorija kao primjer. Ovdje ćemo proći kroz korake i vidjeti kako postaviti testno okruženje s GitLabom ispočetka, stvoriti proces skeniranja i pokrenuti uslužne programe za testiranje testne Dockerfile i nasumične slike - aplikacije JuiceShop.
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 svoj IP:
ip addr
4. Instalirajte i pokrenite GitLab u spremniku, zamjenjujući IP adresu u imenu 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 da GitLab dovrši sve potrebne instalacijske procedure (proces možete pratiti kroz izlaz log datoteke: docker logs -f gitlab).
5. Otvorite svoj lokalni IP u pregledniku i pogledajte stranicu koja nudi promjenu lozinke za root korisnika:
Postavite novu lozinku i idite na GitLab.
6. Napravite novi projekt, na primjer cicd-test i inicijalizirajte ga s početnom datotekom PROČITAJ ME.md:
7. Sada moramo instalirati GitLab Runner: agent koji će pokrenuti sve potrebne operacije na zahtjev.
Preuzmite najnoviju verziju (u ovom slučaju pod 64-bitnim Linuxom):
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 registriramo Runner tako da može komunicirati s 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 registracijski token:
11. Registrirajte trkača zamjenom URL-a i tokena za registraciju:
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, dobivamo gotov radni GitLab, u koji moramo dodati upute za pokretanje naših uslužnih programa. U ovoj demonstraciji nemamo korake izrade aplikacije i kontejnerizacije, ali u stvarnom okruženju oni će prethoditi koracima skeniranja i generirati slike i Dockerfile za analizu.
konfiguracija cjevovoda
1. Dodajte datoteke u repozitorij mojadockerfile.df (ovo je testna Docker datoteka koju ćemo testirati) i konfiguracijska datoteka GitLab CI/CD procesa .gitlab-cicd.yml, koji navodi upute za skenere (obratite pažnju na točku u nazivu datoteke).
Konfiguracijska datoteka .yaml sadrži upute za pokretanje tri pomoćna programa (Hadolint, Dockle i Trivy) koji će analizirati odabranu Dockerfile i sliku navedenu u varijabli DOCKERFILE. Sve potrebne datoteke mogu se preuzeti iz repozitorija:
Izvadak iz mojadockerfile.df (ovo je apstraktna datoteka sa skupom proizvoljnih uputa samo da se pokaže kako uslužni program radi). Izravna poveznica na datoteku:
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 izgleda ovako (sama datoteka se može preuzeti s izravnog linka ovdje:
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, također možete skenirati spremljene slike kao .tar arhivu (međutim, morat ćete promijeniti ulazne parametre za pomoćne programe u YAML datoteci)
Napomena: Trivy zahtijeva instaliranje min и git. Inače će generirati pogreške prilikom skeniranja slika temeljenih na RedHatu i dobivanja ažuriranja baze podataka ranjivosti.
2. Nakon dodavanja datoteka u repozitorij, prema uputama u našoj konfiguracijskoj datoteci, GitLab će automatski pokrenuti proces izgradnje i skeniranja. Na kartici CI / CD → Cjevovodi možete vidjeti napredak uputa.
Kao rezultat toga, imamo četiri zadatka. Tri su izravno uključena u skeniranje, a posljednji (Izvješće) prikuplja jednostavno izvješće iz razbacanih datoteka s rezultatima skeniranja.
Prema zadanim postavkama, Trivy zaustavlja svoje izvršenje ako se na slici ili ovisnostima pronađu KRITIČNE ranjivosti. U isto vrijeme, Hadolint uvijek vraća Success u izvršnom kodu, budući da njegovo izvršenje uvijek ima primjedbi, što uzrokuje zaustavljanje izgradnje.
Ovisno o vašim specifičnim zahtjevima, možete konfigurirati izlazni kod tako da ovi pomoćni programi također zaustave proces izgradnje kada se otkriju problemi određene kritičnosti. U našem slučaju, izgradnja će se zaustaviti samo ako Trivy otkrije ranjivost s ozbiljnošću koju smo naveli u varijabli SHOWSTOPPER u .gitlab-ci.yml.
Rezultat rada svakog uslužnog programa može se vidjeti u zapisniku svakog zadatka skeniranja, izravno u json datotekama u odjeljku s artefaktima ili u jednostavnom HTML izvješću (više o tome u nastavku):
3. Za predstavljanje izvješća o komunalnim uslugama u malo čitljivijem obliku, koristi se mala Python skripta za pretvaranje tri json datoteke u jednu HTML datoteku s tablicom nedostataka.
Ovu skriptu pokreće zaseban zadatak izvješća, a njezin je konačni artefakt HTML datoteka s izvješćem. Izvor skripte je također u repozitoriju i može se prilagoditi vašim potrebama, bojama itd.
Shell skripta
Druga je opcija prikladna za slučajeve kada trebate provjeriti Docker slike koje nisu unutar CI/CD sustava ili trebate imati sve upute u obliku koji se može izvršiti izravno na hostu. Ovu opciju pokriva gotova skripta ljuske koja se može pokrenuti na čistom virtualnom (ili čak stvarnom) stroju. Skripta slijedi iste upute kao gornji gitlab-runner.
Da bi skripta uspješno radila, Docker mora biti instaliran na sustavu i trenutni korisnik mora biti u docker grupi.
Samu skriptu možete pronaći ovdje:
Na početku datoteke, varijable određuju koju sliku treba skenirati i koja će ozbiljnost nedostataka uzrokovati izlazak uslužnog programa Trivy s navedenim kodom pogreške.
Tijekom izvođenja skripte, svi pomoćni programi bit će preuzeti u direktorij docker_tools, rezultati njihovog rada - u imeniku docker_tools/json, a HTML s izvješćem bit će 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 pomoćnim programima
Kao treću alternativu, kompajlirao sam dvije jednostavne Docker datoteke za stvaranje slike sa sigurnosnim uslužnim programima. Jedan Dockerfile pomoći će u izradi skupa za skeniranje slike iz repozitorija, drugi (Dockerfile_tar) će izgraditi skup za skeniranje tar datoteke sa slikom.
1. Uzimamo odgovarajuću Docker datoteku i skripte iz repozitorija
2. Pokrenite ga za sastavljanje:
docker build -t dscan:image -f docker_security.df .
3. Nakon dovršetka izgradnje, stvorite spremnik iz slike. U isto vrijeme prosljeđujemo varijablu okruženja DOCKERIMAGE s nazivom slike koja nas zanima i montiramo Dockerfile koji želimo analizirati s našeg stroja na 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
Nalazi
Pokrili smo samo jedan osnovni skup Docker pomoćnih programa za skeniranje artefakata, za koje mislim da prilično učinkovito pokriva dobar dio sigurnosnih zahtjeva slike. Postoje mnogi drugi plaćeni i besplatni alati koji mogu obavljati iste provjere, crtati prekrasna izvješća ili raditi isključivo u konzolnom načinu rada, pokrivati sustave upravljanja kontejnerima, itd. Pregled ovih alata i kako ih integrirati može se pojaviti nešto kasnije.
Pozitivna strana skupa alata opisanih u članku jest to što su svi izgrađeni na otvorenom kodu i možete eksperimentirati s njima i drugim sličnim alatima kako biste pronašli ono što točno odgovara vašim zahtjevima i značajkama infrastrukture. Naravno, sve ranjivosti koje se pronađu treba proučiti za primjenjivost u određenim uvjetima, ali to je tema za budući veliki članak.
Nadam se da će vam ove upute, skripte i uslužni programi pomoći i postati polazna točka za stvaranje sigurnije infrastrukture u području kontejnerizacije.
Izvor: www.habr.com