Bảo mật Infrastructure as Code với Checkov: Quét cấu hình sai và kiểm tra tuân thủ cho Terraform trong CI/CD

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Cái giá thực sự khi để lọt cấu hình cloud mất an toàn lên production

Quý trước, một kỹ sư trong đội ngũ của chúng tôi đã đẩy một module Terraform tạo AWS S3 bucket nhưng vô tình bật quyền đọc công khai (public read) và tắt mã hóa phía máy chủ (server-side encryption). Mọi thứ vẫn diễn ra êm đẹp khi chạy terraform apply: AWS API trả về mã 200 OK, và hạ tầng được cấp phát mà không có lấy một cảnh báo.

Mười bốn ngày trôi qua trước khi đội ngũ SecOps phát hiện ra bucket bị hở này trong một đợt audit SOC 2 định kỳ. Chúng tôi đã may mắn: khoảng 18 GB dữ liệu sao lưu cơ sở dữ liệu khách hàng bị phơi bày trên internet mà chưa có lượt truy cập trái phép nào. Dù vậy, sai sót này đã khiến chúng tôi mất hai đêm mất ngủ, một chu kỳ triển khai khẩn cấp và bốn giờ họp post-mortem đầy căng thẳng.

Kiểu sự cố này diễn ra phổ biến đến mức đáng báo động. Các đội ngũ áp dụng Infrastructure as Code (IaC) để bàn giao sản phẩm nhanh hơn. Thế nhưng, tốc độ mà thiếu đi các rào chắn bảo vệ thì chỉ đơn giản là tự động hóa sai lầm ở quy mô lớn hơn.

Các công cụ quét lỗ hổng truyền thống chỉ kiểm tra các gói hệ điều hành hoặc container đang chạy, chứ không thể phân tích các khai báo control-plane đám mây viết bằng HashiCorp Configuration Language (HCL). Việc khắc phục một security group mở toang trên môi trường production tiêu tốn trung bình 4.000 USD chi phí kỹ thuật để xử lý và xác minh. Trong khi đó, phát hiện đúng lỗi ngớ ngẩn ấy ngay trong pull request chỉ mất chưa đầy ba mươi giây.

Nguyên nhân cốt lõi: Vì sao mã IaC thiếu an toàn lại lọt vào nhánh main

Terraform mang tính khai báo thuần túy (strictly declarative). Nó đối soát trạng thái mong muốn của bạn với nhà cung cấp đám mây, nhưng không bao giờ đánh giá xem kiến trúc đó có an toàn hay không. Lệnh terraform validate mặc định chỉ kiểm tra cú pháp, các định nghĩa đối số bắt buộc và kiểu dữ liệu cơ bản. Nó sẽ vui vẻ phê duyệt một ingress rule mở cổng 22 cho 0.0.0.0/0 trên toàn bộ VPC của bạn, miễn là các dấu ngoặc và dấu nháy đúng chuẩn HCL.

Quy trình review code thủ công của con người cũng dễ thất bại dưới áp lực. Khi một pull request chạm đến 400 dòng Terraform trải dài trên năm module, người review sẽ rất nhanh bị quá tải và mệt mỏi. Các kỹ sư thường chỉ tập trung vào tag của module, cách đặt tên biến hay khoảng cách thụt dòng. Họ rất dễ bỏ sót các lỗ hổng bảo mật tinh vi, chẳng hạn như một ổ đĩa EBS 2 TB chưa được mã hóa hay một S3 bucket thiếu customer-managed key từ dịch vụ quản lý khóa (KMS). Tự động hóa chính sách dưới dạng mã (Policy-as-code) bắt buộc phải can thiệp trước khi bất kỳ pull request nào kịp merge vào nhánh main.

Các khái niệm cốt lõi: Cách Checkov thiết lập rào chắn bảo vệ

Checkov là một công cụ phân tích tĩnh (static analysis) mã nguồn mở được xây dựng chuyên biệt cho bảo mật IaC. Được duy trì bởi Prisma Cloud (ban đầu là Bridgecrew), nó phân tích các file cấu hình thành Cây Cú pháp Trừu tượng (AST – Abstract Syntax Tree). Sau đó, nó kiểm tra cây cú pháp này dựa trên hơn 1.000 chính sách có sẵn được ánh xạ trực tiếp theo các tiêu chuẩn CIS Benchmarks, NIST 800-53, HIPAA và PCI-DSS 4.0.

