هی هابر!
در واقعیت امروز، با توجه به نقش فزاینده کانتینریسازی در فرآیندهای توسعه، موضوع تامین امنیت مراحل مختلف و موجودیتهای مرتبط با کانتینرها در آخرین جایگاه قرار ندارد. انجام چک ها به صورت دستی یک کار پر زحمت است، بنابراین بهتر است حداقل گام های اولیه برای خودکارسازی این فرآیند بردارید.
در این مقاله، اسکریپتهای آماده برای پیادهسازی چندین ابزار امنیتی Docker و دستورالعملهایی در مورد نحوه راهاندازی یک استند نمایشی کوچک برای آزمایش این فرآیند به اشتراک میگذارم. می توانید از مواد برای آزمایش نحوه سازماندهی فرآیند تست امنیت تصاویر و دستورالعمل های Dockerfile استفاده کنید. واضح است که زیرساخت توسعه و پیاده سازی برای همه متفاوت است، بنابراین در زیر چندین گزینه ممکن را ارائه خواهم کرد.
ابزارهای چک امنیتی
تعداد زیادی برنامه و اسکریپت کمکی مختلف وجود دارد که جنبه های مختلف زیرساخت داکر را بررسی می کند. برخی از آنها قبلاً در مقاله قبلی توضیح داده شده است (
هادولینت
یک ابزار کنسول نسبتاً ساده که به ارزیابی صحت و ایمنی دستورالعملهای Dockerfile کمک میکند (به عنوان مثال، فقط با استفاده از ثبت تصاویر مجاز یا استفاده از sudo).
داکل
یک ابزار کنسول که بر روی یک تصویر (یا روی یک تصویر ذخیره شده) کار می کند که صحت و امنیت یک تصویر خاص را با تجزیه و تحلیل لایه ها و پیکربندی آن بررسی می کند - چه کاربرانی ایجاد شده اند، چه دستورالعمل هایی در حال استفاده هستند، چه حجم هایی نصب شده اند. وجود پسورد خالی و غیره. در حالی که تعداد چک ها خیلی زیاد نیست و بر اساس چندین بررسی و توصیه شخصی است.
بی اهمیت
هدف این ابزار یافتن دو نوع آسیبپذیری است - مشکلات ساخت سیستم عامل (Alpine، RedHat (EL)، CentOS، Debian GNU، Ubuntu پشتیبانی میشوند) و مشکلات وابستگی (Gemfile.lock، Pipfile.lock، composer.lock، بسته-lock). .json، yarn.lock، Cargo.lock). Trivy می تواند هم تصویر موجود در مخزن و هم تصویر محلی را اسکن کند و همچنین بر اساس فایل .tar منتقل شده با تصویر Docker اسکن کند.
گزینه های پیاده سازی Utilities
به منظور آزمایش برنامه های کاربردی توصیف شده در شرایط ایزوله، دستورالعمل هایی را برای نصب همه ابزارها به عنوان بخشی از یک فرآیند ساده ارائه خواهم کرد.
ایده اصلی این است که نشان دهیم چگونه می توانید بررسی خودکار محتوای Dockerfiles و تصاویر Docker را که در طول توسعه ایجاد می شوند، پیاده سازی کنید.
خود تأیید شامل مراحل زیر است:
- بررسی صحت و ایمنی دستورالعملهای Dockerfile با یک ابزار لینتر هادولینت
- بررسی صحت و امنیت تصاویر نهایی و میانی - یک ابزار داکل
- بررسی آسیب پذیری های رایج شناخته شده (CVE) در تصویر پایه و تعدادی از وابستگی ها - توسط ابزار کاربردی بی اهمیت
بعداً در مقاله سه گزینه برای اجرای این مراحل ارائه خواهم داد:
اولین مورد با پیکربندی خط لوله CI / CD با استفاده از مثال GitLab (با شرحی از فرآیند بالا بردن یک نمونه آزمایشی) است.
مورد دوم استفاده از اسکریپت پوسته است.
سومین مورد با ساخت یک تصویر داکر برای اسکن تصاویر داکر است.
شما می توانید گزینه ای را انتخاب کنید که برای شما مناسب است، آن را به زیرساخت خود منتقل کنید و آن را با نیازهای خود تطبیق دهید.
تمام فایل های لازم و دستورالعمل های اضافی نیز در مخزن موجود است:
ادغام GitLab CI/CD
در گزینه اول، نحوه اجرای بررسی های امنیتی را با استفاده از سیستم مخزن GitLab به عنوان مثال بررسی خواهیم کرد. در اینجا ما مراحل را طی می کنیم و نحوه راه اندازی یک محیط آزمایشی با GitLab را از ابتدا، ایجاد یک فرآیند اسکن و اجرای برنامه های کاربردی برای آزمایش یک Dockerfile آزمایشی و یک تصویر تصادفی - برنامه JuiceShop، خواهیم دید.
نصب GitLab
1. Docker را نصب کنید:
sudo apt-get update && sudo apt-get install docker.io
2. کاربر فعلی را به گروه docker اضافه کنید تا بتوانید بدون استفاده از sudo با docker کار کنید:
sudo addgroup <username> docker
3. IP خود را پیدا کنید:
ip addr
4. GitLab را در کانتینر نصب و اجرا کنید و آدرس IP موجود در نام میزبان را با آدرس خود جایگزین کنید:
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
ما منتظر GitLab هستیم تا تمام مراحل نصب لازم را انجام دهد (شما می توانید فرآیند را از طریق خروجی فایل log دنبال کنید: docker logs -f gitlab).
5. IP محلی خود را در مرورگر باز کنید و صفحه ای را ببینید که برای تغییر رمز عبور کاربر اصلی پیشنهاد می شود:
یک رمز عبور جدید تنظیم کنید و به GitLab بروید.
6. یک پروژه جدید، به عنوان مثال cicd-test ایجاد کنید و آن را با یک فایل start مقداردهی کنید README.md:
7. اکنون باید GitLab Runner را نصب کنیم: عاملی که در صورت درخواست، تمامی عملیات لازم را اجرا می کند.
آخرین نسخه (در این مورد، تحت لینوکس 64 بیتی) را دانلود کنید:
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
8. آن را قابل اجرا کنید:
sudo chmod +x /usr/local/bin/gitlab-runner
9. یک کاربر سیستم عامل برای Runner اضافه کنید و سرویس را شروع کنید:
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
باید چیزی شبیه این باشد:
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. اکنون Runner را ثبت می کنیم تا بتواند با نمونه GitLab ما تعامل داشته باشد.
برای انجام این کار، صفحه Settings-CI/CD (http://OUR_ IP_ADDRESS/root/cicd-test/-/settings/ci_cd) را باز کنید و در تب Runners URL و نشانه ثبت نام را بیابید:
11. Runner را با جایگزینی URL و نشانه ثبت نام ثبت کنید:
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"
در نتیجه، یک GitLab کار آماده دریافت می کنیم که در آن باید دستورالعمل هایی را برای شروع برنامه های خود اضافه کنیم. در این نسخه آزمایشی، مراحل ساخت اپلیکیشن و کانتینرسازی نداریم، اما در یک محیط واقعی، این مراحل قبل از مراحل اسکن میشوند و تصاویر و یک Dockerfile برای تجزیه و تحلیل تولید میکنند.
پیکربندی خط لوله
1. فایل ها را به مخزن اضافه کنید mydockerfile.df (این یک Dockerfile آزمایشی است که ما آزمایش خواهیم کرد) و فایل پیکربندی فرآیند GitLab CI/CD .gitlab-cicd.yml، که دستورالعمل های مربوط به اسکنرها را فهرست می کند (به نقطه در نام فایل توجه کنید).
فایل پیکربندی .yaml حاوی دستورالعمل هایی برای اجرای سه ابزار (Hadolint، Dockle و Trivy) است که Dockerfile انتخاب شده و تصویر مشخص شده در متغیر DOCKERFILE را تجزیه می کند. تمام فایل های لازم را می توان از مخزن برداشت:
استخراج از mydockerfile.df (این یک فایل انتزاعی با مجموعهای از دستورالعملهای دلخواه است که فقط برای نشان دادن نحوه عملکرد ابزار است). لینک مستقیم فایل:
محتویات 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
پیکربندی YAML به این شکل است (خود فایل را می توان از پیوند مستقیم اینجا گرفت:
مطالب .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
در صورت لزوم، می توانید تصاویر ذخیره شده را نیز به عنوان بایگانی tar اسکن کنید (با این حال، باید پارامترهای ورودی برنامه های کاربردی را در فایل YAML تغییر دهید)
نکته: Trivy نیاز به نصب دارد دور در دقیقه и دستگاه گوارش. در غیر این صورت، هنگام اسکن تصاویر مبتنی بر RedHat و دریافت بهروزرسانیهای پایگاه داده آسیبپذیری، خطا ایجاد میکند.
2. پس از افزودن فایل ها به مخزن، طبق دستورالعمل های موجود در فایل پیکربندی ما، GitLab به طور خودکار فرآیند ساخت و اسکن را شروع می کند. در برگه CI / CD → Pipelines، می توانید پیشرفت دستورالعمل ها را مشاهده کنید.
در نتیجه ما چهار وظیفه داریم. سه مورد از آنها مستقیماً درگیر اسکن هستند و آخرین مورد (گزارش) یک گزارش ساده از فایل های پراکنده با نتایج اسکن جمع آوری می کند.
اگر آسیبپذیریهای مهمی در تصویر یا وابستگیها یافت شود، بهطور پیشفرض، Trivy اجرای خود را متوقف میکند. در عین حال، هادولینت همیشه Success را در کد اجرا برمی گرداند، زیرا اجرای آن همیشه دارای نکاتی است که باعث توقف ساخت می شود.
بسته به نیازهای خاص خود، میتوانید یک کد خروجی را پیکربندی کنید تا در صورت شناسایی مشکلات با بحرانی خاص، این ابزارها فرآیند ساخت را متوقف کنند. در مورد ما، ساخت تنها در صورتی متوقف میشود که Trivy آسیبپذیری را با شدتی که در متغیر SHOWSTOPPER در آن مشخص کردهایم شناسایی کند. .gitlab-ci.yml.
نتیجه عملکرد هر ابزار را میتوان در گزارش هر کار اسکن، مستقیماً در فایلهای json در بخش مصنوعات یا در یک گزارش ساده HTML مشاهده کرد (اطلاعات بیشتر در مورد آن در زیر):
3. برای ارائه گزارشهای ابزار به شکلی خواناتر برای انسان، از یک اسکریپت کوچک پایتون برای تبدیل سه فایل json به یک فایل HTML با جدولی از نقصها استفاده میشود.
این اسکریپت توسط یک کار گزارش جداگانه راه اندازی می شود و آرتیفکت نهایی آن یک فایل HTML با یک گزارش است. منبع اسکریپت نیز در مخزن است و می تواند با نیازها، رنگ ها و غیره شما سازگار شود.
اسکریپت شل
گزینه دوم برای مواردی مناسب است که باید تصاویر Docker را که در سیستم CI / CD نیستند بررسی کنید یا باید تمام دستورالعمل ها را به شکلی داشته باشید که بتوان مستقیماً روی هاست اجرا کرد. این گزینه توسط یک اسکریپت پوسته آماده پوشانده شده است که می تواند بر روی یک ماشین مجازی تمیز (یا حتی واقعی) اجرا شود. اسکریپت همان دستورالعمل gitlab-runner بالا را دنبال می کند.
برای اینکه اسکریپت با موفقیت کار کند، Docker باید روی سیستم نصب شده باشد و کاربر فعلی باید در گروه docker باشد.
خود اسکریپت را می توانید در اینجا پیدا کنید:
در ابتدای فایل، متغیرها مشخص می کنند که کدام تصویر باید اسکن شود و چه شدت نقصی باعث می شود که ابزار Trivy با کد خطای مشخص شده خارج شود.
در طول اجرای اسکریپت، تمام برنامه های کاربردی در دایرکتوری دانلود می شوند docker_tools، نتایج کار آنها - در دایرکتوری docker_tools/json، و HTML با گزارش در فایل خواهد بود results.html.
نمونه خروجی اسکریپت
~/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
تصویر داکر با تمام امکانات
به عنوان جایگزین سوم، من دو Dockerfiles ساده را برای ایجاد یک تصویر با ابزارهای امنیتی کامپایل کردم. یک Dockerfile به ساخت مجموعه ای برای اسکن تصویر از مخزن کمک می کند، دومی (Dockerfile_tar) مجموعه ای را برای اسکن فایل tar با تصویر می سازد.
1. فایل Docker و اسکریپت های مناسب را از مخزن می گیریم
2. آن را برای مونتاژ اجرا کنید:
docker build -t dscan:image -f docker_security.df .
3. پس از اتمام ساخت، یک ظرف از تصویر ایجاد کنید. در همان زمان، متغیر محیطی DOCKERIMAGE را با نام تصویری که به آن علاقه داریم ارسال می کنیم و Dockerfile را که می خواهیم آنالیز کنیم از دستگاه خود به فایل متصل می کنیم. /dockerfile (توجه داشته باشید که یک مسیر مطلق برای این فایل مورد نیاز است):
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
یافته ها
ما فقط یک مجموعه اساسی از ابزارهای اسکن مصنوع Docker را پوشش دادهایم، که فکر میکنم بخش خوبی از الزامات امنیتی تصویر را کاملاً مؤثر پوشش میدهد. بسیاری از ابزارهای پولی و رایگان دیگر نیز وجود دارند که میتوانند همان بررسیها را انجام دهند، گزارشهای زیبایی بکشند یا صرفاً در حالت کنسول کار کنند، سیستمهای مدیریت کانتینر را پوشش دهند و غیره. مروری بر این ابزارها و نحوه ادغام آنها ممکن است کمی بعد ظاهر شود.
جنبه مثبت مجموعه ابزارهایی که در مقاله توضیح داده شد این است که همه آنها بر اساس منبع باز ساخته شده اند و می توانید با آنها و سایر ابزارهای مشابه آزمایش کنید تا دقیقاً مطابق با نیازها و ویژگی های زیرساخت خود بیابید. البته، تمام آسیبپذیریهایی که پیدا میشوند باید برای کاربرد در شرایط خاص مورد مطالعه قرار گیرند، اما این موضوع برای یک مقاله بزرگ آینده است.
امیدوارم این دستورالعمل ها، اسکریپت ها و ابزارهای کمکی به شما کمک کند و نقطه شروعی برای ایجاد زیرساخت امن تر در زمینه کانتینرسازی باشد.
منبع: www.habr.com