امنیت Container ها با Trivy
امنیت همیشه یکی از مهمترین گزینه ها برای محصولاته به خصوص اگر این محصول به صورت عمومی منتشر بشه و در اختیار بقیه قرار بگیره. استفاده از Container ها خیلی رایج شده و همه ما در پروژه ها داریم ازشون استفاده می کنیم. در این پست به بررسی های امنیتی در این حوزه می پردازیم.
مشکل کجاست ؟
وقتی ما داریم یه Container آماده می کنیم بخش های زیادی دخیل هستن از جمله :
- سورس کد پروژه
- نصب پکیج های سیستم عامل
- نصب Dependency های خود پروژه ( استفاده از NPM, Composer, ... )
برای بخش اول خب مسلما برنامه نویس های عزیز همه کار میکنن تا پروژه مشکل امنیتی نداشته باشه. برای دو مورد بعدی چه کنیم ؟ برای مثال شما به پکیج OpenSSL نیاز دارید و در ابتدای Dockerfile خودتون اون رو با استفاده از apt
نصب می کنید. حالا اگر همین نسخه OpenSSL که نصب میشه دارای باگ امنیتی باشه چه اتفاقی میوفته ؟ شما اونو توی کانتینر خودتون قرار دادید و اونو یه جایی Deploy می کنید.
بریم جلوتر ... شما یه پروژه Laravel توسعه دادید و نیازمندی های اون رو با استفاده از Composer نصب کردید. یکی از این نیازمندی ها مثلا guzzle
مثل مورد قبلی دارای باگ خاصی باشه.
اگر یه تیم بخواد تک تک پکیج ها رو بررسی کنه و vulnerabilities ازشون در بیاره و نسخه تنظیم کنه خب باید برن یه تیم دیگه استخدام کنن ... اصلا این کار رو چندبار باید انجام بدن ؟ ممکنه هفته ای یک نسخه منتشر بشه ٬ باید هر هفته چند ساعت وقت بذارن و دستی تمام موارد رو بررسی کنن ؟ مسلما نه
راه حل چیه ؟
در حال حاضر اکثر ماها از CI/CD استفاده می کنیم. تمام روند تست و بیلد و انتشار پروژه ها خودکار میشه و خودمون رو راحت می کنیم. قبلا هم چندتا پست در این باره نوشتم که احتمالا مطالعه کرده باشید :
حالا که این همه روند توسعه و انتشار ما با ابزار های CI گره خورده ٬ خیلی خوب میشه اگر بررسی موارد امنیتی هم در همین حین انجام بدیم. اینجاست که Trivy وارد میشه !!!
Trivy چیه ؟
این پروژه تقریبا یک سال از انتشارش میگذره و در حال حاضر به نسخه 0.11.0 رسیده. کارش هم اسکن کردن Container ها یا فایل های سیستمی شماست تا مطمپن بشید هیچ مشکل امنیتی وجود نداره. به طور ویژه ای برای استفاده در ابزار های CI ساخته شده تا همون روند خودکار سازی که قبل از این توضیح دادم اتفاق بیوفته. ویژگی های خوبی هم داره از جمله :
- شناسایی مشکلات امنیتی در بخش های مختلف
- ساده
- سریع
- نصب و استفاده آسان
- دقت بالا
- مناسب برای CI
- پشتیبانی از پلتفرم های مختلف
نصب
نصب Trivy خیلی ساده است و فقط با یه دستور انجام میشه :
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh -s -- -b /usr/local/bin
در صورت نیاز میتونید به قسمت Release ریپازیتوری برید و نسخه های باینری دلخواهتون رو دانلود کنید.
استفاده
برای اسکن کردن تنها کافیه یک Docker image که درواقع همون کانتینر شما به حساب میاد رو به Trivy بدید :
trivy image [YOUR_IMAGE_NAME]
# Example
trivy image python:3.4-alpine3.9
2019-05-16T01:20:43.180+0900 INFO Updating vulnerability database...
2019-05-16T01:20:53.029+0900 INFO Detecting Alpine vulnerabilities...
python:3.4-alpine3.9 (alpine 3.9.2)
===================================
Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
| openssl | CVE-2019-1543 | MEDIUM | 1.1.1a-r1 | 1.1.1b-r1 | openssl: ChaCha20-Poly1305 |
| | | | | | with long nonces |
+---------+------------------+----------+-------------------+---------------+--------------------------------+
مشاهده می کنید که در ابتدا دیتابیس vulnerability به روزرسانی میشه و سپس پکیج های سیستم عامل که در اینجا ما Alpine داریم بررسی میشه و نتایج اعلام میشه.
کار با CI
تنظیم کردن Trivy برای کار با ابزار های CI هم چیز سختی نیست. از اونجایی که اسکن روی کانتینر ها انجام میشه فقط کافیه تا این عملیات رو بعد از بخش Build کردن ایمیج داکر انجام بدیم :
Build image > Scan by Trivy > Push to registry
به این مثال در Azure Pipeline نگاه کنید :
- stage: Build
dependsOn: Test
condition: succeeded()
displayName: Build, Scan and Push image
jobs:
- job: Build
steps:
- task: Docker@2
displayName: Build docker image
inputs:
containerRegistry: "DockerHub"
repository: $(imageName)
command: build
Dockerfile: "$(Build.SourcesDirectory)/Dockerfile"
tags: $(tag)
- script: |
sudo apt-get install rpm
wget https://github.com/aquasecurity/trivy/releases/download/v$(trivyVersion)/trivy_$(trivyVersion)_Linux-64bit.deb
sudo dpkg -i trivy_$(trivyVersion)_Linux-64bit.deb
trivy -v
displayName: "Download and install Trivy"
- task: CmdLine@2
displayName: "Run trivy scan"
inputs:
script: |
trivy image --download-db-only
trivy image --exit-code 0 --severity LOW,MEDIUM $(imageName):$(tag)
trivy image --exit-code 1 --severity HIGH,CRITICAL $(imageName):$(tag)
trivy image --clear-cache
- task: Docker@2
displayName: "Push image"
inputs:
containerRegistry: "DockerHub"
repository: "$(imageName)"
command: push
tags: "$(tag)"
همینطور که مشاهده می کنید در این Stage ما ۴ کار انجام میدیم :
- Build image
- Download and install Trivy
- Scan container
- Push image
اگر به قسمت اسکن دقت کنید کمی دستورات رو پیچیده تر نوشتم. به طور پیشفرض اگر مشکل امنیتی پیدا بشه Trivy با کد 0 خاتمه پیدا میکنه. در اینجا با استفاده از severity
مشخص کردم اگه اگر مشکل پیدا شده از نظر شدت در درجه LOW یا MEDIUM بود با همون کد 0 خارج شو و اگر شدت در درجه HIGH یا CRITICAL بود با کد ۱ خارج شو.
برای استفاده از Trivy تنظیمات و گزینه های دیگه ای هم وجود داره که می تونید برای اطلاع بیشتر به ریپازیتوری پروژه مراجعه کنید :
اضافه کردن دو Job به Pipeline ها کار چندان سختی نیست ...سعی کنید با انجام دادنش پروژه های خودتون رو ایمن تر کنید. خودم از امروز به روزرسانی ها رو انجام میدم به تدریج :))