SiamCafe · Blog
Crossplane Composition Audit Trail Logging —
เครือข่ายและอินเทอร์เน็ต

Crossplane Composition Audit Trail Logging —

เผยแพร่ May 28, 2026

Crossplane Audit Trail

Crossplane Composition Audit Trail Logging —

Crossplane Composition Audit Trail Logging Kubernetes CRD Provider Claim XRD ELK Stack Falco OPA Gatekeeper GitOps Compliance

ComponentRoleData SourceOutput
K8s Audit LogAPI Request Loggingkube-apiserverJSON Log File
FilebeatLog CollectionAudit Log File→ Logstash/ES
LogstashLog ProcessingFilebeat→ Elasticsearch
ElasticsearchLog Storage + SearchLogstashIndex
KibanaDashboard + AlertElasticsearchVisualization
FalcoRuntime SecuritySyscalls + K8s APIAlert

Audit Policy Configuration

# === Kubernetes Audit Policy for Crossplane ===

# /etc/kubernetes/audit-policy.yaml
# apiVersion: audit.k8s.io/v1
# kind: Policy
# rules:
#   # Log all Crossplane resource changes at RequestResponse level
#   - level: RequestResponse
#     resources:
#       - group: "*.crossplane.io"
#       - group: "*.aws.crossplane.io"
#       - group: "*.gcp.crossplane.io"
#       - group: "*.azure.crossplane.io"
#     verbs: ["create", "update", "patch", "delete"]
#
#   # Log Composition and XRD changes
#   - level: RequestResponse
#     resources:
#       - group: "apiextensions.crossplane.io"
#         resources: ["compositions", "compositeresourcedefinitions"]
#     verbs: ["create", "update", "patch", "delete"]
#
#   # Log Claims
#   - level: Metadata
#     resources:
#       - group: "*.crossplane.io"
#     verbs: ["get", "list", "watch"]
#
#   # Log RBAC changes for Crossplane service accounts
#   - level: RequestResponse
#     resources:
#       - group: "rbac.authorization.k8s.io"
#     verbs: ["create", "update", "patch", "delete"]
#     namespaces: ["crossplane-system"]

# kube-apiserver flags
# --audit-policy-file=/etc/kubernetes/audit-policy.yaml
# --audit-log-path=/var/log/kubernetes/audit.log
# --audit-log-maxage=30
# --audit-log-maxbackup=10
# --audit-log-maxsize=100

from dataclasses import dataclass

@dataclass
class AuditRule:
    resource: str
    level: str
    verbs: str
    reason: str

rules = [
    AuditRule("*.crossplane.io (Managed Resources)",
        "RequestResponse",
        "create, update, patch, delete",
        "บันทึกทุกการเปลี่ยนแปลง Cloud Resources"),
    AuditRule("Compositions / XRDs",
        "RequestResponse",
        "create, update, patch, delete",
        "บันทึกการเปลี่ยน Infrastructure Template"),
    AuditRule("Claims",
        "Metadata",
        "get, list, watch",
        "บันทึก Developer ขอ Resource อะไร"),
    AuditRule("RBAC (crossplane-system)",
        "RequestResponse",
        "create, update, patch, delete",
        "บันทึกการเปลี่ยน Permission"),
    AuditRule("Secrets (crossplane-system)",
        "Metadata",
        "create, update, delete",
        "บันทึก Cloud Credentials Change (ไม่เก็บ Value)"),
]

print("=== Audit Rules ===")
for r in rules:
    print(f"  [{r.resource}] Level: {r.level}")
    print(f"    Verbs: {r.verbs}")
    print(f"    Reason: {r.reason}")

ELK Stack Integration

Crossplane Composition Audit Trail Logging —
# === ELK Stack for Crossplane Audit ===

# Filebeat config (filebeat.yml)
# filebeat.inputs:
#   - type: log
#     paths:
#       - /var/log/kubernetes/audit.log
#     json.keys_under_root: true
#     json.add_error_key: true
#     fields:
#       log_type: crossplane-audit
#
# output.logstash:
#   hosts: ["logstash:5044"]

