Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed
Hej Habr!

I moderne virkelighed, på grund af containeriseringens voksende rolle i udviklingsprocesser, er spørgsmålet om at sikre sikkerheden for forskellige stadier og enheder forbundet med containere ikke det mindst vigtige spørgsmål. Det er tidskrævende at udføre manuelle kontroller, så det vil være en god idé at tage mindst de første skridt til at automatisere denne proces.

I denne artikel vil jeg dele færdige scripts til implementering af adskillige Docker-sikkerhedsværktøjer og instruktioner om, hvordan man implementerer et lille demo-stativ for at teste denne proces. Du kan bruge materialerne til at eksperimentere med, hvordan du organiserer processen med at teste sikkerheden af ​​Dockerfile-billeder og instruktioner. Det er klart, at alles udviklings- og implementeringsinfrastruktur er forskellig, så nedenfor vil jeg give flere mulige muligheder.

Sikkerhedskontrolværktøjer

Der er et stort antal forskellige hjælpeprogrammer og scripts, der udfører kontrol af forskellige aspekter af Docker-infrastrukturen. Nogle af dem er allerede blevet beskrevet i den forrige artikel (https://habr.com/ru/company/swordfish_security/blog/518758/#docker-security), og i dette materiale vil jeg gerne fokusere på tre af dem, som dækker hovedparten af ​​sikkerhedskravene til Docker-billeder bygget under udviklingsprocessen. Derudover vil jeg også vise et eksempel på, hvordan disse tre hjælpeprogrammer kan forbindes til én pipeline for at udføre sikkerhedstjek.

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

Et ret simpelt konsolværktøj, der hjælper, som en første tilnærmelse, med at evaluere rigtigheden og sikkerheden af ​​Dockerfile-instruktioner (for eksempel ved kun at bruge autoriserede billedregistre eller ved at bruge sudo).

Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

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

Et konsolværktøj, der arbejder med et billede (eller med et gemt tar-arkiv af et billede), som kontrollerer rigtigheden og sikkerheden af ​​et bestemt billede som sådan, analyserer dets lag og konfiguration - hvilke brugere der oprettes, hvilke instruktioner der bruges, hvilke mængder er monteret, tilstedeværelsen af ​​et tomt kodeord osv. d. Indtil videre er antallet af kontroller ikke særlig stort og er baseret på flere af vores egne kontroller og anbefalinger CIS (Center for Internet Security) benchmark for Docker.
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

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

Dette værktøj er rettet mod at finde to typer sårbarheder - problemer med OS builds (understøttet af Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) og problemer med afhængigheder (Gemfile.lock, Pipfile.lock, composer.lock, pakke -lock.json , yarn.lock, cargo.lock). Trivy kan scanne både et billede i depotet og et lokalt billede, og kan også scanne baseret på den overførte .tar-fil med Docker-billedet.

Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

Muligheder for implementering af hjælpeprogrammer

For at prøve de beskrevne programmer i et isoleret miljø, vil jeg give instruktioner til installation af alle hjælpeprogrammer i en noget forenklet proces.

Hovedidéen er at demonstrere, hvordan du kan implementere automatisk indholdsverifikation af Dockerfiler og Docker-billeder, der oprettes under udvikling.

Selve kontrollen består af følgende trin:

  1. Kontrol af rigtigheden og sikkerheden af ​​Dockerfile-instruktionerne ved hjælp af et linter-værktøj Hadolint
  2. Kontrol af rigtigheden og sikkerheden af ​​de endelige og mellemliggende billeder ved hjælp af et hjælpeprogram Dockle
  3. Tjek for tilstedeværelsen af ​​offentligt kendte sårbarheder (CVE) i basisbilledet og en række afhængigheder - ved hjælp af hjælpeprogrammet Trivy

Senere i artiklen vil jeg give tre muligheder for at implementere disse trin:
Den første er ved at konfigurere CI/CD-pipelinen ved at bruge GitLab som eksempel (med en beskrivelse af processen med at rejse en testinstans).
Den anden bruger et shell-script.
Den tredje involverer at bygge et Docker-billede for at scanne Docker-billeder.
Du kan vælge den mulighed, der passer dig bedst, overføre den til din infrastruktur og tilpasse den til dine behov.

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

Integration i GitLab CI/CD

I den første mulighed vil vi se på, hvordan du kan implementere sikkerhedstjek ved at bruge GitLab repository-systemet som eksempel. Her vil vi gennemgå trinene og finde ud af, hvordan man installerer et testmiljø med GitLab fra bunden, opretter en scanningsproces og starter hjælpeprogrammer til at tjekke testen Dockerfile og et tilfældigt billede - JuiceShop-applikationen.

Installation af GitLab
1. Installer Docker:

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

2. Tilføj den aktuelle bruger til docker-gruppen, så du kan arbejde med docker uden at bruge sudo:

sudo addgroup <username> docker

3. Find din IP:

ip addr

4. Installer og start GitLab i containeren, og udskift IP-adressen i værtsnavnet med dit 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, indtil GitLab fuldfører alle de nødvendige installationsprocedurer (du kan overvåge processen gennem logfilens output: docker logs -f gitlab).

5. Åbn din lokale IP i browseren og se en side, der beder dig om at ændre adgangskoden til root-brugeren:
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed
Indstil en ny adgangskode og gå til GitLab.

6. Opret et nyt projekt, for eksempel cicd-test og initialiser det med startfilen README.md:
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed
7. Nu skal vi installere GitLab Runner: en agent, der vil køre alle de nødvendige operationer efter anmodning.
Download den seneste version (i dette tilfælde til 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. Gør det eksekverbart:

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

9. Tilføj en OS-bruger til 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 sådan ud:

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. Nu registrerer vi Runner, så den kan interagere med vores GitLab-instans.
For at gøre dette skal du åbne siden Settings-CI/CD (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) og på fanen Runners finde URL'en og registreringstoken:
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed
11. Registrer Runner ved at erstatte URL'en og registreringstokenet:

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 færdigt fungerende GitLab, hvori vi skal tilføje instruktioner for at starte vores hjælpeprogrammer. I denne demo har vi ikke trinene til at bygge applikationen og containerisere den, men i et virkeligt miljø vil disse gå forud for scanningstrinene og generere billeder og en Dockerfil til analyse.

pipeline konfiguration

1. Tilføj filer til depotet mydockerfile.df (dette er en test Docker-fil, som vi vil tjekke) og GitLab CI/CD-proceskonfigurationsfilen .gitlab-cicd.yml, som viser instruktioner til scannere (bemærk prikken i filnavnet).

YAML-konfigurationsfilen indeholder instruktioner til at køre tre hjælpeprogrammer (Hadolint, Dockle og Trivy), som analyserer den valgte Dockerfil og det billede, der er angivet i DOCKERFILE-variablen. Alle nødvendige filer kan tages fra depotet: https://github.com/Swordfish-Security/docker_cicd/

Uddrag fra mydockerfile.df (dette er en abstrakt fil med et sæt vilkårlige instruktioner kun for at demonstrere funktionen af ​​hjælpeprogrammet). Direkte link til filen: mydockerfile.df

Indhold af 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

Konfigurationen YAML ser sådan ud (selve filen kan findes via det direkte link her: .gitlab-ci.yml):

Indhold af .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ødvendigt kan du også scanne gemte billeder i form af et .tar-arkiv (du skal dog ændre inputparametrene for hjælpeprogrammerne i YAML-filen)

NB: Trivy kræver installeret rpm и git. Ellers vil det generere fejl ved scanning af RedHat-baserede billeder og modtagelse af opdateringer til sårbarhedsdatabasen.

2. Efter at have tilføjet filer til depotet, i henhold til instruktionerne i vores konfigurationsfil, vil GitLab automatisk begynde bygge- og scanningsprocessen. På fanen CI/CD → Pipelines kan du se instruktionernes fremskridt.

Derfor har vi fire opgaver. Tre af dem omhandler direkte scanning, og den sidste (Rapport) samler en simpel rapport fra spredte filer med scanningsresultater.
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed
Som standard stopper Trivy med at køre, hvis KRITISKE sårbarheder opdages i billedet eller afhængigheder. Samtidig returnerer Hadolint altid en succeskode, fordi den altid resulterer i kommentarer, som får bygningen til at stoppe.

Afhængigt af dine specifikke krav kan du konfigurere en exit-kode, så når disse hjælpeprogrammer opdager problemer af en vis kritikalitet, stopper de også byggeprocessen. I vores tilfælde stopper bygningen kun, hvis Trivy opdager en sårbarhed med den kritikalitet, som vi specificerede i SHOWSTOPPER-variablen i .gitlab-ci.yml.
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

Resultatet af hvert værktøj kan ses i loggen for hver scanningsopgave, direkte i json-filerne i artefaktsektionen eller i en simpel HTML-rapport (mere om det nedenfor):
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

3. For at præsentere hjælperapporter i en lidt mere læselig form, bruges et lille Python-script til at konvertere tre JSON-filer til én HTML-fil med en tabel over defekter.
Dette script startes af en separat rapportopgave, og dets sidste artefakt er en HTML-fil med en rapport. Scriptkilden er også i depotet og kan tilpasses, så den passer til dine behov, farver mv.
Metoder og eksempler på implementering af hjælpeprogrammer til kontrol af Docker-sikkerhed

Shell script

Den anden mulighed er velegnet til tilfælde, hvor du skal kontrollere Docker-billeder uden for CI/CD-systemet, eller du skal have alle instruktionerne i en form, der kan udføres direkte på værten. Denne mulighed er dækket af et færdiglavet shell-script, der kan køres på en ren virtuel (eller endda ægte) maskine. Scriptet udfører de samme instruktioner som gitlab-runneren beskrevet ovenfor.

For at scriptet kan køre med succes, skal Docker være installeret på systemet, og den aktuelle bruger skal være i docker-gruppen.

Selve scriptet kan findes her: docker_sec_check.sh

I begyndelsen af ​​filen angiver variabler, hvilket billede der skal scannes, og hvilke kritikalitetsfejl, der får Trivy-værktøjet til at afslutte med den angivne fejlkode.

Under scriptudførelse vil alle hjælpeprogrammer blive downloadet til mappen docker_tools, resultaterne af deres arbejde er i biblioteket docker_tools/json, og HTML'en med rapporten vil være i filen resultater.html.

Eksempel på scriptoutput

~/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-billede med alle hjælpeprogrammer

Som et tredje alternativ kompilerede jeg to simple Dockerfiler for at skabe et billede med sikkerhedsværktøjer. Den ene Dockerfile hjælper med at bygge et sæt til at scanne et billede fra et lager, den anden (Dockerfile_tar) hjælper med at bygge et sæt til at scanne en tar-fil med et billede.

1. Tag den tilsvarende Docker-fil og scripts fra lageret https://github.com/Swordfish-Security/docker_cicd/tree/master/Dockerfile.
2. Vi starter den til montering:

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

3. Efter at samlingen er afsluttet, opretter vi en beholder fra billedet. Samtidig sender vi DOCKERIMAGE miljøvariablen med navnet på det billede, vi er interesseret i og monterer den Dockerfil, som vi vil analysere fra vores maskine til filen /Dockerfil (bemærk at den absolutte sti til denne fil er påkrævet):

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

Fund

Vi har kun set på ét grundlæggende sæt værktøjer til scanning af Docker-artefakter, som efter min mening meget effektivt dækker en anstændig del af billedsikkerhedskravene. Der er også et stort antal betalte og gratis værktøjer, der kan udføre de samme kontroller, tegne smukke rapporter eller arbejde rent i konsoltilstand, dække containerstyringssystemer osv. En oversigt over disse værktøjer og hvordan man integrerer dem kan dukke op lidt senere .

Det gode ved det sæt værktøjer, der er beskrevet i denne artikel, er, at de alle er open source, og du kan eksperimentere med dem og andre lignende værktøjer for at finde det, der passer til dine behov og infrastruktur. Selvfølgelig skal alle sårbarheder, der findes, undersøges for anvendelighed under specifikke forhold, men dette er et emne for en fremtidig stor artikel.

Jeg håber, at denne guide, scripts og hjælpeprogrammer vil hjælpe dig og blive et udgangspunkt for at skabe en mere sikker infrastruktur inden for containerisering.

Kilde: www.habr.com

Tilføj en kommentar