
Helló, Habr!
A modern reality, due to the increasing role of containerization in development processes, raises concerns about securing various stages and entities related to containers. Manual checks are labor-intensive, so it would be beneficial to take at least initial steps toward automating this process.
In this article, I will share ready-made scripts for implementing several security utilities for Docker and instructions on how to deploy a small demo stand to test this process. The materials can be used to experiment with organizing the security testing process for Docker image and Dockerfile instructions. It is clear that development and deployment infrastructures vary, so below I will provide some possible options.
Security Check Utilities
There are many different auxiliary applications and scripts that perform checks on various aspects of Docker infrastructure. Some of them were described in the previous article (), and in this material, I would like to focus on three of them that cover the main security requirements for Docker images built during development. Additionally, I will show an example of how to combine these three utilities into one pipeline for conducting security checks.
Hadolint
A fairly simple console utility that helps to roughly assess the correctness and security of Dockerfile instructions (for example, using only allowed image registries or using sudo).

Dockle
A console utility that works with an image (or a saved tar archive of the image), which checks the correctness and security of a specific image as such, analyzing its layers and configuration – what users are created, what instructions are used, what volumes are attached, the presence of an empty password, etc. Currently, the number of checks is not very large and is based on a few custom checks and recommendations. for Docker.

Trivy
Ez a segédprogram a kétféle sebezhetőség, az operációs rendszerek összeállítási problémáinak (támogatott Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) és a függőségek problémáinak felderítésére összpontosít (Gemfile.lock, Pipfile.lock, composer.lock, package-lock.json, yarn.lock, Cargo.lock). A Trivy képes szkennelni a tárolóban lévő képet, valamint a helyi képet is, illetve szkennelést végezni a megadott .tar fájl alapján, amely egy Docker-képet tartalmaz.

A segédprogramok bevezetési lehetőségei
Ahhoz, hogy elszigetelt környezetben kipróbálhassuk a leírt alkalmazásokat, alább bemutatok egy egyszerűsített folyamatot az összes segédprogram telepítésére vonatkozóan.
A fő ötlet az, hogy bemutassuk, hogyan lehet automatikus ellenőrzési folyamatot bevezetni a Dockerfile és a fejlesztési folyamat során létrehozott Docker-képek tartalmának ellenőrzésére.
Az ellenőrzés a következő lépésekből áll:
- A Dockerfile utasításainak helyessége és biztonsága — linter segédprogram segítségével Hadolint
- A végső és közbenső képek helyessége és biztonsága — segédprogrammal Dockle
- Ismert sebezhetőségek (CVE) ellenőrzése az alapképen és egyes függőségeken — segédprogrammal Trivy
A cikk további részében három lehetőséget mutatok be ezen lépések bevezetésére:
Az első — a CI/CD pipeline GitLab példáján keresztül (a tesztpélda példányának létrehozásának folyamatával).
A második — shell-skripttel.
A harmadik — Docker-kép létrehozásával a Docker-képek szkennelésére.
Ön választhatja azt a lehetőséget, ami a legjobban megfelel önnek, átviheti a saját infrastruktúrájára és alkalmazhatja az igényei szerint.
Minden szükséges fájl és további útmutatók is megtalálhatóak a tárolóban:
Integráció a GitLab CI/CD-be
Az első lehetőségben azt vizsgáljuk meg, hogyan lehet biztonsági ellenőrzéseket bevezetni a GitLab tároló rendszerének példáján. Itt lépésről lépésre végigmegyünk, és részletezzük, hogyan lehet nulláról telepíteni a GitLab tesztkörnyezetet, elkészíteni a szkennelési folyamatot, és végrehajtani a segédprogramok indítását a teszt Dockerfile és egy véletlenszerű kép — a JuiceShop alkalmazás ellenőrzésére.
GitLab telepítése
1. Telepítjük a Dockert:
sudo apt-get update && sudo apt-get install docker.io2. Hozzáadjuk a jelenlegi felhasználót a docker csoporthoz, hogy ne kelljen sudo-val dolgoznia a dockeren:
sudo addgroup docker3. Megkeressük az IP címünket:
ip addr4. Telepítjük és elindítjuk a GitLab-ot egy konténerben, a hostname-ben lévő IP-címet a sajátunkra cserélve:
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:latestVárjunk, amíg a GitLab elvégzi a szükséges telepítési lépéseket (a folyamatot nyomon követhetjük a log fájl kimenetén: docker logs -f gitlab).
5. Nyissuk meg a böngészőben a helyi IP címünket, és lássuk a jelszó megváltoztatására vonatkozó ajánlást a root felhasználónak:

Adjunk meg egy új jelszót, és lépjünk be a GitLab-ba.
6. Hozzunk létre egy új projektet, például cicd-teszt, és inicializáljuk egy kezdő fájllal. README.md:

7. Most telepítenünk kell a GitLab Runner-t: egy ügynököt, amely kérésre végrehajt minden szükséges műveletet.
Töltsük le a legfrissebb verziót (jelen esetben Linux 64-bit-re):
sudo curl -L --output \/usr\/local\/bin\/gitlab-runner https:\/\/gitlab-runner-downloads.s3.amazonaws.com\/latest\/binaries\/gitlab-runner-linux-amd648. Tegyük végrehajthatóvá:
sudo chmod +x \/usr\/local\/bin\/gitlab-runner9. Adjuk hozzá az OS felhasználót a Runner-hez, és indítsuk el a szolgáltatást:
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 startEnnek körülbelül így kell kinéznie:
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. Most regisztráljuk a Runert, hogy tudjon kommunikálni a GitLab példányunkkal.
Ehhez nyissuk meg a Beállítások-CI\/CD oldalt (http:\/\/OUR_ IP_ADDRESS\/root\/cicd-teszt\/-\/settings\/ci_cd) és a Runners fülön találjuk meg az URL-t és a Regisztrációs tokent:

11. Regisztráljuk a Runert, helyettesítve az URL-t és a Regisztrációs tokent:
sudo gitlab-runner register
--non-interactive
--url "http:\/\/\/"
--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"Ennek eredményeként egy működő GitLab-ot kapunk, amelyhez hozzá kell adnunk az utasításokat az eszközeink indításához. Ebben a bemutató esetben nincsenek az alkalmazás építési és konténerizálási lépései, de egy valódi környezetben ezek a lépések megelőzik a vizsgálati lépéseket, és képeket és Dockerfile-t alkotnak az elemzéshez.
Pipeline konfiguráció
1. Adjunk hozzá fájlokat a repóhoz mydockerfile.df (ez egy teszt Dockerfile, amelyet ellenőrizni fogunk) és a GitLab CI\/CD folyamat konfigurációs fájlja .gitlab-cicd.yml, amely felsorolja a szkennelő utasításokat (figyeljünk a pontra a fájl nevében).
A YAML configuration file contains instructions for running three utilities (Hadolint, Dockle, and Trivy) that will analyze the selected Dockerfile and the image specified in the DOCKERFILE variable. All necessary files can be taken from the repository:
Kivonat a mydockerfile.df (this is an abstract file with a set of arbitrary instructions just to demonstrate the utility's operation). Direct link to the file:
Content of 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 "
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 rootThe YAML configuration looks like this (the file itself can be accessed via the direct link here: ):
Content of .gitlab-ci.yml
változók:
DOCKER_HOST: "tcp://docker:2375/"
DOCKERFILE: "mydockerfile.df" # a Dockerfile neve, amelyet elemezni kell
DOCKERIMAGE: "bkimminich/juice-shop" # a Docker kép neve, amelyet elemezni kell
# DOCKERIMAGE: "knqyf263/cve-2018-11235" # teszt Docker kép, több KRITIKUS CVE-vel
SHOWSTOPPER_PRIORITY: "KRITIKUS" # milyen szintű kritikus esemény esetén sikertelen a Trivy feladat
TRIVYCACHE: "$CI_PROJECT_DIR/.cache" # hová cache-eljük a Trivy sebezhetőségi adatbázisát a gyorsabb újrafelhasználás érdekében
ARTIFACT_FOLDER: "$CI_PROJECT_DIR"
szolgáltatások:
- docker:dind # a Docker képek létrehozásához a Futó környezetben
stádiumok:
- scan
- report
- publish
HadoLint:
# Alap lint elemzés a Dockerfile utasításainak
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 mindig 0 kilépési kóddal lép ki
- ./hadolint-Linux-x86_64 -f json $DOCKERFILE > $ARTIFACT_FOLDER/hadolint_results.json || exit 0
artefaktumok:
when: always # artefaktumok visszaadása még hiba esetén
pathways:
- $ARTIFACT_FOLDER/hadolint_results.json
Dockle:
# A Docker képekkel kapcsolatos legjobb gyakorlatok elemzése (felhasználói jogosultságok, utasítások követése a kép létrehozásakor stb.)
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
artefaktumok:
when: always # artefaktumok visszaadása még hiba esetén
pathways:
- $ARTIFACT_FOLDER/dockle_results.json
Trivy:
# A Docker kép és csomag függőségek elemzése különböző CVE bázisokkal szemben
stage: scan
image: docker:git
script:
# a legfrissebb Trivy beszerzése
- 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
# az összes sebezhetőség megjelenítése a build megszakítása nélkül
- ./trivy -d --cache-dir $TRIVYCACHE -f json -o $ARTIFACT_FOLDER/trivy_results.json --exit-code 0 $DOCKERIMAGE
# sebezhetőségi információ írása az stdout-ra emberi olvasásra alkalmas formátumban (a tiszta json olvasása nem vicces, ugye?). Ezt eltávolíthatja, ha erre nincs szüksége.
- ./trivy -d --cache-dir $TRIVYCACHE --exit-code 0 $DOCKERIMAGE
# a build meghibásítása, ha a SHOWSTOPPER prioritást találják
- ./trivy -d --cache-dir $TRIVYCACHE --exit-code 1 --severity $SHOWSTOPPER_PRIORITY --quiet $DOCKERIMAGE
artefaktumok:
when: always # artefaktumok visszaadása még hiba esetén
pathways:
- $ARTIFACT_FOLDER/trivy_results.json
cache:
pathways:
- .cache
Jelentés:
# az eszközök kimenetének egyesítése egy HTML fájlba
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
artefaktumok:
pathways:
- results.htmlSzükség esetén a tárolt képeket .tar-archívum formájában is lehet vizsgálni (azonban a bemeneti paramétereket a YAML fájlban módosítani kell a segédprogramokhoz).
Megjegyzés: A Trivy a működéséhez telepített rpm és git. Ellenkező esetben hibákat fog kiadni a RedHat-alapú képek vizsgálata során, és a sebezhetőségi adatbázis frissítésekor.
2. Miután a fájlokat hozzáadtuk a tárolóhoz, a konfigurációs fájlunk utasításainak megfelelően a GitLab automatikusan elindítja a build és vizsgálati folyamatot. A CI/CD → Pipelines fül alatt nyomon követhetjük az utasítások végrehajtását.
Eredményül négy feladatot kaptunk. Három közvetlenül a vizsgálattal foglalkozik, az utolsó (Jelentés) pedig egy egyszerű jelentést készít a szórványos vizsgálati eredményekből.

Alapértelmezés szerint a Trivy leállítja a működését, ha KRITIKUS sebezhetőségeket talál a képen vagy a függőségeken. Ezzel szemben a Hadolint mindig sikerkódot ad vissza, mivel a végrehajtás során mindig vannak megjegyzések, ami a build leállításához vezet.
A konkrét követelmények függvényében konfigurálható a kilépési kód, így ezek a segédprogramok bizonyos kritikus problémák észlelésekor a build folyamatát is leállítják. A mi esetünkben a build csak akkor áll le, ha a Trivy olyan sebezhetőséget talál, amelynek kritikus szintjét a SHOWSTOPPER változóban megadtuk. .gitlab-ci.yml.

A segédprogramok működésének eredménye a minden vizsgálati feladat naplójában, közvetlenül a json-fájlokban, az artefaktumok részben, vagy egy egyszerű HTML-jelentésben tekinthető meg (erről később):

3. A segédprogramok jelentéseinek kicsit emberibb olvashatóságú formába való átkonvertálásához egy kis Python szkriptet használunk, amely három json-fájlt konvertál egy HTML-fájllá, amely táblázatban mutatja a hibákat.
Ezt a szkriptet egy külön Report feladat indítja el, és a végső artefaktuma egy HTML-jelentés. A szkript forráskódja is megtalálható a tárolóban, és igény szerint módosítható, színek stb. szerint.

Shell-szkript
A második lehetőség azokban az esetekben megfelelő, amikor a Docker képeit nem a CI/CD rendszer keretein belül kell ellenőrizni, vagy ha minden utasítást közvetlenül a hoszton futtatható formában szükséges megkapni. Ezt a lehetőséget egy kész shell-skripttel lehet megvalósítani, amelyet egy tiszta virtuális (vagy akár valódi) gépen futtathatunk. A skript ugyanis ugyanazokat az utasításokat hajtja végre, mint a fent említett gitlab-runner.
A skript sikeres működéséhez a rendszerben telepítve kell lennie a Dockernak, és a jelenlegi felhasználónak a docker csoport tagjának kell lennie.
A skripthez itt juthat el:
A fájl elején változókban van definiálva, hogy melyik képet kell szkennelni, és hogy melyik kritikus szintű hibák esetén lép ki a Trivy eszköz az adott hibaüzenettel.
A skript végrehajtása során minden segédeszközt a következő könyvtárba tölt le: docker_tools, a működésük eredményei pedig a könyvtárba: docker_tools/json, a jelentéssel ellátott HTML pedig ebben a fájlban található: results.html.
A skript kimenetének példája:
~/docker_cicd$ ./docker_sec_check.sh
[+] Környezeti változók beállítása
[+] Szükséges csomagok telepítése
[+] Szükséges könyvtárak előkészítése
[+] Minta Dockerfile beszerzése
2020-10-20 10:40:00 (45.3 MB/s) - 'Dockerfile' mentve [8071/8071]
[+] Kép letöltése a szkenneléshez
latest: Letöltés a bkimminich/juice-shop-ból
[+] Hadolint futtatása
...
Dockerfile:205 DL3015 Kerülje el a további csomagokat az `--no-install-recommends` megadásával
Dockerfile:248 DL3002 Az utolsó felhasználónak nem szabad rootnak lennie
...
[+] Dockle futtatása
...
WARN - DKL-DI-0006: Kerülje a legújabb címkét
* Kerülje a 'latest' címkét
INFO - CIS-DI-0005: Engedélyezze a tartalombizalmat a Dockerhez
* export DOCKER_CONTENT_TRUST=1 a docker pull/build előtt
...
[+] Trivy futtatása
juice-shop/frontend/package-lock.json
=====================================
Összesen: 3 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 2, CRITICAL: 0)
+---------------------+------------------+----------+---------+-------------------------+
| KÖNYVTÁR | SEBÉSZSÉGI AZONOSÍTÓ | SÚLYOSSÁG | VERSZIÓ | CÍM |
+---------------------+------------------+----------+---------+-------------------------+
| object-path | CVE-2020-15256 | MAGAS | 0.11.4 | Prototype pollution in |
| | | | | object-path |
+---------------------+------------------+ +---------+-------------------------+
| tree-kill | CVE-2019-15599 | | 1.2.2 | Kódinjekció |
+---------------------+------------------+----------+---------+-------------------------+
| webpack-subresource | CVE-2020-15262 | ALACSONY | 1.4.1 | Védtelen dinamikusan |
| | | | | betöltött darabok |
+---------------------+------------------+----------+---------+-------------------------+
juice-shop/package-lock.json
============================
Összesen: 20 (UNKNOWN: 0, LOW: 1, MEDIUM: 6, HIGH: 8, CRITICAL: 5)
...
juice-shop/package-lock.json
============================
Összesen: 5 (CRITICAL: 5)
...
[+] Maradványok eltávolítása
[+] A kimenet szépítése
[+] JSON eredmények átkonvertálása
[+] Eredmények írása HTML-be
[+] Zökkenőmentes kilépés ============================================================
[+] Minden kész. A generált HTML jelentést a results.html fájlban találja.Docker-kép minden eszközzel
Harmadik alternatívaként két egyszerű Dockerfile-t állítottam össze, melyek biztonsági eszközökkel látják el a képet. Az egyik Dockerfile segít összerakni a képkénti szkenneléshez szükséges készletet a tárolóból, a másik (Dockerfile_tar) pedig egy tar fájlból származó kép szkenneléséhez.
1. Készítsük el a megfelelő Docker fájlt és a szkripteket a tárolóból .
2. Futtassuk a build folyamatot:
docker build -t dscan:image -f docker_security.df .
3. A build befejezése után hozzunk létre egy konténert a képből. Ezen belül adjuk meg a DOCKERIMAGE környezeti változót, amely a minket érintő kép nevét tartalmazza, és csatoljuk a Dockerfile-t, amit elemezni szeretnénk, a gépünkről a fájlra. /Dockerfile (vegye figyelembe, hogy az abszolút útvonalra van szükség erre a fájlra):
docker run --rm -v $(pwd)/results:/results -v $(pwd)/docker_security.df:/Dockerfile -e DOCKERIMAGE="bkimminich/juce-shop" dscan:image
[+] Környezeti változók beállítása
[+] Hadolint futtatása
/Dockerfile:3 DL3006 Mindig kifejezetten címkézze az image verzióját
[+] Dockle futtatása
FIGYELMEZTETÉS - DKL-DI-0006: Kerülje a latest címkét
* Kerülje a 'latest' címkét
INFO - CIS-DI-0005: Engedélyezze a tartalom megbízhatóságát a Dockernél
* export DOCKER_CONTENT_TRUST=1 a docker pull/build előtt
INFO - CIS-DI-0006: Adjon HEALTHCHECK utasítást a konténerképhez
* nem található HEALTHCHECK utasítás
INFO - DKL-LI-0003: Csak a szükséges fájlokat helyezze el
* felesleges fájl: juice-shop/node_modules/sqlite3/Dockerfile
* felesleges fájl: juice-shop/node_modules/sqlite3/tools/docker/architecture/linux-arm64/Dockerfile
* felesleges fájl: juice-shop/node_modules/sqlite3/tools/docker/architecture/linux-arm/Dockerfile
[+] Trivy futtatása
...
juice-shop/package-lock.json
============================
Összesen: 20 (ISMERETLEN: 0, ALACSONY: 1, KÖZEPES: 6, MAGAS: 8, KRITIKUS: 5)
...
[+] A kimeneti megjelenés szépítése
[+] A fő modul indítása ============================================================
[+] JSON eredmények átkonvertálása
[+] Eredmények HTML írása
[+] Tisztított kilépés ============================================================
[+] Minden kész. Az eredményül kapott HTML jelentést a results.html fájlban találja.Eredmények
Csak egy alapvető munkaeszközkészletet vizsgáltunk meg a Docker artefaktumainak szkennelésére, amely véleményem szerint hatékonyan lefedi a képek biztonsági követelményeinek jelentős részét. Számos más ingyenes és fizetős eszköz is létezik, amelyek ugyanazokat a vizsgálatokat elvégezhetik, szép jelentéseket készíthetnek vagy tisztán a konzolos módba működhetnek, beleértve a konténerkezelő rendszereket is. Ezeknek az eszközöknek és az integrációs módszereiknek a bemutatása később talán megjelenik.
A cikkben leírt eszközkészlet pozitívuma, hogy mindnyájan nyílt forráskódúak, ezért kísérletezhet velük és más hasonló eszközökkel, hogy megtalálja az igényeihez és infrastruktúrájának sajátosságaihoz legjobban illeszkedőt. Mindenképpen az összes található sebezhetőséget a konkrét körülmények között kell vizsgálni, de ez egy jövőbeni nagyobb cikk témája lesz.
Remélem, hogy ez az útmutató, a szkriptek és az eszközök segítenek Önnek, és kiindulási pontként szolgálnak egy biztonságosabb infrastruktúra létrehozásához a konténerizálás területén.
Forrás: habr.com
