Skip to content

Continuous Validation: Kiểm Soát Compliance Cho Running Pods

Tại sao quan trọng trong production

Deployment-time enforcement (ValidatingAdmissionWebhook) chỉ chặn tại một điểm: lúc Pod được tạo. Nhưng có những kịch bản mà enforcement tại deploy-time là chưa đủ:

  1. Policy thay đổi sau khi Pod đã chạy: Thêm yêu cầu mới vào policy không ảnh hưởng gì đến Pods đang chạy từ trước đó. Một cluster có thể chạy hàng trăm Pods được deploy theo policy cũ lỏng lẻo hơn.

  2. Image bị phát hiện có vulnerability sau khi deploy: CVE mới được tìm thấy trong image đang chạy. Enforcement tại deploy-time không biết về CVE này — nó đã pass. Cần cơ chế detect và alert tình trạng này.

  3. Key attestation bị revoke: Signing key bị compromise → tất cả attestations được ký bằng key này không còn valid. Enforcement tại deploy-time không re-evaluate attestations của Pods đang chạy.

  4. Image freshness: Image quá cũ (vài tháng không update) có thể chứa các vulnerability đã được fix trong phiên bản mới. Deploy-time enforcement không kiểm tra "image này có quá cũ không".

Continuous Validation (CV) được thiết kế để giải quyết tất cả các khoảng trống này.


Internal Model: Cơ Chế CV Hoạt Động Như Thế Nào

Architecture Tổng Quan

CV là một dịch vụ ngoài cluster — không chạy trong GKE cluster mà là một managed service của Google Cloud. Nó tương tác với cluster qua Cloud Asset Inventory (CAI) feed để nhận thông tin về Pods đang chạy.

┌─────────────────────────────────────────────────────────┐
│  GKE Cluster                                            │
│  ┌─────────┐   ┌─────────┐   ┌─────────┐              │
│  │  Pod A  │   │  Pod B  │   │  Pod C  │              │
│  └────┬────┘   └────┬────┘   └────┬────┘              │
│       └──────────────┴──────────────┘                   │
│                      │                                   │
│               (CAI feed export)                          │
└──────────────────────┼──────────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│  Cloud Asset Inventory                                  │
│  Feed: binauthz-cv-cai-feed                             │
└──────────────────────┬──────────────────────────────────┘


┌─────────────────────────────────────────────────────────┐
│  Binary Authorization CV Service                        │
│                                                         │
│  Every ≥24h:                                            │
│  1. Get running pods from CAI feed                      │
│  2. Extract container image digests                     │
│  3. Evaluate against platform policy                    │
│  4. Log violations to Cloud Logging                     │
└─────────────────────────────────────────────────────────┘

CAI feed: CV tạo một resource binauthz-cv-cai-feed khi được enable. Feed này export thông tin về Pod objects từ cluster sang Cloud Asset Inventory. CV đọc từ feed này để biết Pods nào đang chạy và images nào đang được dùng.

Chu Kỳ Evaluation

Theo Google Cloud documentation: "CV reviews images associated with each Pod at least every 24 hours."

"At least every 24 hours" là ngưỡng tối thiểu — trong thực tế có thể xảy ra thường xuyên hơn tùy thuộc vào tải hệ thống. Không có SLA về thời gian tối đa giữa các lần evaluation, nhưng Google đảm bảo ít nhất một lần trong 24 giờ.

Điểm quan trọng: CV không phải real-time monitoring. Nếu một image bị compromise và CV vừa chạy xong vài phút trước, sẽ có khoảng trống lên đến 24 giờ trước khi CV detect. Đây là trade-off giữa monitoring frequency và cost.

CV vs Enforcement: Sự Khác Biệt Cơ Bản

Khía cạnhDeploy-time EnforcementContinuous Validation
Khi nào chạyLúc tạo Pod (CREATE webhook)Định kỳ (≥24h) cho Pods đang chạy
Loại policyProject-singleton policyPlatform policies (check-based)
Số policy per project1Nhiều
Hành động khi vi phạmBlock deploymentChỉ log — không evict
ScopeGKE, Cloud Run, GDCGKE only
Tag supportCó (resolve sang digest)Không — chỉ digest

