Giới Thiệu
Chào các bạn! Bạn đã có một pipeline CI/CD hoạt động trơn tru, nhưng bạn có thể đang thiếu một số bước quét bảo mật cho mã nguồn của mình. Trong bài viết này, tôi sẽ chia sẻ hành trình xây dựng một pipeline bảo mật theo kiểu doanh nghiệp, bao gồm:
- Quét bí mật với GitGuardian và TruffleHog
- Báo cáo lỗ hổng bằng Bandit, Semgrep và Safety
- Quét lỗ hổng trong các phụ thuộc Python bằng Snyk
- Quét giấy phép và tuân thủ bằng FOSSA
- Quét bảo mật IaC với Checkov để tìm lỗ hổng trong Docker, Kubernetes và Terraform
- Quét bảo mật container bằng Trivy và Docker Scout
- Kiểm tra bảo mật động cho các endpoint API
Hãy cùng tôi tìm hiểu cách tôi thực hiện điều này, và quan trọng hơn, tại sao từng phần lại quan trọng nhé.
Bước Cơ Bản Nhưng Chưa Đủ
Hầu hết chúng ta bắt đầu với một số công việc như sau trong GitHub Actions:
yaml
- name: Chạy Bandit (SAST)
run: bandit -r .
- name: Quét Phụ Thuộc Snyk
uses: snyk/actions/python@master
- name: Quét Container Trivy
uses: aquasecurity/trivy-action@master
Điều này chỉ bao gồm các bước cơ bản - một số phân tích tĩnh, quét phụ thuộc và bảo mật container. Nhưng điều đó chưa đủ cho các ứng dụng thực tế. Bạn đang thiếu phát hiện bí mật, bảo mật hạ tầng, cổng chất lượng thích hợp và nhiều thứ khác có thể gây rắc rối sau này.
Lưu ý: Quét phụ thuộc Snyk có thể chậm nếu cây phụ thuộc của bạn lớn và bạn đang sử dụng tài khoản miễn phí.
Quy Trình Bảo Mật Nâng Cao:
Tôi đã tạo ra "quy trình bảo mật nâng cao" mà bao gồm hầu hết các khía cạnh quét bảo mật mà tôi có thể nghĩ đến. Hãy cùng đi sâu vào từng phần và hiểu tại sao mỗi phần lại quan trọng.
1. Phân Quyền Bảo Mật Trước Hết
yaml
permissions:
contents: read
security-events: write
actions: read
Tại sao điều này quan trọng: Mặc định, GitHub Actions nhận quá nhiều quyền. Đây là nguyên tắc quyền tối thiểu trong hành động - chỉ cấp những gì thực sự cần thiết. Quyền security-events: write cho phép chúng ta tải lên các báo cáo SARIF vào tab bảo mật của GitHub.
2. Phát Hiện Bí Mật
Đây có lẽ là bổ sung quan trọng nhất. Bạn có thể đã thấy các lập trình viên vô tình commit các khóa API, mật khẩu cơ sở dữ liệu hoặc thông tin đăng nhập AWS.
yaml
- name: Quét Bảo Mật GitGuardian
uses: GitGuardian/ggshield/actions/secret@v1.25.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
- name: Quét Bí Mật OSS TruffleHog
uses: trufflesecurity/trufflehog@main
with:
path: ./services/upload_service
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --debug --only-verified
Điều gì đang xảy ra ở đây:
- GitGuardian biết về 450 loại bí mật và có tỉ lệ dương tính giả rất thấp.
- TruffleHog là lựa chọn mã nguồn mở rất tốt.
- Cờ
--only-verifiednghĩa là nó chỉ cảnh báo về những bí mật mà nó thực sự có thể xác minh (như kiểm tra xem một khóa API có hoạt động hay không).
Mẹo: Chạy cả hai! GitGuardian có thể phát hiện điều gì đó mà TruffleHog bỏ lỡ và ngược lại.
Lưu ý: Một trong hai hoặc cả hai nên có trong hook pre-commit của bạn để phát hiện bí mật ở giai đoạn sớm nhất có thể.
3. SAST Nâng Cao (Kiểm Tra Bảo Mật Ứng Dụng Tĩnh)
Thay vì chỉ chạy Bandit, chúng ta sẽ thêm một vài công cụ nữa:
yaml
- name: Cài Đặt Công Cụ Bảo Mật
run: |
pip install bandit[toml] safety semgrep
- name: Chạy Bandit SAST (Nâng Cao)
working-directory: ./services/upload_service
run: |
bandit -r . -f json -o bandit-report.json || true
bandit -r . -f txt
continue-on-error: true
- name: Phân Tích Bảo Mật Semgrep
uses: semgrep/semgrep-action@v1
with:
config: >-
p/security-audit
p/python
p/owasp-top-ten
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- name: Kiểm Tra Safety (Phụ Thuộc Python)
working-directory: ./services/upload_service
run: safety check --json --output safety-report.json || true
Phân tích từng phần:
- Bandit vẫn là công cụ quét bảo mật đặc thù cho Python, nhưng bây giờ chúng ta lưu báo cáo cả ở định dạng JSON (để xử lý) và văn bản (để đọc bởi con người) - Lưu ý: Điều này sẽ chạy bandit hai lần, hãy điều chỉnh cho phù hợp.
- Semgrep là công cụ SAST mới - nó có các quy tắc cho OWASP Top 10, các vấn đề cụ thể của ngôn ngữ và các mẫu bảo mật chung.
- Safety kiểm tra các phụ thuộc Python của bạn với các cơ sở dữ liệu lỗ hổng đã biết.
Tại sao cần nhiều công cụ? Mỗi công cụ có điểm mạnh riêng. Bandit biết rất rõ về Python, Semgrep có phạm vi rộng hơn, và Safety tập trung cụ thể vào các phụ thuộc. Giống như có nhiều chuyên gia bảo mật quét mã của bạn. Một số người trong chúng ta có thể cho rằng việc này là thừa thãi, nhưng điều này giúp chúng ta hiểu, đánh giá và chọn ra sự kết hợp tốt nhất.
4. Bảo Mật Hạ Tầng Như Mã (Dockerfiles Cũng Quan Trọng)
yaml
- name: Quét Bảo Mật IaC Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: dockerfile,kubernetes,terraform
output_format: sarif
output_file_path: checkov-report.sarif
quiet: true
soft_fail: true
Đây là một bước rất quan trọng! Checkov quét các tệp Docker, các manifest Kubernetes, cấu hình Terraform - về cơ bản là bất kỳ hạ tầng nào bạn có dưới dạng mã. Nó sẽ phát hiện các vấn đề như:
- Chạy container với quyền root (không nên chút nào)
- Kiểm tra sức khỏe bắt buộc trong các container
- Thiếu bối cảnh bảo mật trong Kubernetes
- Chính sách IAM quá rộng rãi trong Terraform
- Bí mật được mã hóa cứng trong tệp Docker
Cờ soft_fail: true có nghĩa là nó sẽ không làm hỏng quá trình build, nhưng vẫn sẽ báo cáo các vấn đề.
5. Cổng Chất Lượng
Bước này quyết định xem quy trình làm việc có thất bại hay không. Thay vì chỉ chạy các quét và hy vọng ai đó đọc báo cáo, điều này thực hiện quyết định tự động:
python
def check_security_reports():
critical_issues = 0
high_issues = 0
# Kiểm tra báo cáo Bandit
try:
with open('services/upload_service/bandit-report.json') as f:
bandit_data = json.load(f)
for result in bandit_data.get('results', []):
if result['issue_severity'] == 'HIGH':
high_issues += 1
elif result['issue_severity'] == 'MEDIUM':
critical_issues += 1
except FileNotFoundError:
print("Báo cáo Bandit không tìm thấy")
# Logic cổng bảo mật
if critical_issues > 0:
print(f"❌ CỔNG BẢO MẬT THẤT BẠI: {critical_issues} vấn đề bảo mật nghiêm trọng được phát hiện")
sys.exit(1)
elif high_issues > 5:
print(f"⚠️ CẢNH BÁO: {high_issues} vấn đề nghiêm trọng được phát hiện")
else:
print("✅ CỔNG BẢO MẬT ĐÃ ĐƯỢC THÔNG QUA: Không phát hiện vấn đề bảo mật nghiêm trọng nào")
Đây là nơi phép màu xảy ra! Pipeline sẽ thực sự thất bại nếu có vấn đề bảo mật nghiêm trọng. Sửa chữa ngay hoặc việc triển khai của bạn sẽ không diễn ra.
Bạn có thể tùy chỉnh các ngưỡng này dựa trên mức rủi ro của mình. Có thể bạn cho phép 0 vấn đề nghiêm trọng trong sản xuất nhưng 3 trong các nhánh phát triển.
6. Bảo Mật Container
Chúng ta không chỉ quét hình ảnh cuối cùng nữa:
yaml
- name: Quét Hệ Thống Tệp Trivy
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: './services/upload_service'
- name: Quét Hình Ảnh Container Trivy (Nghiêm Trọng)
uses: aquasecurity/trivy-action@master
with:
image-ref: 'upload-service:latest'
exit-code: '1'
severity: 'CRITICAL,HIGH'
- name: Quét CVE Docker Scout
uses: docker/scout-action@v1
with:
command: cves
image-ref: upload-service:latest
only-severities: critical,high
Ba lớp bảo mật container:
- Quét hệ thống tệp - kiểm tra mã nguồn và các tệp
- Quét hình ảnh - quét hình ảnh Docker đã xây dựng để tìm lỗ hổng
- Docker Scout - quét bảo mật riêng của Docker (cơ sở dữ liệu lỗ hổng khác)
Cờ exit-code: '1' trên quét hình ảnh có nghĩa là nó sẽ làm thất bại quá trình build nếu phát hiện vấn đề nghiêm trọng hoặc cao.
7. Kiểm Tra Bảo Mật Động (Kiểm Tra Thời Gian Chạy)
yaml
- name: Khởi Động Ứng Dụng cho DAST
run: |
docker-compose up -d
sleep 30
curl -f http://localhost:8000/health || exit 1
- name: Quét API OWASP ZAP
uses: zaproxy/action-api-scan@v0.7.0
with:
target: 'http://localhost:8000'
format: 'openapi'
DAST (Kiểm Tra Bảo Mật Ứng Dụng Động) là nơi chúng ta thực sự chạy ứng dụng và kiểm tra nó để xem có lỗ hổng nào chỉ xuất hiện trong thời gian chạy hay không. OWASP ZAP giống như có một hacker thử nghiệm API của bạn để phát hiện các lỗ hổng web phổ biến.
Gia Vị Bí Mật: Tích Hợp SARIF
Bạn sẽ nhận thấy chúng ta đang xuất nhiều báo cáo ở định dạng SARIF:
yaml
- name: Tải Lên Các Báo Cáo SARIF Trivy
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: |
trivy-fs-results.sarif
trivy-image-results.sarif
SARIF (Định Dạng Trao Đổi Kết Quả Phân Tích Tĩnh) là định dạng chuẩn mà GitHub hiểu. Khi bạn tải lên các tệp SARIF, tất cả các phát hiện bảo mật của bạn sẽ xuất hiện một cách đẹp đẽ trong tab bảo mật của GitHub. Không còn phải đào bới qua các nhật ký build nữa!
Những Cạm Bẫy Thường Gặp và Cách Tránh Chúng
1. Dương Tính Giả
Mỗi công cụ bảo mật đều sản xuất các kết quả dương tính giả. Đây là cách xử lý chúng:
- Bắt đầu với
continue-on-error: truetrong khi bạn điều chỉnh các ngưỡng của mình. - Tạo tệp gỡ lỗi cho các dương tính giả đã biết.
- Sử dụng nhiều công cụ để xác minh chéo các phát hiện.
2. Quản Lý Bí Mật cho Các Công Cụ Bảo Mật
Bạn sẽ cần mã thông báo API cho hầu hết các công cụ này:
SNYK_TOKEN
GITGUARDIAN_API_KEY
SEMGREP_APP_TOKEN
FOSSA_API_KEY
SAFETY_API_KEY
Lưu trữ chúng dưới dạng bí mật GitHub, điều này là hiển nhiên. Hầu hết các công cụ đều có các gói miễn phí rất phù hợp để bắt đầu.
3. Ảnh Hưởng Đến Hiệu Suất
Quy trình làm việc này rất toàn diện nhưng cũng khá chậm. Đây là cách tối ưu hóa:
- Snyk đặc biệt chậm nếu bạn sử dụng tài khoản miễn phí.
- Chạy quét nặng chỉ trên các đẩy nhánh chính và PR.
- Sử dụng bộ nhớ cache cho các cài đặt công cụ.
- Chạy một số quét song song khi có thể.
4. Trải Nghiệm của Nhà Phát Triển
Không ai thích các pipeline thường xuyên bị hỏng. Hãy làm cho nó thân thiện với nhà phát triển:
- Thông báo lỗi rõ ràng trong các cổng chất lượng.
- Báo cáo bảo mật dễ tìm.
- Tài liệu hướng dẫn cách khắc phục các vấn đề phổ biến.
Tiếp Theo Là Gì?
Cài đặt này bao gồm hầu hết các kiểm tra bảo mật cốt lõi, và đây là một số bước để đưa nó đi xa hơn:
- Tự động khắc phục: Sử dụng Dependabot để tự động sửa các lỗ hổng phụ thuộc.
- Thông báo bảo mật: Tích hợp với Slack/Teams để nhận cảnh báo bảo mật.
- Chỉ số bảo mật: Theo dõi MTTR (Thời gian trung bình để khắc phục) và các sửa chữa bảo mật.
Kết Luận
Pipeline này không chỉ là việc thêm nhiều công cụ - mà là thực thi các chính sách. Quy trình này cung cấp cho các nhà phát triển phản hồi ngay lập tức về các vấn đề bảo mật trong khi vẫn duy trì tốc độ phát triển.
Điều này không hoàn hảo, nhưng bảo mật tốt hơn đáng kể hoàn toàn có thể đạt được với công cụ và quy trình đúng đắn. Bạn có thể chọn và điều chỉnh nó theo nhu cầu cụ thể của bạn, và từ từ nâng cao bảo mật của mình.
Mục tiêu không phải là làm chậm phát triển - mà là phát hiện các vấn đề sớm khi chúng dễ sửa chữa, thay vì trong sản xuất khi chúng đắt đỏ và xấu hổ.
Chúc bạn lập trình vui vẻ và triển khai nhanh chóng! 🚀