Cái giá của một dòng cấu hình sai
Tôi vẫn còn nhớ một cảnh báo PagerDuty lúc 3 giờ sáng năm 2021. Một kỹ sư trẻ đã vô tình triển khai một S3 bucket với quyền truy cập công khai (public read access). Đó không phải là một sai lầm liều lĩnh—chỉ là một thiết lập mặc định trong một module Terraform cộng đồng đã bị bỏ sót khi review. Chỉ trong vòng 15 phút, các trình quét tự động đã tìm thấy endpoint này. Chúng tôi đã tránh được một vụ rò rỉ dữ liệu chỉ nhờ may mắn, nhưng đó là một bài học cảnh tỉnh. Bảo mật không thể là ‘bước kiểm tra cuối cùng’ được thực hiện mỗi tháng một lần; nó phải được lồng ghép vào từng lần commit.
Khi chúng ta mở rộng quy mô với Infrastructure as Code (IaC), sai sót của con người cũng tăng theo. Dù bạn đang quản lý môi trường AWS bằng Terraform hay điều phối các cụm máy chủ với Helm, chỉ một thuộc tính bị thiếu cũng có thể làm lộ toàn bộ hệ thống của bạn. Việc review thủ công rất có giá trị, nhưng chúng không thể đáp ứng được hàng ngàn dòng code và chắc chắn không thể đảm bảo không có sai sót.
Tại sao IaC của chúng ta thường không an toàn theo mặc định
Các sai sót cấu hình thường bắt nguồn từ ba yếu tố áp lực chính. Đầu tiên, các nhà cung cấp đám mây ưu tiên ‘tốc độ làm quen’ (onboarding velocity). Họ muốn bạn thấy kết quả trong vòng năm phút, điều này thường dẫn đến các quyền truy cập mở rộng và vô hiệu hóa mã hóa trong các template ‘Quick Start’ của họ.
Thứ hai, khối lượng cấu hình hiện đại là quá lớn. Một kiến trúc microservices điển hình có thể bao gồm hơn 5.000 dòng mã YAML và HCL (HashiCorp Configuration Language). Kỳ vọng một người review đang mệt mỏi phát hiện ra việc thiếu allow_privileged_escalation: false nằm sâu trong một manifest Kubernetes là điều phi thực tế.
Cuối cùng là khoảng cách về kiến thức đang ngày càng lớn. Hầu hết các kỹ sư DevOps là chuyên gia về điều phối nhưng không nhất thiết phải là nhà nghiên cứu bảo mật. Theo kịp mọi CVE mới hay các tiêu chuẩn CIS cho hàng chục dịch vụ đám mây là một công việc toàn thời gian mà hầu hết các đội ngũ không thể chi trả.
So sánh các công cụ quét: Tại sao lại chọn Checkov?
Khi tôi đánh giá các công cụ để tự động hóa việc này, tôi đã xem xét TFSec, Terrascan, và KICS. Mặc dù mỗi công cụ đều có ưu điểm riêng, tôi đã chuẩn hóa việc sử dụng Checkov vì bốn lý do chính:
- Hỗ trợ hệ sinh thái rộng lớn: Nó xử lý nhiều thứ hơn là chỉ Terraform. Nó quét được cả Kubernetes, CloudFormation, Bicep, ARM template và thậm chí cả Dockerfile.
- Thư viện chính sách khổng lồ: Nó đi kèm with hơn 1.000 chính sách tích hợp sẵn được đối chiếu với các tiêu chuẩn ngành như CIS và NIST.
- Khả năng mở rộng dựa trên Python: Việc viết logic tùy chỉnh bằng Python trực quan hơn nhiều đối với hầu hết các đội ngũ so với việc học một ngôn ngữ đặc thù (DSL) của một công cụ cụ thể.
- Phân tích dựa trên biểu đồ: Không giống như các công cụ tìm kiếm văn bản đơn giản, Checkov hiểu được mối quan hệ giữa các tài nguyên. Nó biết liệu một security group cụ thể có thực sự được gắn vào một instance hay không, từ đó giảm thiểu các cảnh báo giả (false positives).
Một workflow tốt hơn: Tích hợp Checkov
Mục tiêu không chỉ là tạo ra một báo cáo; mà là tạo ra một vòng lặp phản hồi để ngăn chặn code lỗi trước khi nó được merge. Tôi đề xuất một chiến lược phân tầng: kiểm thử cục bộ, pre-commit hooks và thực thi trong CI/CD.
1. Kiểm thử cục bộ và cài đặt
Việc bắt đầu chỉ mất chưa đầy một phút. Tôi thích sử dụng trình quản lý gói của Python, mặc dù Docker image là lựa chọn lý tưởng để giữ cho môi trường cục bộ của bạn luôn sạch sẽ.
# Cài đặt qua pip
pip install checkov
# Hoặc chạy qua Docker
docker run -v $(pwd):/tf bridgecrew/checkov -d /tf
Chạy một lượt quét cho thư mục Terraform hiện tại của bạn. Nếu bạn thấy một loạt văn bản màu đỏ, đừng hoảng sợ. Điều này là bình thường. Hầu hết các dự án đang chạy đều tích tụ các nợ kỹ thuật (technical debt) cần được giải quyết dần dần.
checkov -d ./terraform_project
2. Bảo mật các Manifest Kubernetes
Một trong những tính năng mạnh mẽ nhất của Checkov là khả năng phát hiện các cấu hình Kubernetes ‘cẩu thả’. Rất dễ để quên giới hạn tài nguyên hoặc để container chạy dưới quyền root. Bạn có thể quét toàn bộ thư mục chứa các file YAML chỉ với một câu lệnh:
checkov -d ./k8s_manifests --framework kubernetes
Checkov sẽ ngay lập tức gắn cờ các vấn đề rủi ro cao, chẳng hạn như:
- Các container chạy với
privileged: true. - Thiếu các liveness và readiness probe gây ảnh hưởng đến tính sẵn sàng.
- Các pod không có giới hạn CPU/Memory, thường dẫn đến vấn đề ‘hàng xóm ồn ào’ (noisy neighbor) trong các cụm cluster dùng chung.
3. Thực thi tự động trong CI/CD
Đây là lúc việc tự động hóa phát huy hiệu quả. Nếu một cấu hình không vượt qua được bài quét bảo mật, quá trình build sẽ dừng lại. GitHub Actions là cách đơn giản nhất để thực thi việc này. Dưới đây là một đoạn mã sẵn sàng cho môi trường production:
name: Quét Bảo mật IaC
on: [push, pull_request]
jobs:
checkov-job:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Chạy Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: terraform/
framework: terraform
soft_fail: false # Chặn PR nếu các kiểm tra bảo mật thất bại
output_format: cli
download_external_modules: true
Với thiết lập này, bất kỳ Pull Request nào gây ra lỗ hổng bảo mật đều bị chặn. Điều này buộc các nhà phát triển phải sửa lỗ hổng hoặc cung cấp giải trình được ghi chép lại trước khi code được đưa lên production.
Những bài học từ thực tế
Sau khi triển khai Checkov cho hàng chục dự án doanh nghiệp, tôi nhận thấy rằng phương pháp ‘bật tất cả mọi thứ’ thường thất bại do sự mệt mỏi vì cảnh báo (alert fatigue). Đây là cách để triển khai nó thành công.
Chuẩn hóa bằng file cấu hình
Đừng phụ thuộc vào các cờ CLI dài dòng. Hãy tạo một file .checkov.yaml trong thư mục gốc. Điều này đảm bảo mọi nhà phát triển và trình chạy CI/CD đều sử dụng các quy tắc giống hệt nhau, loại bỏ các vấn đề bảo mật kiểu ‘chạy ổn trên máy tôi’.
# .checkov.yaml
directory:
- terraform
- k8s
skip-check:
- CKV_AWS_144 # Ví dụ: Việc mã hóa S3 được xử lý bởi một chính sách chung của tổ chức
soft-fail: false
output: cli
Xử lý các trường hợp ngoại lệ một cách khéo léo
Các quy tắc bảo mật không phải lúc nào cũng áp dụng cho mọi trường hợp. Thay vì vô hiệu hóa một quy tắc trên toàn hệ thống, hãy sử dụng các comment nội dòng để bỏ qua nó cho một tài nguyên cụ thể. Tôi luôn yêu cầu một comment ‘Lý do’ để duy trì dấu vết kiểm tra (audit trail) cho các lần review sau này.
# terraform
resource "aws_security_group" "bastion" {
# checkov:skip=CKV_AWS_24: "Đảm bảo không có security group nào cho phép 0.0.0.0/0 truy cập vào cổng 22"
# Lý do: Đây là một máy chủ bastion công cộng đã được gia cố đặc biệt để truy cập SSH khẩn cấp
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Triển khai theo từng giai đoạn
Nếu bạn quét một dự án cũ lần đầu tiên, bạn có thể thấy hơn 500 lỗi. Đừng cố gắng sửa tất cả trong một sprint. Hãy sử dụng cờ --check để chỉ tập trung vào các vấn đề có mức độ nghiêm trọng ‘Critical’ và ‘High’ trước. Khi các lỗi ‘Critical’ đã về 0, bạn có thể dần dần nâng mức tiêu chuẩn để bao gồm cả các kiểm tra mức ‘Medium’ và ‘Low’.
checkov -d . --check CRITICAL,HIGH
Lời kết
Bảo mật hạ tầng là một cuộc chạy marathon, không phải là một cuộc chạy nước rút. Bằng cách sử dụng Checkov, bạn loại bỏ các phỏng đoán và cung cấp cho đội ngũ của mình những phản hồi tức thì và có thể hành động được. Bạn không chỉ đang quét code; bạn đang xây dựng một văn hóa nơi bảo mật được coi trọng như logic ứng dụng. Hãy bắt đầu từ việc nhỏ, chặn các lỗi ‘Critical’ trong pipeline và ngủ ngon hơn khi biết rằng các thiết lập mặc định của đám mây không để cửa mở toang cho kẻ xấu.