CV chỉ log, không evict — đây là điểm then chốt. CV không terminate Pods vi phạm. Nó chỉ ghi violation vào Cloud Logging. Lý do thiết kế này:

  1. Tránh gián đoạn production: Auto-eviction của running Pod là hành động nghiêm trọng, dễ gây outage nếu nhiều Pods vi phạm cùng lúc
  2. Cho phép graceful remediation: Operator nhận notification, review, và quyết định hành động phù hợp
  3. Separation of detection và response: CV detect, operator respond

Tag Không Được Hỗ Trợ Trong CV

CV chỉ xử lý image digests. Với Pods dùng tag (image: myapp:v1.2.3), CV cố gắng resolve tag sang digest; nếu resolve thất bại → đây được coi là policy violation (CV không thể verify gì nếu không có digest).

Đây là thêm một lý do để enforce digest pinning trong Kubernetes manifests — CV hoạt động correctly chỉ khi digest được pin.


Platform Policies vs Project-Singleton Policies

Sự Khác Biệt Về Cấu Trúc

Binary Authorization có hai loại policy khác nhau:

Project-singleton policy (dùng cho deploy-time enforcement):

  • Mỗi project có đúng một
  • URI: projects/{PROJECT_ID}/policy
  • Format: YAML với admissionWhitelistPatterns, defaultAdmissionRule, clusterAdmissionRules
  • Chứa evaluationModerequireAttestationsBy

Platform policies (dùng cho CV):

  • Mỗi project có thể có nhiều
  • URI: projects/{PROJECT_ID}/platforms/{PLATFORM}/policies/{POLICY_ID}
  • Format: Check-based với gkePolicy.checkSets
  • Linh hoạt hơn: per-namespace, per-service-account scoping
  • Hỗ trợ nhiều loại checks (attestation, vulnerability, SLSA, v.v.)

Lưu ý: Legacy CV dùng project-singleton policy đã bị deprecated từ tháng 4/2024 và sẽ không còn support từ tháng 5/2025. Mọi implementation CV mới phải dùng platform policies.

Cấu Trúc Platform Policy

yaml
# platform_policy.yaml
name: "projects/my-project/platforms/gke/policies/production-cv-policy"
description: "Continuous validation for production GKE clusters"
gkePolicy:
  checkSets:
  # Default check set — áp dụng cho tất cả namespaces
  - displayName: "Default production checks"
    checks:
    - displayName: "Require security scan attestation"
      simpleSigningAttestationCheck:
        containerAnalysisAttestationProjects:
        - "projects/my-project"
        attestationAuthenticators:
        - pkixPublicKeySet:
            pkixPublicKeys:
            - publicKeyPem: |
                -----BEGIN PUBLIC KEY-----
                MFkwEwYH...
                -----END PUBLIC KEY-----
              signatureAlgorithm: ECDSA_P256_SHA256
    - displayName: "Image freshness check"
      imageFreshnessCheck:
        maxUploadAgeDays: 90
    - displayName: "Vulnerability check"
      vulnerabilityCheck:
        maximumFixableSeverity: MEDIUM
        maximumUnfixableSeverity: HIGH

  # Check set scope to specific namespace
  - displayName: "Strict checks for payment namespace"
    scope:
      kubernetesNamespace: "payment"
    checks:
    - displayName: "Require SLSA provenance"
      slsaCheck:
        rules:
        - trustedBuilder:
            googleCloudBuild:
              projectIds:
              - "my-project"
        preferConfigBasedInstructions: true

Check Set Scoping

Check sets có thể scope đến:

  • Cluster-wide default: Không có scope field → áp dụng cho tất cả Pods
  • Namespace-specific: scope.kubernetesNamespace: "payment" → chỉ áp dụng cho namespace payment
  • Service account-specific: scope.kubernetesServiceAccount: "namespace/sa-name"

Giới hạn: Chỉ được có một cluster-wide default check set và một check set per namespace/service account. Không thể có 2 default check sets trong cùng một platform policy.


