Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy
Hei Habr!

I moderne virkelighet, på grunn av containeriseringens økende rolle i utviklingsprosesser, er ikke spørsmålet om å sikre sikkerheten til ulike stadier og enheter knyttet til containere det minst viktige spørsmålet. Å utføre manuelle kontroller er tidkrevende, så det vil være en god idé å ta i det minste de første trinnene for å automatisere denne prosessen.

I denne artikkelen vil jeg dele ferdige skript for implementering av flere Docker-sikkerhetsverktøy og instruksjoner om hvordan du distribuerer et lite demo-stativ for å teste denne prosessen. Du kan bruke materialet til å eksperimentere med hvordan du organiserer prosessen med å teste sikkerheten til Dockerfile-bilder og instruksjoner. Det er klart at alles utviklings- og implementeringsinfrastruktur er forskjellig, så nedenfor vil jeg gi flere mulige alternativer.

Verktøy for sikkerhetssjekk

Det finnes et stort antall forskjellige hjelpeapplikasjoner og skript som utfører kontroller på ulike aspekter av Docker-infrastrukturen. Noen av dem er allerede beskrevet i forrige artikkel (https://habr.com/ru/company/swordfish_security/blog/518758/#docker-security), og i dette materialet vil jeg fokusere på tre av dem, som dekker hoveddelen av sikkerhetskravene for Docker-bilder bygget under utviklingsprosessen. I tillegg vil jeg også vise et eksempel på hvordan disse tre verktøyene kan kobles til én rørledning for å utføre sikkerhetskontroller.

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

Et ganske enkelt konsollverktøy som hjelper, som en første tilnærming, å evaluere riktigheten og sikkerheten til Dockerfile-instruksjoner (for eksempel ved å bruke bare autoriserte bilderegistre eller bruke sudo).

Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

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

Et konsollverktøy som fungerer med et bilde (eller med et lagret tar-arkiv av et bilde), som sjekker riktigheten og sikkerheten til et bestemt bilde som sådan, analyserer dets lag og konfigurasjon - hvilke brukere som er opprettet, hvilke instruksjoner som brukes, hvilke volumer er montert, tilstedeværelsen av et tomt passord osv. d. Så langt er antallet kontroller ikke veldig stort og er basert på flere av våre egne kontroller og anbefalinger CIS (Center for Internet Security) Benchmark for Docker.
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

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

Dette verktøyet er rettet mot å finne to typer sårbarheter - problemer med OS-bygg (støttet av Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) og problemer med avhengigheter (Gemfile.lock, Pipfile.lock, composer.lock, pakke -lock.json , yarn.lock, cargo.lock). Trivy kan skanne både et bilde i depotet og et lokalt bilde, og kan også skanne basert på den overførte .tar-filen med Docker-bildet.

Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

Alternativer for implementering av verktøy

For å prøve de beskrevne applikasjonene i et isolert miljø, vil jeg gi instruksjoner for å installere alle verktøyene i en noe forenklet prosess.

Hovedideen er å demonstrere hvordan du kan implementere automatisk innholdsverifisering av Dockerfiler og Docker-bilder som lages under utvikling.

Selve sjekken består av følgende trinn:

  1. Kontrollere riktigheten og sikkerheten til Dockerfile-instruksjonene ved hjelp av et linter-verktøy Hadolint
  2. Kontrollere riktigheten og sikkerheten til de endelige og mellomliggende bildene ved hjelp av et verktøy Dockle
  3. Sjekker for tilstedeværelsen av offentlig kjente sårbarheter (CVE) i basisbildet og en rekke avhengigheter - ved hjelp av verktøyet Trivy

Senere i artikkelen vil jeg gi tre alternativer for å implementere disse trinnene:
Den første er ved å konfigurere CI/CD-pipelinen ved å bruke GitLab som et eksempel (med en beskrivelse av prosessen med å heve en testinstans).
Den andre bruker et shell-skript.
Den tredje innebærer å bygge et Docker-bilde for å skanne Docker-bilder.
Du kan velge det alternativet som passer deg best, overføre det til din infrastruktur og tilpasse det til dine behov.

Alle nødvendige filer og tilleggsinstruksjoner er også plassert i depotet: https://github.com/Swordfish-Security/docker_cicd

Integrasjon i GitLab CI/CD

I det første alternativet vil vi se på hvordan du kan implementere sikkerhetssjekker ved å bruke GitLab-depotsystemet som eksempel. Her vil vi gå gjennom trinnene og finne ut hvordan du installerer et testmiljø med GitLab fra bunnen av, oppretter en skanneprosess og starter verktøy for å sjekke testen Dockerfile og et tilfeldig bilde - JuiceShop-applikasjonen.

Installerer GitLab
1. Installer Docker:

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

2. Legg til gjeldende bruker i docker-gruppen slik at du kan jobbe med docker uten å bruke sudo:

sudo addgroup <username> docker

3. Finn din IP:

ip addr

4. Installer og start GitLab i beholderen, og bytt ut IP-adressen i vertsnavnet med ditt eget:

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

Vi venter til GitLab fullfører alle nødvendige installasjonsprosedyrer (du kan overvåke prosessen gjennom loggfilutgangen: docker logs -f gitlab).

5. Åpne din lokale IP i nettleseren og se en side som ber deg endre passordet for root-brukeren:
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy
Sett et nytt passord og gå til GitLab.

6. Opprett et nytt prosjekt, for eksempel cicd-test og initialiser det med startfilen README.md:
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy
7. Nå må vi installere GitLab Runner: en agent som vil kjøre alle nødvendige operasjoner på forespørsel.
Last ned den nyeste versjonen (i dette tilfellet for 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. Gjør den kjørbar:

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

9. Legg til en OS-bruker for Runner og start tjenesten:

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

Det skal se omtrent slik ut:

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. Nå registrerer vi Runner slik at den kan samhandle med GitLab-instansen vår.
For å gjøre dette, åpne Settings-CI/CD-siden (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) og på Runners-fanen finner du URL og registreringstoken:
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy
11. Registrer Runner ved å erstatte URL og registreringstoken:

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"

Som et resultat får vi et ferdig fungerende GitLab, der vi må legge til instruksjoner for å starte verktøyene våre. I denne demoen har vi ikke trinnene for å bygge applikasjonen og beholde den, men i et virkelig miljø vil disse gå foran skannetrinnene og generere bilder og en Dockerfile for analyse.

rørledningskonfigurasjon

1. Legg til filer i depotet mydockerfile.df (dette er en test Docker-fil som vi vil sjekke) og GitLab CI/CD-prosesskonfigurasjonsfilen .gitlab-cicd.yml, som viser instruksjoner for skannere (merk prikken i filnavnet).

YAML-konfigurasjonsfilen inneholder instruksjoner for å kjøre tre verktøy (Hadolint, Dockle og Trivy) som vil analysere den valgte Dockerfilen og bildet spesifisert i DOCKERFILE-variabelen. Alle nødvendige filer kan hentes fra depotet: https://github.com/Swordfish-Security/docker_cicd/

Utdrag fra mydockerfile.df (dette er en abstrakt fil med et sett med vilkårlige instruksjoner kun for å demonstrere driften av verktøyet). Direkte lenke til filen: mydockerfile.df

Innhold i 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

Konfigurasjonen YAML ser slik ut (selve filen finner du via direktelenken her: .gitlab-ci.yml):

Innhold i .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

Om nødvendig kan du også skanne lagrede bilder i form av et .tar-arkiv (du må imidlertid endre inngangsparametrene for verktøyene i YAML-filen)

NB: Trivy krever installert rpm и git. Ellers vil det generere feil ved skanning av RedHat-baserte bilder og mottak av oppdateringer til sårbarhetsdatabasen.

2. Etter å ha lagt til filer i depotet, i henhold til instruksjonene i konfigurasjonsfilen vår, vil GitLab automatisk starte bygge- og skanneprosessen. På fanen CI/CD → Pipelines kan du se fremdriften til instruksjonene.

Som et resultat har vi fire oppgaver. Tre av dem omhandler direkte skanning, og den siste (Rapport) samler en enkel rapport fra spredte filer med skanningsresultater.
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy
Som standard slutter Trivy å kjøre hvis KRITISKE sårbarheter oppdages i bildet eller avhengigheter. Samtidig returnerer Hadolint alltid en suksesskode fordi den alltid resulterer i kommentarer, noe som får bygget til å stoppe.

Avhengig av dine spesifikke krav, kan du konfigurere en utgangskode slik at når disse verktøyene oppdager problemer med en viss kritiskhet, stopper de også byggeprosessen. I vårt tilfelle stopper byggingen bare hvis Trivy oppdager en sårbarhet med kritikaliteten som vi spesifiserte i SHOWSTOPPER-variabelen i .gitlab-ci.yml.
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

Resultatet av hvert verktøy kan sees i loggen for hver skanneoppgave, direkte i json-filene i artefakterdelen, eller i en enkel HTML-rapport (mer om det nedenfor):
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

3. For å presentere verktøyrapporter i en litt mer lesbar form, brukes et lite Python-skript for å konvertere tre JSON-filer til én HTML-fil med en tabell over defekter.
Dette skriptet lanseres av en separat rapportoppgave, og dens siste artefakt er en HTML-fil med en rapport. Skriptkilden er også i depotet og kan tilpasses dine behov, farger osv.
Metoder og eksempler på implementering av Docker sikkerhetskontrollverktøy

Shell-skript

Det andre alternativet er egnet for tilfeller der du trenger å sjekke Docker-bilder utenfor CI/CD-systemet eller du må ha alle instruksjonene i et skjema som kan utføres direkte på verten. Dette alternativet er dekket av et ferdig skallskript som kan kjøres på en ren virtuell (eller til og med ekte) maskin. Skriptet utfører de samme instruksjonene som gitlab-runner beskrevet ovenfor.

For at skriptet skal kjøre vellykket, må Docker være installert på systemet og gjeldende bruker må være i docker-gruppen.

Selve skriptet finner du her: docker_sec_check.sh

I begynnelsen av filen spesifiserer variabler hvilket bilde som skal skannes og hvilke kritikalitetsfeil som vil føre til at Trivy-verktøyet avsluttes med den angitte feilkoden.

Under kjøring av skript vil alle verktøy lastes ned til katalogen docker_tools, resultatene av arbeidet deres er i katalogen docker_tools/json, og HTML-en med rapporten vil være i filen results.html.

Eksempel på skriptutgang

~/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-bilde med alle verktøy

Som et tredje alternativ kompilerte jeg to enkle Dockerfiler for å lage et bilde med sikkerhetsverktøy. En Dockerfile vil hjelpe til med å bygge et sett for å skanne et bilde fra et depot, den andre (Dockerfile_tar) vil hjelpe til med å bygge et sett for å skanne en tar-fil med et bilde.

1. Ta den tilsvarende Docker-filen og skriptene fra depotet https://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfile.
2. Vi lanserer den for montering:

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

3. Etter at monteringen er fullført, lager vi en beholder fra bildet. Samtidig sender vi DOCKERIMAGE miljøvariabelen med navnet på bildet vi er interessert i og monterer Dockerfilen som vi ønsker å analysere fra maskinen vår til filen /Dockerfil (merk at den absolutte banen til denne filen kreves):

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

Funn

Vi så på bare ett grunnleggende sett med verktøy for å skanne Docker-artefakter, som etter min mening veldig effektivt dekker en anstendig del av bildesikkerhetskravene. Det finnes også et stort antall betalte og gratis verktøy som kan utføre de samme kontrollene, tegne flotte rapporter eller arbeide rent i konsollmodus, dekke containerhåndteringssystemer osv. En oversikt over disse verktøyene og hvordan de integreres kan dukke opp litt senere .

Det som er bra med settet med verktøy beskrevet i denne artikkelen er at de alle er åpen kildekode, og du kan eksperimentere med dem og andre lignende verktøy for å finne det som passer dine behov og infrastruktur. Selvfølgelig bør alle sårbarheter som blir funnet studeres for anvendelighet under spesifikke forhold, men dette er et tema for en fremtidig stor artikkel.

Jeg håper denne veiledningen, skriptene og verktøyene vil hjelpe deg og bli et utgangspunkt for å skape en sikrere infrastruktur innen containerisering.

Kilde: www.habr.com

Legg til en kommentar