Organization Policies: Ép buộc ràng buộc & tuân thủ
Tổng quan về Organization Policies
Organization Policies ép buộc các ràng buộc lên resources: "Developer không được xóa VM", "Storage phải được mã hóa"
Organization Policy:
"Developer cannot delete Compute Engine instances"
↓
Áp dụng cho: Org → Folder → Project
↓
Thực thi: Không developer nào được xóa instance (ngoại lệ: một số service account cụ thể)Các loại constraint
1. Managed Constraints
Được Google xây sẵn, dùng ngay:
Các managed constraints phổ biến:
- compute.skipDefaultNetworkCreation
- compute.requireOsLogin
- compute.requireShieldedVm
- storage.uniformBucketLevelAccess
- iam.disableServiceAccountCreation2. Custom Constraints
Do người dùng định nghĩa bằng CEL (Common Expression Language):
yaml
# Ví dụ: bắt buộc labels trên mọi resource
constraint:
name: "require-resource-labels"
display_name: "Require resource labels"
description: "Tất cả resource phải có labels 'environment' và 'team'"
condition: |
resource.labels.environment != null
AND resource.labels.team != null
action_type: deny3. Legacy Constraints (đã lỗi thời)
Định dạng cũ, đang được loại bỏ dần. Hãy dùng managed/custom thay thế.
Thiết lập Organization Policies
bash
# 1. Liệt kê managed constraints có sẵn
gcloud resource-manager org-policies list-constraints
# 2. Xem chi tiết constraint
gcloud resource-manager org-policies describe \
constraints/compute.requireOsLogin
# 3. Tạo policy (ép constraint)
gcloud resource-manager org-policies create \
--constraint=constraints/compute.requireOsLogin \
--enforce \
--location=projects/PROJECT_ID
# 4. Đặt ngoại lệ (cho phép service account cụ thể)
gcloud resource-manager org-policies create \
--constraint=constraints/compute.requireOsLogin \
--enforce \
--exemptions=serviceAccount:sa@project.iam.gserviceaccount.com \
--location=projects/PROJECT_IDKế thừa policy
Organization
├── Policy: "Require OS Login"
│ ├── Được kế thừa bởi tất cả folders
│ └── Được kế thừa bởi tất cả projects
│
├── Folder: "Production"
│ ├── Kế thừa: "Require OS Login"
│ ├── Policy: "Require CMEK"
│ │ ├── Được kế thừa bởi child projects
│ │ └── Ngoại lệ: backup-sa@...
│ │
│ └── Project: "prod-api"
│ ├── Kế thừa: "Require OS Login"
│ ├── Kế thừa: "Require CMEK"
│ └── Policy: "Disable SSH keys"Giải quyết xung đột
Nếu policy xung đột thì sao?
Organization: "Enforce CMEK" (phải đúng)
Folder: Override "Allow unencrypted" (phải sai)
Kết quả: CMEK được thực thi
(không thể nới lỏng policy kế thừa ở tầng thấp hơn)Policy có điều kiện với Tags
yaml
# Ép CMEK chỉ cho resource production
policy:
name: "encrypt-production"
constraint: "compute.cmekResources"
rules:
- enforce: true
condition:
expression: "resource.matchTag('environment', 'production')"
description: "Bắt buộc CMEK cho production"
- enforce: false
condition:
expression: "resource.matchTag('environment', 'dev')"
description: "Dev được dùng encryption mặc định"Chế độ Dry-Run
Kiểm thử policy trước khi ép buộc:
bash
# Tạo policy ở chế độ dry-run
gcloud resource-manager org-policies create \
--constraint=constraints/compute.requireOsLogin \
--dry-run \
--location=projects/PROJECT_ID
# Theo dõi audit logs để biết gì sẽ bị chặn
gcloud logging read \
'protoPayload.status.code=7' \ # Permission denied
--format=json
# Khi đã chắc chắn, chuyển sang enforcement
gcloud resource-manager org-policies update \
--constraint=constraints/compute.requireOsLogin \
--enforce \
--location=projects/PROJECT_IDCustom Constraints với CEL
python
from google.cloud import resource_manager_v3
def create_custom_constraint():
"""Tạo custom constraint: yêu cầu labels"""
client = resource_manager_v3.OrgPolicyClient()
# Định nghĩa constraint bằng CEL expression
constraint = resource_manager_v3.CustomConstraint(
display_name="Require environment label",
description="Tất cả resource phải có environment label",
condition="resource.labels.environment != null",
action_type=resource_manager_v3.CustomConstraint.ActionType.DENY,
resource_types=["compute.googleapis.com/Instance"]
)
# Tạo constraint
operation = client.create_custom_constraint(
parent=f"organizations/ORG_ID",
custom_constraint=constraint
)
return operation.result()Ví dụ CEL
yaml
# Ví dụ 1: Bắt buộc machine type cụ thể
resource.type == "compute.googleapis.com/Instance"
AND resource.machineType NOT IN ["n1-standard-1", "n1-standard-2"]
# Ví dụ 2: Bắt buộc labels
resource.labels.environment == null OR resource.labels.team == null
# Ví dụ 3: Giới hạn theo zone
resource.zone NOT IN ["us-central1-a", "us-central1-b"]
# Ví dụ 4: Ép mã hóa
resource.encryptionKey == null
# Ví dụ 5: Điều kiện phức tạp với tags
resource.matchTag("environment", "production")
AND resource.labels.encryption != "cmek"Organization Policies bằng Terraform
hcl
# Ép policy qua Terraform
resource "google_org_policy_policy" "require_os_login" {
name = "organizations/ORG_ID/policies/compute.requireOsLogin"
parent = "organizations/ORG_ID"
rules {
enforce = true
}
}
# Policy có ngoại lệ
resource "google_org_policy_policy" "require_cmek" {
name = "projects/PROJECT_ID/policies/compute.cmekResources"
parent = "projects/PROJECT_ID"
rules {
enforce = true
# Ngoại lệ cho service account
condition {
expression = "resource.matchTag('backup', 'true')"
}
}
}
# Custom constraint
resource "google_org_policy_custom_constraint" "require_labels" {
name = "organizations/ORG_ID/customConstraints/require.labels"
display_name = "Require labels"
description = "Tất cả resource phải có labels"
action_type = "DENY"
condition = "resource.labels.environment != null"
resource_types = ["compute.googleapis.com/Instance"]
}Khắc phục sự cố
Policy không được thực thi
bash
# Kiểm tra policy có thực sự được áp dụng không
gcloud resource-manager org-policies list \
--location=projects/PROJECT_ID
# Kiểm tra audit logs
gcloud logging read \
'protoPayload.resourceName="projects/PROJECT_ID"' \
--limit=50 \
--format=json
# Thử thực hiện hành động bị chặn
# Nếu bị chặn → Policy đang được thực thi
# Nếu vẫn được phép → Có thể policy cấu hình saiGiải quyết xung đột policy
bash
# Nếu nhiều policy cùng áp dụng, policy chặt nhất sẽ thắng
# Ví dụ:
Organization: Allow
Folder: Deny
Project: Allow
Kết quả: Deny (chặt nhất)
# Giải pháp: Kiểm tra hierarchy để tìm policy xung đột
gcloud resource-manager org-policies list --recursiveBest practices
yaml
1. Bắt đầu bằng dry-run
- Hiểu tác động trước khi enforcement
- Theo dõi logs xem điều gì sẽ bị chặn
2. Dùng tags cho policy có điều kiện
- Áp dụng quy tắc khác nhau theo environment
- Sạch hơn nhiều policy rời rạc
3. Ghi tài liệu ngoại lệ
- Vì sao service account này được miễn?
- Giữ audit trail
4. Rà soát định kỳ
- Policy có thể trở nên lỗi thời
- Công nghệ thay đổi (ví dụ: phương thức mã hóa mới)
5. Kiểm thử quy trình khôi phục
- Có thể tạm tắt policy nếu cần không?
- Quy trình phê duyệt là gì?Anti-pattern
| Anti-pattern | Vấn đề | Giải pháp |
|---|---|---|
| Policy quá rộng | Chặn cả use case hợp lệ | Dùng điều kiện, ngoại lệ |
| Quá nhiều ngoại lệ | Policy trở nên vô dụng | Xem lại ai thật sự cần ngoại lệ |
| Không dry-run | Làm hỏng workflow production | Test trước khi enforcement |
| Không tài liệu | Team không hiểu policy | Ghi rõ mục đích, ngoại lệ |
| Không review policy | Ràng buộc lỗi thời | Lên lịch review hàng quý |