Sáu Loại Checks Trong CV

1. Simple Signing Attestation Check

Verify rằng image có attestation hợp lệ được ký bởi PKIX key. Đây là check tương đương với deploy-time REQUIRE_ATTESTATION nhưng trong context CV.

yaml
simpleSigningAttestationCheck:
  containerAnalysisAttestationProjects:
  - "projects/attestation-project"  # nơi lưu attestations
  attestationAuthenticators:
  - pkixPublicKeySet:
      pkixPublicKeys:
      - publicKeyPem: |
          -----BEGIN PUBLIC KEY-----
          ...
          -----END PUBLIC KEY-----
        signatureAlgorithm: ECDSA_P256_SHA256

Cách hoạt động: CV query Artifact Analysis trong containerAnalysisAttestationProjects để tìm attestations cho image digest. Verify signature bằng các public keys trong pkixPublicKeySet. Image thỏa mãn check nếu bất kỳ key nào trong bất kỳ authenticator nào verify được.

Tại sao "any key" thay vì "all keys"? Cho phép key rotation graceful: trong quá trình rotation, image signed bởi key cũ vẫn valid cho đến khi tất cả images được re-signed với key mới.

2. Image Freshness Check

Kiểm tra xem image có được upload vào registry trong khoảng thời gian chỉ định không. Dùng timestamp upload của image (không phải timestamp build).

yaml
imageFreshnessCheck:
  maxUploadAgeDays: 90  # image phải được upload trong vòng 90 ngày

Cơ chế: CV query Artifact Registry metadata để lấy uploadTime của image. Nếu now - uploadTime > maxUploadAgeDays → violation.

Tại sao dùng upload time? Đây là timestamp bất biến sau khi push. Build time dễ bị giả mạo (set bởi Dockerfile hoặc build config). Upload time được lưu bởi Artifact Registry infrastructure.

Use case: Đảm bảo cluster không chạy image quá cũ có chứa security vulnerabilities đã được fix. Kết hợp với auto-remediation để trigger rebuild khi image sắp hết hạn.

3. SLSA Check

Verify SLSA provenance metadata của image, đảm bảo image được build từ trusted source bởi trusted builder.

yaml
slsaCheck:
  rules:
  - trustedBuilder:
      googleCloudBuild:
        projectIds:
        - "my-ci-project"   # chỉ accept builds từ project này
    trustedSourceCodeRepository:
      repoPattern: "https://github.com/my-org/**"  # optional
    preferConfigBasedInstructions: true  # đảm bảo build dùng cloudbuild.yaml

Cơ chế: CV query Artifact Analysis cho SLSA provenance occurrences (kind: BUILD). Verify:

  • builder.id là Cloud Build trong project được chỉ định
  • Nếu preferConfigBasedInstructions: true → build phải dùng config file (cloudbuild.yaml), không phải inline steps
  • Nếu trustedSourceCodeRepository được set → source phải match pattern

Vì sao preferConfigBasedInstructions quan trọng? Build steps được define trong cloudbuild.yaml được review và version control. Inline steps trong trigger UI dễ bị modify mà không có audit trail. Với option này, tất cả build logic phải đi qua code review.

4. Sigstore Signature Check

Verify chữ ký Sigstore trên image. Sigstore là alternative signing framework so với PKIX, dùng keyless signing (signature được tạo bằng OIDC token thay vì long-lived key).

yaml
sigstoreSignatureCheck:
  sigstoreAuthorities:
  - displayName: "GitHub Actions"
    publicKeySet:
      publicKeys:
      - publicKeyPem: |
          -----BEGIN PUBLIC KEY-----
          ...
          -----END PUBLIC KEY-----

Cơ chế: Verify chữ ký Sigstore (Rekor transparency log entries) gắn với image trong Artifact Registry. Image thỏa mãn nếu có valid Sigstore signature từ bất kỳ key nào trong danh sách.