Khác với các công cụ quản lý trạng thái bảo mật đám mây (CSPM) quét ở runtime, Checkov không cần thông tin xác thực cloud đang hoạt động hay tài nguyên đã triển khai. Nó quét mã hoàn toàn offline. Mặc dù hỗ trợ cả Kubernetes manifest, CloudFormation, Bicep và ARM template, thế mạnh sâu nhất của Checkov vẫn là Terraform. Chạy Checkov cục bộ giúp phát hiện các cấu hình sai ngay trong IDE của bạn, từ rất lâu trước khi các thao tác khóa state (state lock) hay tạo tài nguyên thực sự diễn ra.

Thực hành thực tế: Bảo mật Terraform với Checkov

Dưới đây là quy trình từng bước: cài đặt Checkov cục bộ, kiểm thử với các định nghĩa Terraform có lỗ hổng, xử lý ngoại lệ một cách gọn gàng và thiết lập cổng kiểm duyệt tự động trên GitHub Actions.

Bước 1: Cài đặt Checkov

Checkov được viết bằng Python. Bạn có thể cài đặt thông qua pip, Homebrew hoặc container image chính thức. Hãy chọn cách phù hợp nhất với máy của bạn:

# Cài đặt qua Python pip
pip3 install checkov

# Hoặc cài đặt qua Homebrew (macOS/Linux)
brew install checkov

# Kiểm tra phiên bản cài đặt
checkov --version

Bước 2: Tạo file Terraform mẫu có cấu hình mất an toàn

Khởi tạo một thư mục trống tên là terraform-demo. Bên trong thư mục, tạo file main.tf chứa hai lỗi điển hình: một S3 bucket không được mã hóa, không có khối chặn truy cập công khai, và một ingress rule mở cổng SSH cho toàn thế giới.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

# Tài nguyên có lỗi: thiếu mã hóa, ghi log và chặn truy cập công khai
resource "aws_s3_bucket" "finance_reports" {
  bucket = "company-internal-finance-reports-2026"
}

