[ บันทึกช่วยจำ] มาตรวจสอบความปลอดภัยให้กับ Container Images บน Jenkins กันเถอะ #DevSecOps#
เมื่อก่อนหน้านี้ไม่กี่ปีที่ผ่านมีเรามักจะได้ยินคำว่า DevOps มาไม่มากก็น้อย ซึ่งหลายๆ องค์ก็ต้องการบุคลากรในส่วนนี้เข้ามาเสริมทัพเพื่อให้การพัฒนาซอฟแวร์ให้มีประสิทธิภาพที่ดีขึ้น แต่ ณ. ตอนนี้ก็ได้มีคำใหม่ที่เพิ่งจะได้ยินมาได้ไม่ได้นานนี้เองนั้นก็คือ DevSecOps ซึ่งนั้นก็คือเป็นการเพิ่มในมุมของความปลอดภายเพิ่มเข้ามาในทุกๆ ขั้นตอนการพัฒนาซอฟแวร์ เพื่อให้ซอฟแวร์ของเรานั้นมีคุณภาพ และปลอดกับผู้ใช้งานระบบด้วย
ในบทความนี้เป็นส่วนเล็กๆ ส่วนหนึ่งที่จะมาช่วยในการตรวจสอบความปลอดภัยในกับกระบวนการพัฒนาซอฟแวร์ โดยที่เราจะใช้อยู่บน CI/CD เลยโดยเราจะใช้งานอยู่บน Jenkins ซึ่งเครื่องมือที่เราจะนำมาใช้งานในการตรวจสอบ Conteriner Images นั้นเราจะใช้ Anchore
ซึ่งการทำนั้นจะประกอบไปด้วย 2 ส่วนหลักนั้นก็คือ
- Anchore Engine ซึ่งเป็นส่วนหลักของระบบในการตรวจสอบ และวิเคราะห์ Container ที่เราต้องการตรวจสอบ โดยสามารถเรียก CLI หรือผ่านทาง API ได้ ซึ่งตัว Engine นั้นจะประกอบไปด้วยหลาย Container ที่รันขึ้นมาโดยสามารถจะรันบน Container Engine แบบ Standalone, Swarm หรือ K8S ก็ได้ และแน่นอน Anchore Engine เป็น open-source project
- Anchore CLI ส่วนนี้จะเป็น command line interface สำหรับให้ผู้ใช้งานใช้สำหรับสั่งงานต่างๆ ไปที่ Anchore Engine
เตรียม Anchore Engine
ขั้นตอนที่ 1 — ทำการ clone โปรเจค Anchore Engin มา
$ git clone git@github.com:anchore/anchore-engine.git
$ cd anchore-engine\
ขั้นตอนที่ 2— หลังจากนั้นเราก็สั่งรัน docker-compose เลย
$ docker-compose up -dStarting anchore_db_1 ... done
Starting anchore_catalog_1 ... done
Starting anchore_api_1 ... done
Starting anchore_policy-engine_1 ... done
Starting anchore_analyzer_1 ... done
Starting anchore_queue_1 ... done
Attaching to anchore_db_1, anchore_catalog_1, anchore_queue_1, anchore_analyzer_1, anchore_api_1, anchore_policy-engine_1
db_1 |
db_1 | PostgreSQL Database directory appears to contain a database; Skipping initialization
db_1 |
db_1 | LOG: database system was shut down at 2020-10-18 09:45:18 UTC
db_1 | LOG: MultiXact member wraparound protections are now enabled
db_1 | LOG: database system is ready to accept connections
db_1 | LOG: autovacuum launcher started
หมายเหตุ โดยตัวอย่างนี้ผู้เขียนจะรันบน docker-compose บนเครื่อง macOS และตั้งติดตั้ง Docker Engine และ Docker Compose ให้เรียบร้อบ
ขั้นตอนที่ 3— ทดสอบรองเรียก API เบื้องต้นดังรูปข้างล่าง
เพียงนี้ Anchore Engin ก็พร้อมใช้งานแล้ว
ทดสอบการทำงานด้วย Anchore CLI
ขั้นตอนที่ 1— สร้างเมื่อสั่งรัน Anchore Engine แล้วเราก็มาลองติดตั้ง Anchore CLI ต่อ ทำการ clone โปรเจค
$ git clone git@github.com:anchore/anchore-cli.git
$ cd anchore-cli\
ขั้นตอนที่ 2— ทำการติดตั้ง Anchore CLI ผ่าน pip
$ pip install --user --upgrade anchorecliRequirement already up-to-date: anchorecli in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (0.8.2)
Requirement already satisfied, skipping upgrade: Click==7.0 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (7.0)
Requirement already satisfied, skipping upgrade: six==1.14.0 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (1.14.0)
Requirement already satisfied, skipping upgrade: python-dateutil==2.8.1 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (2.8.1)
Requirement already satisfied, skipping upgrade: prettytable==0.7.2 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (0.7.2)
Requirement already satisfied, skipping upgrade: urllib3==1.25.9 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (1.25.9)
Requirement already satisfied, skipping upgrade: PyYAML==5.3.1 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (5.3.1)
Requirement already satisfied, skipping upgrade: requests==2.23.0 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from anchorecli) (2.23.0)
Requirement already satisfied, skipping upgrade: certifi>=2017.4.17 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from requests==2.23.0->anchorecli) (2019.3.9)
Requirement already satisfied, skipping upgrade: idna<3,>=2.5 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from requests==2.23.0->anchorecli) (2.10)
Requirement already satisfied, skipping upgrade: chardet<4,>=3.0.2 in /Users/kritsadanshon.s/Library/Python/2.7/lib/python/site-packages (from requests==2.23.0->anchorecli) (3.0.4)
หมายเหตุ ในเครื่องต้องทำการติดตั้ง python และ pip ให้เรียบร้อย
ขั้นตอนที่ 3 — ตรวจสอบการสถานะระบบ
$ anchore-cli --url http://localhost:8228/v1 --u admin --p foobar system statusService analyzer (anchore-quickstart, http://analyzer:8228): up
Service catalog (anchore-quickstart, http://catalog:8228): up
Service simplequeue (anchore-quickstart, http://queue:8228): up
Service apiext (anchore-quickstart, http://api:8228): up
Service policy_engine (anchore-quickstart, http://policy-engine:8228): upEngine DB Version: 0.0.13
Engine Code Version: 0.8.1
หมายเหตุ ค่าเริ่มต้นของ Username และ Password จะเป็น admin, foobar
ขั้นตอนที่ 4— ทดสอบเพิ่ม Container Images เข้าไปทำการตรวจสอบความปลอดภัย
$ anchore-cli --url http://localhost:8228/v1 --u admin --p foobar image add nginx:latestImage Digest: sha256:4949aa7259aa6f827450207db5ad94cabaa9248277c6d736d5e1975d200c7e43
Parent Digest: sha256:ed7f815851b5299f616220a63edac69a4cc200e7f536a56e421988da82e44ed8
Analysis Status: not_analyzed
Image Type: docker
Analyzed At: None
Image ID: f35646e83998b844c3f067e5a2cff84cdf0967627031aeda3042d78996b68d35
Dockerfile Mode: None
Distro: None
Distro Version: None
Size: None
Architecture: None
Layer Count: NoneFull Tag: docker.io/nginx:latest
Tag Detected At: 2020-10-18T10:05:55Z
ขั้นตอนที่ 5— ตรวจสอบสถานะของการตรวจสอบ Container Images ว่ามีการ analyzed แล้วหรือยัง
$ anchore-cli --url http://localhost:8228/v1 --u admin --p foobar image listFull Tag Image Digest Analysis Status
docker.io/nginx:latest sha256:4949aa7259aa6f827450207db5ad94cabaa9248277c6d736d5e1975d200c7e43 analyzing
ขั้นตอนที่ 6 — แสดงผลลัพธ์ในการตรวจสอบความปลอดภัย
$ anchore-cli --url http://localhost:8228/v1 --u admin --p foobar image vuln nginx:latest allVulnerability ID Package Severity Fix CVE Refs Vulnerability URL Type Feed Group Package Path
CVE-2011-3389 libgnutls30-3.6.7-4+deb10u5 Medium None CVE-2011-3389 https://security-tracker.debian.org/tracker/CVE-2011-3389 dpkg debian:10 pkgdb
CVE-2004-0971 libgssapi-krb5-2-1.17-3 Negligible None CVE-2004-0971 https://security-tracker.debian.org/tracker/CVE-2004-0971 dpkg debian:10 pkgdb.
.
.CVE-2020-13776 libudev1-241-7~deb10u4 Negligible None CVE-2020-13776 https://security-tracker.debian.org/tracker/CVE-2020-13776 dpkg debian:10 pkgdb
CVE-2020-15719 libldap-2.4-2-2.4.47+dfsg-3+deb10u2 Negligible None CVE-2020-15719 https://security-tracker.debian.org/tracker/CVE-2020-15719 dpkg debian:10 pkgdb
CVE-2020-15719 libldap-common-2.4.47+dfsg-3+deb10u2 Negligible None CVE-2020-15719 https://security-tracker.debian.org/tracker/CVE-2020-15719 dpkg debian:10 pkgdb
เพียงเท่านั้น Anchore Engine ก็สามารถงานได้แล้ว
ขั้นตอนที่ 7 — ลองดูผลลัพธ์ภาพรวมของ Container Image ว่าสถานะเป็น pass หรือไม่
$ anchore-cli --url http://localhost:8228/v1 --u admin --p foobar evaluate check nginx:latestImage Digest: sha256:4949aa7259aa6f827450207db5ad94cabaa9248277c6d736d5e1975d200c7e43
Full Tag: docker.io/nginx:latest
Status: pass
Last Eval: 2020-10-18T10:12:12Z
Policy ID: 2c53a13c-1765-11e8-82ef-23527761d060
ตั้งค่าบน Jenkins
ขั้นตอนที่ 1 — ล็อคอินเข้า Console Jenkins เพื่อที่จะเข้าไปติดตั้งไปติดตั้ง plugin Anchore Container Image Scanner โดยให้ไปที่ Manage Jenkins > Manage Plugins
ขั้นตอนที่ 2 — สร้าง Config ในส่วนของ Anchore Container Image Scanner เพื่อให้ไปเรียกใช้งาน Anchore Engine โดยให้ไปที่ Manage Jenkins > Configure System
หมายเหตุ ในตัวอย่างทางผู้เขียนได้ติดตั้ง Anchore Engine อยู่ในเครื่องเดียวกัน หากผู้อ่านติดตั้งอยู่ที่เครื่องให้ทำการเปลี่ยนเป็น IP Adress หรือชื่อเครื่องที่เราติดตั้ง Anchire Engine
ขั้นตอนที่ 3 — สร้าง Job สำหรับในการตรวจสอบ Container Images โดยเราสามารถเลือก Add build step ที่ชื่อว่า Anchore Container Image Scanner
โดยค่าที่สำนั้นก็คือ Image list file ที่ตัวบอกว่าจะให้ตรวจสอบ image อะไรบ้าง
โดยเราสามารถระบบรายชื่อ image เข้าไปโดยการเพิ่ม step ที่ชื่อว่า Execute shell ก่อน step Anchore Container Image Scanner
echo "nginx:latest" > anchore_images
echo "kritsadanshon/tgr-mgr-db" >> anchore_images
หรือหากเป็น Job ที่มีการ build image ด้วยก็สามารถเพิ่มตามตัวอย่างข้างล่างได้เลย
TAG=$(date "+%H%M%S%d%m%Y")
IMAGENAME=build.example.com/myapp
docker build -t $IMAGENAME:$TAG .
docker push $IMAGENAME:$TAG
# Line added to create anchore_images file
echo "$IMAGENAME:$TAG ${WORKSPACE}/Dockerfile " > anchore_images
หน้าตา step จะออกมาประมาณนี้
ขั้นตอนที่ 4— ตรวจสอบผลการตรวจสอบ และรายละเอียดความปลอดภัยต่างๆ
โดยผลลัพธ์จะมีหลักๆ 2 แบบดังนี้
- SUCCESS สัญญาลักษณ์จเป็นวงกลมสีน้ำเงินหมายถึง Job นั้นได้มีการสแกนแล้วพบระดับความเสี่ยงตั้งแต่ Medium ลงไป
- FAILURE สัญญาลักษณ์จเป็นวงกลมสีแดงหมายถึง Job นั้นได้มีการสแกนแล้วพบระดับความเสี่ยงตั้งแต่ High ขึ้นมา
อีกทั้งหน้าแรกของ Job จะแสดงข้อมูล Trend แสดงเป็นกราฟโดยสีแดงคือจำนวนความเสี่ยงระดับ High จนถึง Critical และสีเหลืองคือจำนวนความเสี่ยงระดับ Low จึนถึง Medium
และเมื่อเราเข้ามาที่เมนู Anchore Report จะพบรายละเอียดว่า Container Images ตัวในมีระดับความเสี่ยงต่างๆ อยู่เท่าไร และรายละเอียดความเสี่ยง พร้อมทั้งลิงค์ที่ CVE ของแต่ละตัวด้วย
เพียงเท่านั้นเราก็สามารถนำไปเงื่อนไข Pipeline ได้แล้วว่าหากการตรวจสอบความปลอดภัยไม่ผ่านก็ทำอะไรต่อ
แน่นอนบทความนี้เป็นเพียงแค่พื้นฐานการใช้งาน เครื่องมือนี้จะมีลูกเล่นอีกหลายส่วนที่ต้องเรียนรู้ และหัดใช้งานอยู่อีกมาก หวังผู้ที่หลงเข้ามาอ่านจะสามารถนำไปประยุกค์ใช้ภายในองค์ได้ครับ
สุดท้ายแล้วหากท่านไหนหลงเข้ามาอ่านแล้วเห็นเป็นประโยชน์ก็สามารถนำไปต่อยอดได้เลย หรือหากมีคำแนะนำดีๆ ก็สามารถบอกกล่าวให้ทราบได้เช่นกันครับ
Ref: https://anchore.com/
Ref: https://github.com/anchore/anchore-engine