Crossplane Composition RBAC ABAC Policy —
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