# Tài nguyên có lỗi: mở cổng SSH 22 cho toàn cầu
resource "aws_security_group" "bastion_sg" {
  name        = "bastion-sg"
  description = "Security group cho bastion host"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Bước 3: Chạy lần quét đầu tiên

Chạy Checkov quét thư mục cục bộ của bạn:

checkov -d . --framework terraform

Chỉ trong vòng hai giây, Checkov sẽ in ra bảng tóm tắt đánh giá hiển thị các kiểm tra đạt và không đạt ngay trên terminal. Đối với file mẫu của chúng ta, công cụ sẽ gắn cờ cảnh báo ngay nhiều vi phạm:

  • CKV_AWS_20: S3 bucket cho phép quyền đọc công khai qua ACL hoặc policy.
  • CKV_AWS_145: S3 bucket không được mã hóa bằng customer-managed key của KMS (SSE-KMS).
  • CKV_AWS_24: Security group cho phép ingress toàn cầu từ 0.0.0.0/0 đến cổng 22.
  • CKV_AWS_53: S3 bucket chưa bật tính năng block_public_acls.

Mỗi cảnh báo đều cung cấp chính xác các dòng code vi phạm, mã định danh của kiểm tra thất bại và đường link trực tiếp hướng dẫn các bước khắc phục.

Bước 4: Khắc phục các lỗi được phát hiện

Các phiên bản AWS provider hiện đại (v4 và v5) đã tách các tính năng phụ của S3 bucket thành các resource độc lập riêng biệt. Hãy gia cố (harden) main.tf bằng cách siết chặt truy cập SSH về một IP văn phòng cụ thể (198.51.100.12/32), bổ sung mã hóa phía máy chủ và thiết lập các khối chặn truy cập công khai nghiêm ngặt:

resource "aws_s3_bucket" "finance_reports" {
  bucket = "company-internal-finance-reports-2026"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "finance_reports_crypto" {
  bucket = aws_s3_bucket.finance_reports.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_public_access_block" "finance_reports_block" {
  bucket = aws_s3_bucket.finance_reports.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_security_group" "bastion_sg" {
  name        = "bastion-sg"
  description = "Security group cho bastion host"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    # Giới hạn truy cập cho IP gateway của công ty
    cidr_blocks = ["198.51.100.12/32"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Chạy lại lệnh quét. Các cảnh báo nghiêm trọng sẽ biến mất ngay lập tức, trả về kết quả xanh sạch và an toàn.

Bước 5: Quản lý Baseline và các ngoại lệ hợp lệ

Việc đưa một công cụ quét tĩnh vào một codebase lâu năm có thể làm lộ ra hơn 300 cảnh báo lỗi ngay ngày đầu tiên. Chặn đứng mọi pull request chỉ sau một đêm sẽ khiến tốc độ bàn giao của cả đội ngũ bị đình trệ hoàn toàn. Checkov giải quyết bài toán tiến thoái lưỡng nan này bằng cơ chế baseline và bỏ qua cảnh báo ngay trong code (inline suppression).

Khi một ngoại lệ có lý do chính đáng—chẳng hạn như một bucket chứa tài nguyên tĩnh công khai để hiển thị logo sản phẩm—bạn có thể bỏ qua quy tắc kiểm tra ngay trong code kèm lý do rõ ràng:

resource "aws_s3_bucket" "public_assets" {
  bucket = "company-brand-static-cdn-assets"
  # checkov:skip=CKV_AWS_20:Bucket công khai dùng cho tài nguyên tĩnh của website
}

Đối với các codebase cũ (legacy), hãy ghi nhận các khoản nợ kỹ thuật (technical debt) hiện có mà không làm gián đoạn tiến độ phát triển mới:

# Lưu trữ các vi phạm hiện tại vào file baseline
checkov -d . --create-baseline

# Đảm bảo không phát sinh lỗi mới so với baseline đó
checkov -d . --baseline .checkov.baseline

Các cảnh báo cũ tồn đọng sẽ tiếp tục bị bỏ qua. Nhưng nếu một kỹ sư vô tình thêm vào một lỗi hoàn toàn mới, pipeline sẽ lập tức báo lỗi.

Bước 6: Tự động hóa Checkov trong GitHub Actions

Quét cục bộ phụ thuộc vào tính tự giác của lập trình viên. Pipeline CI sẽ biến việc thực thi chính sách trở thành bắt buộc. Hãy thêm workflow này tại .github/workflows/iac-security.yml để quét mọi pull request trỏ về nhánh main:

name: "Quét bảo mật IaC"

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  checkov-scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write

    steps:
      - name: Checkout mã nguồn
        uses: actions/checkout@v4

      - name: Chạy trình quét Checkov
        id: checkov
        uses: bridgecrewio/checkov-action@master
        with:
          directory: "."
          framework: "terraform"
          output_format: "cli,sarif"
          output_file_path: "console,results.sarif"
          soft_fail: false # Chặn pull request nếu có bất kỳ kiểm tra nào thất bại

      - name: Tải kết quả SARIF lên tab GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: "results.sarif"

Khi bật tính năng xuất định dạng SARIF, Checkov không chỉ dừng lại ở việc làm fail bản build. Nó còn chú thích chính xác các dòng code vi phạm ngay trong giao diện xem diff của pull request trên GitHub. Nhờ đó, lập trình viên có thể sửa lỗi ngay tại chỗ mà không cần phải bới tìm trong các dòng log console thô.

Shift Left để an tâm ngủ ngon

Khắc phục các món nợ bảo mật sau khi đã deploy vừa gây căng thẳng, tốn kém lại vừa tiềm ẩn nhiều rủi ro. Tích hợp Checkov vào vòng đời phát triển Terraform sẽ biến các bước kiểm tra an toàn thành một phần nhanh chóng, không gây cản trở trong quy trình review code. Hãy bắt đầu từ những bước nhỏ: chạy kiểm tra cục bộ cho các module cốt lõi, đóng băng các cảnh báo cũ bằng file baseline, và dựng các cổng kiểm soát trên CI để ngăn chặn những cấu hình sai mới lọt vào môi trường production.

Share: