Hej Habr!
En la moderna realo, pro la kreskanta rolo de kontenerigo en evoluaj procezoj, la afero certigi la sekurecon de diversaj stadioj kaj estaĵoj asociitaj kun ujoj ne estas la malplej grava afero. Fari manajn kontrolojn estas tempopostula, do estus bona ideo fari almenaŭ la komencajn paŝojn por aŭtomatigi ĉi tiun procezon.
En ĉi tiu artikolo, mi dividos pretajn skriptojn por efektivigi plurajn sekurecajn ilojn de Docker kaj instrukciojn pri kiel disfaldi malgrandan demonstran standon por testi ĉi tiun procezon. Vi povas uzi la materialojn por eksperimenti pri kiel organizi la procezon de testado de la sekureco de bildoj kaj instrukcioj de Dockerfile. Estas klare, ke ĉies evolua kaj efektiviga infrastrukturo estas malsama, do sube mi provizos plurajn eblajn opciojn.
Sekureckontrolaj utilecoj
Estas granda nombro da malsamaj helpaj aplikoj kaj skriptoj, kiuj faras kontrolojn pri diversaj aspektoj de la Docker-infrastrukturo. Kelkaj el ili jam estis priskribitaj en la antaŭa artikolo (
Hadolinto
Sufiĉe simpla konzola ilo, kiu helpas, kiel unua aproksimado, taksi la ĝustecon kaj sekurecon de instrukcioj de Dockerfile (ekzemple, uzante nur rajtigitajn bildregistrojn aŭ uzante sudo).
Dockle
Konzola ilo, kiu funkcias kun bildo (aŭ kun konservita gudro-arkivo de bildo), kiu kontrolas la ĝustecon kaj sekurecon de aparta bildo kiel tia, analizante ĝiajn tavolojn kaj agordojn - kiuj uzantoj estas kreitaj, kiuj instrukcioj estas uzataj, kiuj volumoj estas muntitaj, la ĉeesto de malplena pasvorto, ktp. d. Ĝis nun la nombro da ĉekoj ne estas tre granda kaj baziĝas sur pluraj el niaj propraj ĉekoj kaj rekomendoj.
Trivy
Ĉi tiu utileco celas trovi du specojn de vundeblecoj - problemoj kun OS-konstruoj (subtenataj de Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) kaj problemoj kun dependecoj (Gemfile.lock, Pipfile.lock, composer.lock, package). -lock.json , yarn.lock, cargo.lock). Trivy povas skani ambaŭ bildon en la deponejo kaj loka bildo, kaj ankaŭ povas skani surbaze de la translokigita .tar dosiero kun la Docker-bildo.
Opcioj por efektivigi utilecojn
Por provi la priskribitajn aplikaĵojn en izolita medio, mi provizos instrukciojn por instali ĉiujn ilojn en iom simpligita procezo.
La ĉefa ideo estas pruvi kiel vi povas efektivigi aŭtomatan enhavkonfirmon de Dockerfiles kaj Docker-bildoj kreitaj dum disvolviĝo.
La kontrolo mem konsistas el la sekvaj paŝoj:
- Kontrolante la ĝustecon kaj sekurecon de Dockerfile-instrukcioj per linter-ilaĵo Hadolinto
- Kontrolante la ĝustecon kaj sekurecon de la finaj kaj mezaj bildoj uzante ilon Dockle
- Kontrolante la ĉeeston de publike konataj vundeblecoj (CVE) en la baza bildo kaj kelkaj dependecoj - uzante la utilecon Trivy
Poste en la artikolo mi donos tri eblojn por efektivigi ĉi tiujn paŝojn:
La unua estas agordante la CI/KD-dukton uzante GitLab kiel ekzemplon (kun priskribo de la procezo de levi provan petskribon).
La dua uzas ŝelan skripton.
La tria implicas konstrui Docker-bildon por skani Docker-bildojn.
Vi povas elekti la opcion, kiu plej konvenas al vi, translokigi ĝin al via infrastrukturo kaj adapti ĝin al viaj bezonoj.
Ĉiuj necesaj dosieroj kaj kromaj instrukcioj troviĝas ankaŭ en la deponejo:
Integriĝo en GitLab CI/CD
En la unua opcio, ni rigardos kiel vi povas efektivigi sekurecajn kontrolojn uzante la GitLab-deponejan sistemon kiel ekzemplon. Ĉi tie ni trarigardos la paŝojn kaj ekscios kiel instali testan medion kun GitLab de nulo, krei skanan procezon kaj lanĉi utilecojn por kontroli la testan Dockerfile kaj hazardan bildon - la JuiceShop-aplikaĵo.
Instalante GitLab
1. Instalu Docker:
sudo apt-get update && sudo apt-get install docker.io
2. Aldonu la nunan uzanton al la docker-grupo por ke vi povu labori kun docker sen uzi sudo:
sudo addgroup <username> docker
3. Trovu vian IP:
ip addr
4. Instalu kaj lanĉu GitLab en la ujo, anstataŭigante la IP-adreson en la gastiga nomo per via propra:
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
Ni atendas ĝis GitLab kompletigas ĉiujn necesajn instalajn procedurojn (vi povas monitori la procezon per la protokoldosiera eligo: docker logs -f gitlab).
5. Malfermu vian lokan IP en la retumilo kaj vidu paĝon, kiu petas vin ŝanĝi la pasvorton por la radika uzanto:
Agordu novan pasvorton kaj iru al GitLab.
6. Kreu novan projekton, ekzemple cicd-test kaj pravalorigu ĝin per la startdosiero LEGUMIN.md:
7. Nun ni devas instali GitLab Runner: agento, kiu funkcios ĉiujn necesajn operaciojn laŭpeto.
Elŝutu la lastan version (en ĉi tiu kazo, por Linukso 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. Faru ĝin efektivigebla:
sudo chmod +x /usr/local/bin/gitlab-runner
9. Aldonu OS-uzanto por Runner kaj lanĉu la servon:
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
Ĝi devus aspekti kiel ĉi tio:
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. Nun ni registras la Kurilon por ke ĝi povu interagi kun nia GitLab-instanco.
Por fari tion, malfermu la paĝon Agordoj-CI/CD (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) kaj sur la langeto Runners trovi la URL kaj Registrado-ĵetonon:
11. Registri Runner anstataŭigante la URL kaj Registrado-ĵetonon:
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"
Kiel rezulto, ni ricevas pretan funkciantan GitLab, en kiu ni devas aldoni instrukciojn por komenci niajn ilojn. En ĉi tiu demo ni ne havas la paŝojn por konstrui la aplikaĵon kaj kontenerigi ĝin, sed en reala medio ĉi tiuj antaŭus la skanajn paŝojn kaj generus bildojn kaj Dockerfile por analizo.
dukto agordo
1. Aldonu dosierojn al la deponejo miadockerfile.df (ĉi tio estas prova Dockerfile, kiun ni kontrolos) kaj la GitLab CI/CD-proceza agorda dosiero .gitlab-cicd.yml, kiu listigas instrukciojn por skaniloj (notu la punkton en la dosiernomo).
La agorda dosiero YAML enhavas instrukciojn por ruli tri ilojn (Hadolint, Dockle kaj Trivy), kiuj analizos la elektitan Dockerfile kaj la bildon specifitan en la variablo DOCKERFILE. Ĉiuj necesaj dosieroj povas esti prenitaj el la deponejo:
Eltiraĵo el miadockerfile.df (ĉi tio estas abstrakta dosiero kun aro de arbitraj instrukcioj nur por pruvi la funkciadon de la utileco). Rekta ligilo al la dosiero:
Enhavo de 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
La agordo YAML aspektas tiel (la dosiero mem troveblas per la rekta ligilo ĉi tie:
Enhavo de .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
Se necese, vi ankaŭ povas skani konservitajn bildojn en la formo de arkivo .tar (tamen vi devos ŝanĝi la enigajn parametrojn por la utilecoj en la YAML-dosiero)
NB: Trivy postulas instalita rpm и iri. Alie, ĝi generos erarojn dum skanado de bildoj bazitaj en RedHat kaj ricevado de ĝisdatigoj al la vundebla datumbazo.
2. Post aldoni dosierojn al la deponejo, laŭ la instrukcioj en nia agorda dosiero, GitLab aŭtomate komencos la procezon de konstruo kaj skanado. Sur la langeto CI/KD → Duktoj vi povas vidi la progreson de instrukcioj.
Kiel rezulto, ni havas kvar taskojn. Tri el ili traktas rekte pri skanado, kaj la lasta (Raporto) kolektas simplan raporton el disaj dosieroj kun skanaj rezultoj.
Defaŭlte, Trivy ĉesas funkcii se KRITIKAj vundeblecoj estas detektitaj en la bildo aŭ dependecoj. Samtempe, Hadolint ĉiam resendas Sukcesan kodon ĉar ĝi ĉiam rezultigas komentojn, kio kaŭzas la konstruon ĉesi.
Depende de viaj specifaj postuloj, vi povas agordi elirkodon por ke kiam ĉi tiuj iloj detektas problemojn de certa kritiko, ili ankaŭ ĉesigas la konstruprocezon. En nia kazo, la konstruo ĉesos nur se Trivy detektas vundeblecon kun la kritiko, kiun ni specifis en la variablo SHOWSTOPPER en .gitlab-ci.yml.
La rezulto de ĉiu utileco povas esti vidita en la protokolo de ĉiu skanada tasko, rekte en la json-dosieroj en la sekcio de artefaktoj, aŭ en simpla HTML-raporto (pli pri tio ĉi sube):
3. Por prezenti utilajn raportojn en iom pli homlegebla formo, malgranda Python-skripto estas uzata por konverti tri JSON-dosierojn en unu HTML-dosieron kun tabelo de difektoj.
Ĉi tiu skripto estas lanĉita per aparta Raporttasko, kaj ĝia fina artefakto estas HTML-dosiero kun raporto. La skriptofonto ankaŭ estas en la deponejo kaj povas esti adaptita laŭ viaj bezonoj, koloroj, ktp.
Ŝelo-skripto
La dua opcio taŭgas por kazoj, kiam vi bezonas kontroli Docker-bildojn ekster la CI/KD-sistemo aŭ vi devas havi ĉiujn instrukciojn en formo, kiu povas esti ekzekutita rekte sur la gastiganto. Ĉi tiu opcio estas kovrita de preta ŝela skripto, kiu povas esti rulita per pura virtuala (aŭ eĉ reala) maŝino. La skripto plenumas la samajn instrukciojn kiel la gitlab-runner priskribita supre.
Por ke la skripto rulu sukcese, Docker devas esti instalita en la sistemo kaj la nuna uzanto devas esti en la docker-grupo.
La skripto mem troveblas ĉi tie:
Komence de la dosiero, variabloj specifas, kiun bildon devas esti skanita kaj kiuj kritikecaj difektoj igos la Trivy-ilaĵon eliri kun la specifita erarkodo.
Dum skripto-ekzekuto, ĉiuj iloj estos elŝutitaj al la dosierujo docker_tools, la rezultoj de ilia laboro estas en la dosierujo docker_tools/json, kaj la HTML kun la raporto estos en la dosiero rezultoj.html.
Ekzempla skripto eligo
~/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-bildo kun ĉiuj utilecoj
Kiel tria alternativo, mi kompilis du simplajn Dockerfiles por krei bildon kun sekurecaj utilecoj. Unu Dockerfile helpos konstrui aron por skanado de bildo el deponejo, la dua (Dockerfile_tar) helpos konstrui aron por skanado de tar-dosiero kun bildo.
1. Prenu la respondan Docker-dosieron kaj skriptojn el la deponejo
2. Ni lanĉas ĝin por kunigo:
docker build -t dscan:image -f docker_security.df .
3. Post kiam la asembleo estas kompletigita, ni kreas ujon el la bildo. Samtempe, ni pasas la mediovariablon DOCKERIMAGE kun la nomo de la bildo pri kiu ni interesiĝas kaj muntas la Dockerfile, kiun ni volas analizi de nia maŝino al la dosiero. /Dockerfile (notu, ke la absoluta vojo al ĉi tiu dosiero estas postulata):
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
Результаты
Ni rigardis nur unu bazan aron de utilecoj por skanado de Docker-artefaktoj, kiu, laŭ mi, tre efike kovras decan parton de la bildaj sekurecpostuloj. Ekzistas ankaŭ granda nombro da pagitaj kaj senpagaj iloj, kiuj povas fari la samajn kontrolojn, desegni belajn raportojn aŭ labori nur en konzola reĝimo, kovri ujajn mastrumajn sistemojn, ktp. Superrigardo de ĉi tiuj iloj kaj kiel integri ilin povas aperi iom poste. .
La bona afero pri la aro de iloj priskribitaj en la artikolo estas, ke ili ĉiuj estas konstruitaj sur malferma fontkodo kaj vi povas eksperimenti kun ili kaj aliaj similaj iloj por trovi kio konvenas al viaj postuloj kaj infrastrukturaj funkcioj. Kompreneble, ĉiuj vundeblecoj, kiuj troviĝas, devas esti studitaj por aplikebleco en specifaj kondiĉoj, sed ĉi tio estas temo por estonta granda artikolo.
Mi esperas, ke ĉi tiu gvidilo, skriptoj kaj utilecoj helpos vin kaj fariĝos deirpunkto por krei pli sekuran infrastrukturon en la areo de kontenerigo.
fonto: www.habr.com