# Logstash pipeline (crossplane-audit.conf)
# filter {
#   if [log_type] == "crossplane-audit" {
#     json { source => "message" }
#     mutate {
#       add_field => {
#         "crossplane_action" => "%{[verb]}"
#         "crossplane_user" => "%{[user][username]}"
#         "crossplane_resource" => "%{[objectRef][resource]}"
#         "crossplane_name" => "%{[objectRef][name]}"
#         "crossplane_namespace" => "%{[objectRef][namespace]}"
#       }
#     }
#     # Filter only Crossplane resources
#     if [objectRef][apiGroup] !~ /crossplane/ { drop {} }
#   }
# }
# output {
#   elasticsearch {
#     hosts => ["elasticsearch:9200"]
#     index => "crossplane-audit-%{+YYYY.MM.dd}"
#   }
# }

@dataclass
class KibanaDashboard:
    panel: str
    visualization: str
    query: str
    use_case: str

dashboards = [
    KibanaDashboard("Resource Lifecycle",
        "Time Series (create/update/delete count)",
        "crossplane_action:(create OR update OR delete)",
        "ดู Resource สร้าง/แก้/ลบ ต่อวัน"),
    KibanaDashboard("User Activity",
        "Data Table (user, action, resource, count)",
        "crossplane_user:* | top 20 by count",
        "ดูว่าใครทำอะไรบ้าง กี่ครั้ง"),
    KibanaDashboard("Resource Types",
        "Pie Chart (resource type distribution)",
        "crossplane_resource:* | terms",
        "ดู Resource ประเภทไหนถูกสร้างมากที่สุด"),
    KibanaDashboard("Manual Changes",
        "Table (non-GitOps changes)",
        "crossplane_user:NOT(system:serviceaccount:*)",
        "ตรวจจับ Manual Changes นอก GitOps"),
    KibanaDashboard("Failed Operations",
        "Time Series (responseStatus.code >= 400)",
        "responseStatus.code:[400 TO 599]",
        "ตรวจจับ Permission Denied Validation Error"),
]

print("=== Kibana Dashboards ===")
for d in dashboards:
    print(f"  [{d.panel}] {d.visualization}")
    print(f"    Query: {d.query}")
    print(f"    Use: {d.use_case}")

Alerting & Compliance

# === Audit Alerting ===

@dataclass
class AuditAlert:
    alert: str
    condition: str
    severity: str
    action: str

alerts = [
    AuditAlert("Manual Resource Deletion",
        "verb=delete AND user NOT serviceaccount",
        "Critical",
        "ตรวจสอบว่า Authorized ไหม แจ้ง Team Lead"),
    AuditAlert("Resource Created Outside GitOps",
        "verb=create AND user NOT (flux/argocd/crossplane)",
        "Warning",
        "แจ้ง Developer ให้ใช้ GitOps แทน Manual"),
    AuditAlert("Composition Changed",
        "resource=compositions AND verb=(update|patch)",
        "High",
        "ตรวจสอบ Change ถูกต้อง Review PR"),
    AuditAlert("Permission Escalation",
        "resource=clusterrolebindings AND namespace=crossplane-system",
        "Critical",
        "ตรวจสอบ RBAC Change Security Review"),
    AuditAlert("Cloud Credentials Modified",
        "resource=secrets AND namespace=crossplane-system",
        "Critical",
        "ตรวจสอบ Credentials Rotation หรือ Unauthorized"),
    AuditAlert("High Volume Resource Creation",
        "verb=create count > 50 in 1 hour",
        "Warning",
        "อาจเป็น Misconfigured Composition หรือ Loop"),
]

print("=== Audit Alerts ===")
for a in alerts:
    print(f"  [{a.alert}] Severity: {a.severity}")
    print(f"    Condition: {a.condition}")
    print(f"    Action: {a.action}")

เคล็ดลับ

  • GitOps: ตรวจจับ Manual Changes นอก GitOps ด้วย Audit Log
  • Falco: ใช้ Falco ตรวจ Runtime Security ของ Crossplane
  • Retention: เก็บ Audit Log 90 วัน+ สำหรับ Compliance
  • RBAC: ตั้ง RBAC Least Privilege สำหรับ Crossplane
  • Alert: ตั้ง Alert Manual Deletion Credential Change ทันที

Crossplane คืออะไร

Infrastructure as Code Kubernetes CRD Provider AWS GCP Azure Composition Claim XRD kubectl apply GitOps Flux ArgoCD Open Source