Khác PKIX how? Sigstore/Cosign hướng đến keyless signing — CI system (GitHub Actions, Cloud Build) sign bằng OIDC ephemeral credential thay vì long-lived private key. Không cần manage private key, nhưng cần trust OIDC identity provider.

5. Trusted Directory Check

Restrict images chỉ được deploy từ các registry/path patterns được tin tưởng. Đây là whitelist-based check.

yaml
trustedDirectoryCheck:
  trustedDirPatterns:
  - "gcr.io/my-project/**"        # chỉ từ project's GCR
  - "us-central1-docker.pkg.dev/my-project/prod-repo/**"  # Artifact Registry

Cơ chế: CV so sánh image URI với các patterns. Nếu image đến từ registry không trong danh sách → violation. Không có cryptographic verification — đây là location-based trust.

Khi nào dùng? Đảm bảo chỉ images từ internal registries (kiểm soát bởi tổ chức) được chạy, không phải từ Docker Hub hay external registries. Thường combine với attestation check để có cả location-trust và content-trust.

6. Vulnerability Check

Check tích hợp Artifact Analysis vulnerability scanning để đảm bảo image không chứa vulnerabilities vượt quá severity threshold.

yaml
vulnerabilityCheck:
  maximumFixableSeverity: MEDIUM    # reject nếu có fixable vulnerability MEDIUM trở lên
  maximumUnfixableSeverity: HIGH    # reject nếu có unfixable vulnerability HIGH trở lên
  allowedCves:
  - CVE-2023-XXXXX    # whitelist specific CVEs (chấp nhận risk đã được acknowledge)
  blockedCves:
  - CVE-2023-YYYYY    # explicit block dù severity thấp

Cơ chế: CV query Artifact Analysis vulnerability findings cho image digest. Vulnerability data đến từ:

  • Container Scanning API (trong Artifact Registry)
  • OS package scanning
  • Language package scanning (Go, Java, Python, etc.)

Fixable vs Unfixable:

  • Fixable: Có phiên bản mới của package đã fix vulnerability → maximumFixableSeverity
  • Unfixable: Không có fix nào (upstream chưa patch) → maximumUnfixableSeverity

Thường set maximumUnfixableSeverity cao hơn maximumFixableSeverity vì unfixable không có action item rõ ràng.

Severity levels: CRITICAL > HIGH > MEDIUM > LOW > MINIMAL

Latency của vulnerability data: Vulnerability scanning có thể mất vài phút sau khi push image. CV evaluation có thể nhận thiếu data nếu image mới được push và chưa scan xong. Đây là lý do nên integrate vulnerability scan vào CI pipeline và wait for scan completion trước khi deploy.


Kết Hợp Checks Và Check Sets

AND Logic Trong Check Set

Tất cả checks trong một check set phải pass. Nếu check set có 3 checks (attestation + freshness + vulnerability), image phải thỏa mãn cả 3. Nếu bất kỳ check nào fail → check set violation.

Check Set Matching Logic

Một Pod được evaluate bởi check set nào? Binary Authorization chọn check set theo scope priority:

  1. Nếu Pod trong namespace payment → áp dụng check set scoped to payment (nếu có)
  2. Nếu không có namespace-specific check set → áp dụng cluster-wide default check set
  3. Nếu không có default check set → không có violation

Quan trọng: Chỉ một check set áp dụng cho mỗi Pod (most-specific wins). Không có chaining nhiều check sets cho cùng một Pod trong cùng platform policy.

Multiple Platform Policies

Một cluster có thể được monitor bởi nhiều platform policies (từ cùng project hoặc các projects khác). Mỗi policy evaluate độc lập. Violations từ mỗi policy được log riêng.

Điều này cho phép phân tầng policy: một policy global cho toàn tổ chức (managed bởi security team) và một policy per-team cho requirements riêng của team đó.

bash
# Attach platform policy vào cluster
gcloud container binauthz policy-bindings create my-binding \
  --policy=projects/my-project/platforms/gke/policies/production-cv-policy \
  --gke-cluster=us-central1/my-cluster \
  --resource-types=POD

Violation Logging và Monitoring

Log Format

Khi CV detect violation, một log entry được ghi vào Cloud Logging:

