الامتثال والحوكمة ونضج DevSecOps
السياسة كرمز مع OPA و Rego
4 دقيقة للقراءة
السياسة كرمز (PaC) تتعامل مع سياسات الأمان والامتثال كرمز يخضع للتحكم بالإصدارات. Open Policy Agent (OPA) ولغته Rego أصبحا المعيار لتعريف وإنفاذ السياسات عبر دورة حياة تطوير البرمجيات.
لماذا السياسة كرمز؟
| النهج التقليدي | السياسة كرمز |
|---|---|
| مراجعات السياسات اليدوية | إنفاذ آلي |
| قائم على التوثيق | سياسات قابلة للتنفيذ |
| تطبيق غير متسق | متسق عبر البيئات |
| دورات موافقة بطيئة | تحقق في الوقت الفعلي |
| صعب التدقيق | يخضع للتحكم بالإصدارات، قابل للتدقيق |
نظرة عامة على Open Policy Agent (OPA)
┌─────────────────────────────────────────────────────────┐
│ إنفاذ السياسات │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ بيانات الإدخال│───▶│ OPA │ │
│ │ (JSON) │ │ │ │
│ └──────────────┘ │ ┌────────┐ │ │
│ │ │ سياسة │ │───▶ القرار │
│ ┌──────────────┐ │ │ Rego │ │ (سماح/رفض) │
│ │ الاستعلام │───▶│ └────────┘ │ │
│ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
البدء مع OPA
التثبيت
# macOS
brew install opa
# Linux
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
chmod +x opa
sudo mv opa /usr/local/bin/
# التحقق من التثبيت
opa version
سياسة Rego أساسية
# policy.rego
package authz
# الرفض الافتراضي
default allow := false
# السماح إذا كان المستخدم مسؤولاً
allow if {
input.user.role == "admin"
}
# السماح إذا كان المستخدم يملك المورد
allow if {
input.user.id == input.resource.owner_id
}
اختبار السياسة
# بيانات الإدخال (input.json)
{
"user": {
"id": "user123",
"role": "developer"
},
"resource": {
"owner_id": "user123",
"type": "document"
}
}
# تقييم السياسة
opa eval -i input.json -d policy.rego "data.authz.allow"
# النتيجة: true (المستخدم يملك المورد)
التحكم في قبول Kubernetes مع OPA
Gatekeeper: OPA لـ Kubernetes
# تثبيت Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
قالب القيد
# template.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
القيد
# constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: pods-must-have-owner
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
labels: ["app", "owner", "environment"]
إنفاذ السياسات في CI/CD
مثال سياسة Terraform
# terraform_policy.rego
package terraform
# رفض S3 buckets العامة
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.acl == "public-read"
msg := sprintf("S3 bucket '%s' لا يمكن أن يكون عاماً", [resource.name])
}
# طلب التشفير على RDS
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
not resource.change.after.storage_encrypted
msg := sprintf("مثيل RDS '%s' يجب أن يكون مشفراً", [resource.name])
}
# فرض الحد الأدنى لحجم المثيل
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
not valid_instance_type(resource.change.after.instance_type)
msg := sprintf("المثيل '%s' يستخدم نوعاً غير مسموح '%s'", [resource.name, resource.change.after.instance_type])
}
valid_instance_type(type) {
allowed := {"t3.micro", "t3.small", "t3.medium", "m5.large"}
allowed[type]
}
تكامل GitHub Actions
# .github/workflows/policy-check.yml
name: Policy Check
on:
pull_request:
paths:
- '**/*.tf'
jobs:
opa-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Terraform Plan
run: |
terraform init
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
- name: Setup OPA
uses: open-policy-agent/setup-opa@v2
- name: Run OPA Policy Check
run: |
opa eval -i tfplan.json \
-d policies/ \
--format pretty \
"data.terraform.deny"
أنماط السياسات الشائعة
وسم الموارد
package tags
required_tags := {"environment", "owner", "cost-center"}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_instance"
tags := object.get(resource.change.after, "tags", {})
missing := required_tags - {tag | tags[tag]}
count(missing) > 0
msg := sprintf("المورد '%s' ينقصه الوسوم: %v", [resource.name, missing])
}
أمان الشبكة
package network
# رفض مجموعات الأمان المتساهلة جداً
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_security_group_rule"
resource.change.after.type == "ingress"
resource.change.after.cidr_blocks[_] == "0.0.0.0/0"
resource.change.after.from_port == 0
resource.change.after.to_port == 65535
msg := "مجموعة الأمان تسمح بكل الحركة من الإنترنت"
}
اختبار سياسات Rego
# policy_test.rego
package terraform
test_deny_public_s3 {
deny["S3 bucket 'test' cannot be public"] with input as {
"resource_changes": [{
"type": "aws_s3_bucket",
"name": "test",
"change": {"after": {"acl": "public-read"}}
}]
}
}
test_allow_private_s3 {
count(deny) == 0 with input as {
"resource_changes": [{
"type": "aws_s3_bucket",
"name": "test",
"change": {"after": {"acl": "private"}}
}]
}
}
# تشغيل الاختبارات
opa test policies/ -v
بعد ذلك، سنستكشف أتمتة الامتثال لـ SOC2 و HIPAA و PCI-DSS. :::