Crossplane RBAC ABAC
Crossplane Composition RBAC ABAC Policy Infrastructure as Code Kubernetes CRD Claim Multi-tenant OPA Kyverno Access Control Platform API Cloud Resources
| Policy Engine | Language | Complexity | K8s Native | เหมาะกับ |
|---|---|---|---|---|
| OPA Gatekeeper | Rego | สูง | Admission | Complex Policy |
| Kyverno | YAML | ต่ำ | Admission + Mutation | Simple Policy |
| K8s RBAC | YAML | ต่ำ | Built-in | Who can do what |
| CEL | Expression | ปานกลาง | ValidatingAdmissionPolicy | Simple Validation |
Crossplane Composition
# === Crossplane Composition ===
# CompositeResourceDefinition (XRD)
# apiVersion: apiextensions.crossplane.io/v1
# kind: CompositeResourceDefinition
# metadata:
# name: databases.platform.example.com
# spec:
# group: platform.example.com
# names:
# kind: Database
# plural: databases
# claimNames:
# kind: DatabaseClaim
# plural: databaseclaims
# versions:
# - name: v1alpha1
# served: true
# reachable: true
# schema:
# openAPIV3Schema:
# type: object
# properties:
# spec:
# type: object
# properties:
# engine:
# type: string
# enum: [postgres, mysql]
# size:
# type: string
# enum: [small, medium, large]
# environment:
# type: string
# enum: [dev, staging, prod]
# Composition
# apiVersion: apiextensions.crossplane.io/v1
# kind: Composition
# metadata:
# name: database-aws
# spec:
# compositeTypeRef:
# apiVersion: platform.example.com/v1alpha1
# kind: Database
# resources:
# - name: rds-instance
# base:
# apiVersion: rds.aws.upbound.io/v1beta1
# kind: Instance
# spec:
# forProvider:
# engine: postgres
# instanceClass: db.t3.medium
# allocatedStorage: 20
# - name: security-group
# base:
# apiVersion: ec2.aws.upbound.io/v1beta1
# kind: SecurityGroup
# Claim (Developer uses this)
# apiVersion: platform.example.com/v1alpha1
# kind: DatabaseClaim
# metadata:
# name: my-app-db
# namespace: team-alpha
# spec:
# engine: postgres
# size: medium
# environment: dev
from dataclasses import dataclass
@dataclass
class Composition:
name: str
resources: int
providers: str
claims: int
teams: int
compositions = [
Composition("Database", 4, "AWS RDS, SG, Subnet, SSM", 12, 5),
Composition("Kubernetes Cluster", 8, "EKS, VPC, IAM, NodeGroup", 3, 2),
Composition("Storage Bucket", 2, "S3, IAM Policy", 25, 8),
Composition("Redis Cache", 3, "ElastiCache, SG, Subnet", 8, 4),
Composition("VPC Network", 6, "VPC, Subnet, IGW, NAT, RT", 5, 3),
]
print("=== Compositions ===")
for c in compositions:
print(f" [{c.name}] {c.resources} resources")
print(f" Providers: {c.providers}")
print(f" Active Claims: {c.claims} | Teams: {c.teams}")
RBAC ABAC Policy
# === RBAC + ABAC Policy ===
# Kubernetes RBAC for Crossplane Claims
# apiVersion: rbac.authorization.k8s.io/v1
# kind: Role
# metadata:
# name: database-user
# namespace: team-alpha
# rules:
# - apiGroups: ["platform.example.com"]
# resources: ["databaseclaims"]
# verbs: ["get", "list", "create", "update", "delete"]
# - apiGroups: ["platform.example.com"]
# resources: ["storagebucketclaims"]
# verbs: ["get", "list", "create"]
# Kyverno Policy — Enforce Labels and Limits
# apiVersion: kyverno.io/v1
# kind: ClusterPolicy
# metadata:
# name: crossplane-claim-policy
# spec:
# rules:
# - name: require-team-label
# match:
# resources:
# kinds: ["DatabaseClaim", "StorageBucketClaim"]
# validate:
# message: "Claims must have team and cost-center labels"
# pattern:
# metadata:
# labels:
# team: "?*"
# cost-center: "?*"
# - name: restrict-prod-size
# match:
# resources:
# kinds: ["DatabaseClaim"]
# preconditions:
# - key: "{{request.object.spec.environment}}"
# operator: Equals
# value: "dev"
# validate:
# message: "Dev environment only allows small/medium"
# pattern:
# spec:
# size: "small | medium"
@dataclass
class PolicyRule:
name: str
type: str
scope: str
action: str
violations_30d: int
policies = [
PolicyRule("Require Team Label", "Validation", "All Claims", "Block", 5),
PolicyRule("Dev Size Limit", "Validation", "DatabaseClaim (dev)", "Block", 8),
PolicyRule("Prod Approval Required", "Validation", "All Claims (prod)", "Block + Alert", 2),
PolicyRule("Budget Limit per Team", "ABAC", "All Claims", "Block at limit", 3),
PolicyRule("Naming Convention", "Mutation", "All Claims", "Auto-fix", 15),
PolicyRule("Auto-add Tags", "Mutation", "All Resources", "Inject tags", 0),
]
print("\n=== Policy Rules ===")
for p in policies:
print(f" [{p.type}] {p.name}")
print(f" Scope: {p.scope} | Action: {p.action} | Violations: {p.violations_30d}")
Multi-tenant Architecture
# === Multi-tenant Crossplane ===
# Namespace per Team
# kubectl create namespace team-alpha
# kubectl create namespace team-beta
# kubectl create namespace team-gamma
# RoleBinding per Team
# apiVersion: rbac.authorization.k8s.io/v1
# kind: RoleBinding
# metadata:
# name: team-alpha-db-access
# namespace: team-alpha
# subjects:
# - kind: Group
# name: team-alpha
# apiGroup: rbac.authorization.k8s.io
# roleRef:
# kind: Role
# name: database-user
# apiGroup: rbac.authorization.k8s.io
# Budget Tracking per Team
# OPA Rego Policy:
# package crossplane.budget
# deny[msg] {
# input.review.object.kind == "DatabaseClaim"
# team := input.review.object.metadata.labels.team
# current_cost := data.budgets[team].current
# limit := data.budgets[team].limit
# current_cost > limit
# msg := sprintf("Team %s exceeded budget: $%d/$%d", [team, current_cost, limit])
# }
@dataclass
class TeamQuota:
team: str
namespace: str
db_limit: int
db_used: int
budget: float
spent: float
members: int
teams = [
TeamQuota("Alpha", "team-alpha", 5, 3, 5000, 3200, 8),
TeamQuota("Beta", "team-beta", 3, 2, 3000, 1800, 5),
TeamQuota("Gamma", "team-gamma", 10, 7, 10000, 7500, 15),
TeamQuota("Platform", "team-platform", 20, 12, 20000, 14000, 10),
]
print("Multi-tenant Dashboard:")
for t in teams:
db_pct = t.db_used / t.db_limit * 100
budget_pct = t.spent / t.budget * 100
print(f" [{t.team}] ns: {t.namespace} | Members: {t.members}")
print(f" DB: {t.db_used}/{t.db_limit} ({db_pct:.0f}%) | Budget: / ({budget_pct:.0f}%)")
audit_checklist = [
"RBAC: แต่ละ Team ใช้ได้เฉพาะ Namespace ตัวเอง",
"Policy: บังคับ Labels Team Cost-center ทุก Claim",
"Quota: จำกัด Resource ต่อ Team",
"Budget: Alert เมื่อใช้ 80% Block เมื่อ 100%",
"Audit: Log ทุก Create/Update/Delete Resource",
"Network: แยก VPC/Subnet ต่อ Environment",
"Encryption: เข้ารหัส Secrets ทุกตัว",
]
print(f"\n\nAudit Checklist:")
for i, c in enumerate(audit_checklist, 1):
print(f" {i}. {c}")
เคล็ดลับ
- Composition: สร้าง Composition ซ่อนความซับซ้อนจาก Dev
- RBAC: ใช้ K8s RBAC จำกัดสิทธิ์ต่อ Namespace
- Kyverno: ใช้ Kyverno สำหรับ Policy ง่ายกว่า OPA
- Labels: บังคับ Labels ทุก Claim สำหรับ Cost Tracking
- Budget: ตั้ง Budget Limit ต่อ Team ป้องกันบานปลาย
Crossplane Composition คืออะไร
รวม Cloud Resources เป็น API เดียว CRD Claim Developer ไม่ต้องรู้ Cloud RDS SG Subnet SSM Platform API Kubernetes
RBAC กับ ABAC ต่างกันอย่างไร
RBAC ตาม Role Admin Editor Viewer ง่าย ABAC ตาม Attribute Department Environment Time ยืดหยุ่น ซับซ้อน ใช้ร่วมกันได้
ใช้ Policy Engine อะไรกับ Crossplane
OPA Gatekeeper Rego Kyverno YAML K8s RBAC CEL Composition Functions Validation Admission Control Mutation
ออกแบบ Multi-tenant Crossplane อย่างไร
Namespace ต่อ Team RBAC จำกัด Claim Composition Limits Policy Labels Budget Network Isolation Audit Log
สรุป
Crossplane Composition RBAC ABAC Policy OPA Kyverno Kubernetes Multi-tenant Claim Namespace Budget Labels Audit Infrastructure as Code Platform API Cloud
