Habari Habr!
Katika hali halisi ya kisasa, kutokana na kuongezeka kwa jukumu la uwekaji vyombo katika michakato ya maendeleo, suala la kuhakikisha usalama wa hatua na vyombo mbalimbali vinavyohusishwa na vyombo sio suala muhimu sana. Kufanya ukaguzi wa mikono kunatumia muda mwingi, kwa hivyo itakuwa vyema kuchukua angalau hatua za awali kuelekea uendeshaji mchakato huu kiotomatiki.
Katika nakala hii, nitashiriki hati zilizotengenezwa tayari za kutekeleza huduma kadhaa za usalama za Docker na maagizo ya jinsi ya kupeleka kisimamo kidogo cha onyesho ili kujaribu mchakato huu. Unaweza kutumia nyenzo kujaribu jinsi ya kupanga mchakato wa kujaribu usalama wa picha na maagizo ya Dockerfile. Ni wazi kwamba miundombinu ya maendeleo na utekelezaji wa kila mtu ni tofauti, kwa hiyo hapa chini nitatoa chaguo kadhaa iwezekanavyo.
Huduma za ukaguzi wa usalama
Kuna idadi kubwa ya maombi tofauti ya wasaidizi na hati zinazofanya ukaguzi kwenye vipengele mbalimbali vya miundombinu ya Docker. Baadhi yao tayari wameelezewa katika nakala iliyotangulia (
Hadolint
Huduma rahisi ya kiweko ambayo husaidia, kama makadirio ya kwanza, kutathmini usahihi na usalama wa maagizo ya Dockerfile (kwa mfano, kutumia sajili za picha zilizoidhinishwa pekee au kutumia sudo).
Dockle
Huduma ya kiweko ambayo inafanya kazi na picha (au na kumbukumbu ya tar iliyohifadhiwa ya picha), ambayo hukagua usahihi na usalama wa picha fulani kama hiyo, kuchambua tabaka zake na usanidi - ambayo watumiaji huundwa, maagizo gani hutumiwa, ambayo juzuu zimewekwa, uwepo wa nenosiri tupu, n.k. d. Hadi sasa idadi ya hundi si kubwa sana na inategemea ukaguzi na mapendekezo yetu kadhaa.
Trivy
Huduma hii inalenga kupata aina mbili za udhaifu - matatizo na miundo ya OS (inayoungwa mkono na Alpine, RedHat (EL), CentOS, Debian GNU, Ubuntu) na matatizo na utegemezi (Gemfile.lock, Pipfile.lock, composer.lock, kifurushi. -lock.json , yarn.lock, cargo.lock). Trivy inaweza kuchanganua picha katika hifadhi na picha ya ndani, na pia inaweza kuchanganua kulingana na faili ya .tar iliyohamishwa na picha ya Docker.
Chaguzi za utekelezaji wa huduma
Ili kujaribu programu zilizoelezewa katika mazingira ya pekee, nitatoa maagizo ya kusakinisha huduma zote katika mchakato uliorahisishwa.
Wazo kuu ni kuonyesha jinsi unavyoweza kutekeleza uthibitishaji wa maudhui kiotomatiki wa Dockerfiles na picha za Docker ambazo huundwa wakati wa uundaji.
Cheki yenyewe ina hatua zifuatazo:
- Kuangalia usahihi na usalama wa maagizo ya Dockerfile kwa kutumia matumizi ya linter Hadolint
- Kuangalia usahihi na usalama wa picha za mwisho na za kati kwa kutumia matumizi Dockle
- Inatafuta uwepo wa udhaifu unaojulikana kwa umma (CVE) katika picha ya msingi na idadi ya tegemezi - kwa kutumia matumizi. Trivy
Baadaye katika kifungu nitatoa chaguzi tatu za kutekeleza hatua hizi:
Ya kwanza ni kwa kusanidi bomba la CI/CD kwa kutumia GitLab kama mfano (na maelezo ya mchakato wa kuongeza mfano wa jaribio).
Ya pili ni kutumia hati ya ganda.
Ya tatu inajumuisha kujenga picha ya Docker ili kuchambua picha za Docker.
Unaweza kuchagua chaguo linalokufaa zaidi, uhamishe kwa miundombinu yako na uibadilishe kulingana na mahitaji yako.
Faili zote muhimu na maagizo ya ziada pia yapo kwenye ghala:
Ujumuishaji katika GitLab CI/CD
Katika chaguo la kwanza, tutaangalia jinsi unavyoweza kutekeleza ukaguzi wa usalama kwa kutumia mfumo wa hazina wa GitLab kama mfano. Hapa tutapitia hatua na kujua jinsi ya kusakinisha mazingira ya majaribio na GitLab kutoka mwanzo, kuunda mchakato wa kuchanganua na kuzindua huduma za kukagua jaribio la Dockerfile na picha nasibu - programu ya JuiceShop.
Kufunga GitLab
1. Sakinisha Docker:
sudo apt-get update && sudo apt-get install docker.io
2. Ongeza mtumiaji wa sasa kwenye kikundi cha docker ili uweze kufanya kazi na docker bila kutumia sudo:
sudo addgroup <username> docker
3. Tafuta IP yako:
ip addr
4. Sakinisha na uzindue GitLab kwenye kontena, ukibadilisha anwani ya IP katika jina la mwenyeji na yako mwenyewe:
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
Tunasubiri hadi GitLab ikamilishe taratibu zote muhimu za usakinishaji (unaweza kufuatilia mchakato kupitia pato la faili la logi: kumbukumbu za docker -f gitlab).
5. Fungua IP yako ya ndani kwenye kivinjari na uone ukurasa unaokuuliza ubadilishe nenosiri la mtumiaji wa mizizi:
Weka nenosiri mpya na uende kwa GitLab.
6. Unda mradi mpya, kwa mfano cicd-test na uanzishe na faili ya kuanza README.md:
7. Sasa tunahitaji kusakinisha GitLab Runner: wakala ambaye ataendesha shughuli zote muhimu kwa ombi.
Pakua toleo la hivi punde (katika kesi hii, kwa 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. Ifanye itekelezwe:
sudo chmod +x /usr/local/bin/gitlab-runner
9. Ongeza mtumiaji wa OS kwa Runner na uanze huduma:
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
Inapaswa kuonekana kama hii:
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. Sasa tunasajili Runner ili iweze kuingiliana na mfano wetu wa GitLab.
Ili kufanya hivyo, fungua ukurasa wa Mipangilio-CI/CD (http://OUR_IP_ADDRESS/root/cicd-test/-/settings/ci_cd) na kwenye kichupo cha Runners pata URL na tokeni ya Usajili:
11. Sajili Mkimbiaji kwa kubadilisha URL na tokeni ya Usajili:
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"
Kwa hivyo, tunapata GitLab iliyo tayari kufanya kazi, ambayo tunahitaji kuongeza maagizo ili kuanzisha huduma zetu. Katika onyesho hili hatuna hatua za kuunda programu na kuiweka kwenye kontena, lakini katika mazingira halisi haya yangetangulia hatua za skanning na kutoa picha na Dockerfile kwa uchambuzi.
usanidi wa bomba
1. Ongeza faili kwenye hifadhi mydockerfile.df (hili ni jaribio la Dockerfile ambalo tutaangalia) na faili ya usanidi wa mchakato wa GitLab CI/CD. .gitlab-cicd.yml, ambayo huorodhesha maagizo ya vichanganuzi (kumbuka kitone kwenye jina la faili).
Faili ya usanidi ya YAML ina maagizo ya kuendesha huduma tatu (Hadolint, Dockle, na Trivy) ambazo zitachanganua faili ya Docker iliyochaguliwa na picha iliyobainishwa katika kigezo cha DOCKERFILE. Faili zote muhimu zinaweza kuchukuliwa kutoka kwa hazina:
Dondoo kutoka mydockerfile.df (hii ni faili ya dhahania iliyo na seti ya maagizo ya kiholela tu kuonyesha utendakazi wa matumizi). Kiungo cha moja kwa moja kwa faili:
Yaliyomo kwenye 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
Usanidi wa YAML unaonekana kama hii (faili yenyewe inaweza kupatikana kupitia kiunga cha moja kwa moja hapa:
Yaliyomo katika .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
Ikihitajika, unaweza pia kuchanganua picha zilizohifadhiwa kwa njia ya kumbukumbu ya .tar (hata hivyo, utahitaji kubadilisha vigezo vya ingizo vya huduma katika faili ya YAML)
NB: Trivy inahitaji kusakinishwa rpm ΠΈ git. Vinginevyo, itazalisha makosa wakati wa kuchanganua picha zinazotegemea RedHat na kupokea masasisho kwenye hifadhidata ya athari.
2. Baada ya kuongeza faili kwenye hifadhi, kwa mujibu wa maagizo katika faili yetu ya usanidi, GitLab itaanza moja kwa moja mchakato wa kujenga na kutambaza. Kwenye kichupo cha CI/CD β Mabomba unaweza kuona maendeleo ya maagizo.
Matokeo yake, tuna kazi nne. Tatu kati yao huhusika moja kwa moja na skanning, na ya mwisho (Ripoti) inakusanya ripoti rahisi kutoka kwa faili zilizotawanyika na matokeo ya skanning.
Kwa chaguomsingi, Trivy huacha kufanya kazi ikiwa udhaifu CRITICAL utatambuliwa kwenye picha au vitegemezi. Wakati huo huo, Hadolint daima hurejesha Msimbo wa Mafanikio kwa sababu daima husababisha maoni, ambayo husababisha kujenga kuacha.
Kulingana na mahitaji yako maalum, unaweza kusanidi nambari ya kutoka ili huduma hizi zinapogundua shida za umuhimu fulani, pia zisimamishe mchakato wa ujenzi. Kwa upande wetu, muundo utaacha tu ikiwa Trivy itatambua athari kwa umuhimu ambao tulibainisha katika kigezo cha SHOWSTOPPER katika .gitlab-ci.yml.
Matokeo ya kila matumizi yanaweza kutazamwa katika kumbukumbu ya kila kazi ya kuchanganua, moja kwa moja kwenye faili za json katika sehemu ya vizalia vya programu, au katika ripoti rahisi ya HTML (zaidi juu ya hiyo hapa chini):
3. Ili kuwasilisha ripoti za matumizi katika umbo linaloweza kusomeka zaidi na binadamu, hati ndogo ya Python inatumiwa kubadilisha faili tatu za JSON kuwa faili moja ya HTML yenye jedwali la kasoro.
Hati hii imezinduliwa na kazi tofauti ya Ripoti, na vizalia vyake vya mwisho ni faili ya HTML yenye ripoti. Chanzo cha hati pia kiko kwenye hazina na kinaweza kubadilishwa ili kuendana na mahitaji yako, rangi, n.k.
Hati ya Shell
Chaguo la pili linafaa kwa kesi wakati unahitaji kuangalia picha za Docker nje ya mfumo wa CI/CD au unahitaji kuwa na maagizo yote katika fomu ambayo inaweza kutekelezwa moja kwa moja kwenye mwenyeji. Chaguo hili linafunikwa na hati ya ganda iliyotengenezwa tayari ambayo inaweza kuendeshwa kwenye mashine safi ya kawaida (au hata halisi). Hati hutekeleza maagizo sawa na gitlab-runner ilivyoelezwa hapo juu.
Ili hati ifanye kazi kwa mafanikio, Docker lazima isakinishwe kwenye mfumo na mtumiaji wa sasa lazima awe kwenye kikundi cha docker.
Nakala yenyewe inaweza kupatikana hapa:
Mwanzoni mwa faili, vigeu hubainisha ni picha gani inayohitaji kuchanganuliwa na ni kasoro zipi za uhasibu zitasababisha shirika la Trivy kuondoka na msimbo wa hitilafu uliobainishwa.
Wakati wa utekelezaji wa hati, huduma zote zitapakuliwa kwenye saraka zana_za_docker, matokeo ya kazi yao iko kwenye saraka docker_tools/json, na HTML iliyo na ripoti itakuwa kwenye faili matokeo.html.
Mfano wa matokeo ya hati
~/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
Picha ya Docker na huduma zote
Kama mbadala wa tatu, nilikusanya Dockerfiles mbili rahisi kuunda picha na huduma za usalama. Dockerfile moja itasaidia kujenga seti ya skanning picha kutoka kwenye hifadhi, ya pili (Dockerfile_tar) itasaidia kujenga seti ya skanning faili ya tar na picha.
1. Chukua faili ya Docker inayolingana na maandishi kutoka kwa hazina
2. Tunaizindua kwa kusanyiko:
docker build -t dscan:image -f docker_security.df .
3. Baada ya kusanyiko kukamilika, tunaunda chombo kutoka kwenye picha. Wakati huo huo, tunapitisha mabadiliko ya mazingira ya DOCKERIMAGE na jina la picha tunayopendezwa nayo na kuweka faili ya Docker ambayo tunataka kuchambua kutoka kwa mashine yetu hadi kwenye faili. /Dockerfile (kumbuka kuwa njia kamili ya faili hii inahitajika):
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
Matokeo
Tuliangalia seti moja tu ya msingi ya huduma za kuchanganua mabaki ya Docker, ambayo, kwa maoni yangu, inashughulikia kwa ufanisi sehemu nzuri ya mahitaji ya usalama wa picha. Pia kuna idadi kubwa ya zana zinazolipishwa na zisizolipishwa ambazo zinaweza kufanya ukaguzi sawa, kuchora ripoti nzuri au kufanya kazi katika hali ya kiweko, mifumo ya udhibiti wa kontena, n.k. Muhtasari wa zana hizi na jinsi ya kuziunganisha unaweza kuonekana baadaye kidogo. .
Jambo jema kuhusu seti ya zana zilizoelezwa katika makala hii ni kwamba zote ni chanzo wazi na unaweza kuzifanyia majaribio na zana zingine zinazofanana ili kupata kile kinachofaa mahitaji yako na miundombinu. Bila shaka, udhaifu wote unaopatikana unapaswa kuchunguzwa kwa matumizi katika hali maalum, lakini hii ni mada ya makala kubwa ya baadaye.
Natumai mwongozo huu, maandishi na huduma zitakusaidia na kuwa kianzio cha kuunda miundombinu salama zaidi katika eneo la kontena.
Chanzo: mapenzi.com