مشکل کجاست ؟

وقتی ما داریم یه Container آماده می کنیم بخش های زیادی دخیل هستن از جمله :

  • سورس کد پروژه
  • نصب پکیج های سیستم عامل
  • نصب Dependency های خود پروژه ( استفاده از NPM, Composer, ... )

برای بخش اول خب مسلما برنامه نویس های عزیز همه کار میکنن تا پروژه مشکل امنیتی نداشته باشه. برای دو مورد بعدی چه کنیم ؟ برای مثال شما به پکیج OpenSSL نیاز دارید و در ابتدای Dockerfile خودتون اون رو با استفاده از apt نصب می کنید. حالا اگر همین نسخه OpenSSL که نصب میشه دارای باگ امنیتی باشه چه اتفاقی میوفته ؟ شما اونو توی کانتینر خودتون قرار دادید و اونو یه جایی Deploy می کنید.

بریم جلوتر ... شما یه پروژه Laravel توسعه دادید و نیازمندی های اون رو با استفاده از Composer نصب کردید. یکی از این نیازمندی ها مثلا guzzle مثل مورد قبلی دارای باگ خاصی باشه.

اگر یه تیم بخواد تک تک پکیج ها رو بررسی کنه و vulnerabilities ازشون در بیاره و نسخه تنظیم کنه خب باید برن یه تیم دیگه استخدام کنن ... اصلا این کار رو چندبار باید انجام بدن ؟ ممکنه هفته ای یک نسخه منتشر بشه ٬ باید هر هفته چند ساعت وقت بذارن و دستی تمام موارد رو بررسی کنن ؟ مسلما نه

راه حل چیه ؟

در حال حاضر اکثر ماها از CI/CD استفاده می کنیم. تمام روند تست و بیلد و انتشار پروژه ها خودکار میشه و خودمون رو راحت می کنیم. قبلا هم چندتا پست در این باره نوشتم که احتمالا مطالعه کرده باشید :

استقرار خودکار پروژه های Laravel با Gitlab CI
آخرین مرحله از روند توسعه یک پروژه مربوط به مباحث استقرار اون میشه. خودکارسازی این کار کمک زیادی به صرفه جویی در وقت میکنه و باعث میشه نیروهای فنی مجموعه تمرکز خودشون رو روی موارد دیگه ای قرار بدن. در این پست به بررسی چنین کاری می پردازیم.
پروژه های Laravel و CI/CD
وجود ابزارهای مختلف برای تست و استقرار پروژه خیلی خوبه ، ولی وقتی ارزش دارن که ازشون استفاده کنید. یکی از بهترین ابزار های این حوزه هم Gitlab CI/CD است که تو این پست استفاده ازش برای پروژه های Laravel رو توضیح میدم.
استفاده از Github Actions برای پروژه های Go
قابلیت جدیدی که اخیرا توسط GitHub معرفی شده ، GitHub Actions است و به شما این امکان را می‌دهد که جریان کاری را به صورت خودکار درآورید. این پروژه درواقع یک CI درحال توسعه است که روز به روز در حال تکامل بوده و هم رده با رقبا پیشرفت میکنه.

حالا که این همه روند توسعه و انتشار ما با ابزار های 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 تنظیمات و گزینه های دیگه ای هم وجود داره که می تونید برای اطلاع بیشتر به ریپازیتوری پروژه مراجعه کنید :

aquasecurity/trivy
A Simple and Comprehensive Vulnerability Scanner for Containers, Suitable for CI - aquasecurity/trivy

اضافه کردن دو Job به Pipeline ها کار چندان سختی نیست ...سعی کنید با انجام دادنش پروژه های خودتون رو ایمن تر کنید. خودم از امروز به روزرسانی ها رو انجام میدم به تدریج :))