json
{
  "logName": "projects/my-project/logs/binaryauthorization.googleapis.com%2Fcontinuous_validation",
  "resource": {
    "type": "k8s_cluster",
    "labels": {
      "cluster_name": "production-cluster",
      "namespace_name": "default",
      "project_id": "my-project"
    }
  },
  "jsonPayload": {
    "podEvent": {
      "podNamespace": "default",
      "podName": "my-app-xxx",
      "deployTime": "2024-01-15T10:00:00Z",
      "endTime": "",
      "verdict": "VIOLATES_POLICY",
      "images": [
        {
          "containerName": "app",
          "description": "IMAGE_FRESHNESS_CHECK_FAILED",
          "image": "gcr.io/my-project/my-app@sha256:abc123",
          "verdict": "VIOLATES_POLICY"
        }
      ]
    }
  }
}

Logging behavior:

  • Log được ghi mỗi evaluation cycle cho mỗi Pod vi phạm (ít nhất mỗi 24 giờ)
  • Log được ghi chỉ khi có violation — nếu Pod compliant, không có log
  • Log tiếp tục được ghi ngay cả khi Pod bị xóa — entry cuối có thể xuất hiện sau khi Pod đã terminate

Alerting Trên Violations

Tạo log-based alert để notify khi có CV violation:

bash
# Tạo log-based metric
gcloud logging metrics create cv_violations \
  --description="Binary Authorization CV violations" \
  --log-filter='resource.type="k8s_cluster"
    AND logName:"binaryauthorization.googleapis.com/continuous_validation"
    AND jsonPayload.podEvent.verdict="VIOLATES_POLICY"'

# Tạo alerting policy
gcloud alpha monitoring policies create \
  --policy-from-file=cv-alert-policy.yaml
yaml
# cv-alert-policy.yaml
displayName: "Binary Authorization CV Violations"
conditions:
- displayName: "CV violation detected"
  conditionThreshold:
    filter: metric.type="logging.googleapis.com/user/cv_violations"
    comparison: COMPARISON_GT
    thresholdValue: 0
    duration: 60s
notificationChannels:
- "projects/my-project/notificationChannels/my-slack-channel"

Constraints và Design Decisions

CV Không Evict — Implications

CV chỉ log violations. Điều này có nghĩa:

  1. Violations không tự resolve: Một Pod vi phạm sẽ tiếp tục chạy và tiếp tục bị log là violation cho đến khi operator xử lý
  2. Cần manual remediation: Operator phải review violation log và quyết định action (redeploy với compliant image, patch image, add to allowlist)
  3. Monitoring là critical: Nếu không có alerting setup, violations có thể bị bỏ qua trong thời gian dài

Tại sao không auto-evict? Eviction của running Pod có blast radius lớn — nếu có bug trong policy hoặc false positive, auto-eviction có thể gây outage. Thiết kế "log only" là conservative choice ưu tiên stability over security automation.

Để có enforcement mạnh hơn, teams thường build automation:

  1. CV violation → Cloud Logging sink → Pub/Sub → Cloud Function
  2. Cloud Function evaluate severity → nếu CRITICAL → trigger automated remediation (drain namespace, scale down deployment, notify on-call)

Coverage: CV Chỉ Monitor Running Pods

CV monitor Pods đang chạy tại thời điểm evaluation. Nếu một Pod vi phạm được deploy trong khoảng giữa hai evaluation cycle và bị terminate trước evaluation tiếp theo → CV không bao giờ detect. Đây là tại sao deploy-time enforcement và CV cần được dùng kết hợp, không thể thay thế nhau.

Chi Phí Của Vulnerability Check

Vulnerability check gọi Artifact Analysis API cho mỗi image trong mỗi Pod trong mỗi evaluation cycle. Với cluster lớn (1000 Pods × 2 containers × daily check), đây là ~2000 API calls/ngày. Artifact Analysis có pricing theo số occurrences stored và API calls. Cần tính toán chi phí trước khi bật vulnerability check ở scale lớn.


Tài liệu tham khảo