pub const BINDY_ROLE_YAML: &str = "# Copyright (c) 2025 Erick Bourgeois, firestoned\n# SPDX-License-Identifier: MIT\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n name: bindy-role\n labels:\n app.kubernetes.io/name: bindy\n app.kubernetes.io/component: rbac\n annotations:\n # Trivy suppressions - see inline justifications at affected rules\n trivy.aquasecurity.com/ignore: KSV-0041,KSV-0056\nrules:\n # Bind9Instance resources\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"bind9instances\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\", \"list\", \"watch\": Read instances for status updates\n # - \"create\": Create instances for Bind9Cluster scaling\n # - \"update\", \"patch\": Update instance configuration\n # - \"delete\": Scale down instances (Bind9Cluster reconciler) and finalizer cleanup\n\n # Bind9Instance status subresource (separate permissions for least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"bind9instances/status\"]\n verbs: [\"get\", \"update\", \"patch\"]\n # Status updates only need get/update/patch, not create/delete\n\n # Bind9Cluster resources\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"bind9clusters\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\", \"list\", \"watch\": Read clusters for status updates\n # - \"create\": Create clusters for ClusterBind9Provider\n # - \"update\", \"patch\": Update cluster configuration\n # - \"delete\": Clean up clusters (ClusterBind9Provider finalizer cleanup)\n\n # Bind9Cluster status subresource (separate permissions for least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"bind9clusters/status\"]\n verbs: [\"get\", \"update\", \"patch\"]\n # Status updates only need get/update/patch, not create/delete\n\n # ClusterBind9Provider resources - cluster-scoped, NO DELETE (least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"clusterbind9providers\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\"]\n # Removed: \"delete\" - Use bindy-admin-role for deletions\n\n # ClusterBind9Provider status subresource (separate permissions for least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"clusterbind9providers/status\"]\n verbs: [\"get\", \"update\", \"patch\"]\n # Status updates only need get/update/patch, not create/delete\n\n # DNSZone resources - NO DELETE (least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"dnszones\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\"]\n # Removed: \"delete\" - Use bindy-admin-role for deletions\n\n # DNSZone status subresource (separate permissions for least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources: [\"dnszones/status\"]\n verbs: [\"get\", \"update\", \"patch\"]\n # Status updates only need get/update/patch, not create/delete\n\n # Record resources - NO DELETE (least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources:\n - \"arecords\"\n - \"aaaarecords\"\n - \"txtrecords\"\n - \"cnamerecords\"\n - \"mxrecords\"\n - \"nsrecords\"\n - \"srvrecords\"\n - \"caarecords\"\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\"]\n # Removed: \"delete\" - Use bindy-admin-role for deletions\n\n # Record status subresources (separate permissions for least privilege)\n - apiGroups: [\"bindy.firestoned.io\"]\n resources:\n - \"arecords/status\"\n - \"aaaarecords/status\"\n - \"txtrecords/status\"\n - \"cnamerecords/status\"\n - \"mxrecords/status\"\n - \"nsrecords/status\"\n - \"srvrecords/status\"\n - \"caarecords/status\"\n verbs: [\"get\", \"update\", \"patch\"]\n # Status updates only need get/update/patch, not create/delete\n\n # Kubernetes Deployments\n - apiGroups: [\"apps\"]\n resources: [\"deployments\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\", \"list\", \"watch\": Read deployment status\n # - \"create\": Create deployments for Bind9Instance\n # - \"update\", \"patch\": Update deployment configuration\n # - \"delete\": Finalizer cleanup (Bind9Instance reconciler)\n # Note: Owner references provide automatic GC, but finalizer explicitly deletes\n\n # Kubernetes Services\n # trivy:ignore:KSV-0056\n # Suppression Justification (KSV-0056 - Services/Endpoints Access):\n # REQUIRED FOR CORE FUNCTIONALITY - DNS operator MUST manage Services to expose BIND9 servers.\n # Mitigation Strategy:\n # 1. Namespace-scoped via RoleBinding - cannot intercept traffic in other namespaces\n # 2. Owner references - Services are bound to Bind9Instance resources (automatic cleanup)\n # 3. Finalizers - Explicit deletion only when parent Bind9Instance is deleted\n # 4. Service selectors - Only route traffic to pods owned by this operator\n # 5. NetworkPolicy enforcement - Traffic interception prevented by cluster NetworkPolicies\n # Risk Acceptance: Service management is fundamental to DNS server operation. Network policies\n # and namespace isolation provide defense-in-depth against traffic interception.\n # Compliance: NIST SP 800-190 (container orchestration security), CIS Kubernetes Benchmark 5.1.5\n - apiGroups: [\"\"]\n resources: [\"services\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\", \"list\", \"watch\": Read service status and endpoints\n # - \"create\": Create services for Bind9Instance\n # - \"update\", \"patch\": Update service configuration (preserves clusterIP)\n # - \"delete\": Finalizer cleanup (Bind9Instance reconciler)\n # Note: Owner references provide automatic GC, but finalizer explicitly deletes\n\n # Kubernetes ConfigMaps\n - apiGroups: [\"\"]\n resources: [\"configmaps\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\", \"list\", \"watch\": Read configuration data\n # - \"create\": Create ConfigMaps for Bind9Instance configuration\n # - \"update\", \"patch\": Update BIND9 configuration (zone changes)\n # - \"delete\": Finalizer cleanup (Bind9Instance reconciler)\n # Note: Owner references provide automatic GC, but finalizer explicitly deletes\n\n # Kubernetes Secrets - RNDC key management (CRITICAL: least privilege for sensitive data)\n # trivy:ignore:KSV-0041\n # Suppression Justification (KSV-0041 - Secrets Access):\n # REQUIRED FOR CORE FUNCTIONALITY - DNS operator MUST manage RNDC secrets for BIND9 authentication.\n # Mitigation Strategy:\n # 1. Namespace-scoped via RoleBinding (not ClusterRoleBinding) - limits blast radius\n # 2. Minimal verbs - no \"update\" permission, only \"patch\" for metadata-only changes\n # 3. Purpose-specific secrets - only creates/reads secrets with \"bindy-rndc-\" prefix\n # 4. Audit logging enabled - all secret operations logged for compliance (PCI-DSS 10.2)\n # 5. RBAC separation - admin role required for cluster-wide secret access\n # Risk Acceptance: Secrets access is unavoidable for DNS operator authentication requirements.\n # Compliance: PCI-DSS 7.1.2 (minimal permissions), NIST SP 800-190 (container secrets management)\n - apiGroups: [\"\"]\n resources: [\"secrets\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\": Load RNDC keys for zone updates (DNSZone reconciler)\n # - \"list\": Check if RNDC secrets exist (Bind9Cluster reconciler)\n # - \"watch\": Monitor RNDC secret changes\n # - \"create\": Generate RNDC keys for new Bind9Instance resources\n # - \"update\": RNDC key rotation \u{2014} kube::Api::replace() (HTTP PUT) replaces the entire\n # Secret with new key material + updated rotation count + annotations.\n # patch is insufficient here because key data itself changes during rotation.\n # - \"patch\": Metadata-only changes (e.g. adding annotations without touching key data)\n # - \"delete\": Clean up RNDC keys when Bind9Instance is deleted (finalizer)\n # PCI-DSS 7.1.2: Minimal permissions for RNDC secret lifecycle management\n\n # Kubernetes ServiceAccounts\n - apiGroups: [\"\"]\n resources: [\"serviceaccounts\"]\n verbs: [\"get\", \"list\", \"watch\", \"create\", \"update\", \"patch\", \"delete\"]\n # Permissions needed:\n # - \"get\", \"list\", \"watch\": Read service account status\n # - \"create\": Create service accounts for Bind9Instance pods\n # - \"update\", \"patch\": Update service account configuration\n # - \"delete\": Finalizer cleanup (Bind9Instance reconciler)\n # Note: Owner references provide automatic GC, but finalizer explicitly deletes\n\n # Kubernetes Pods - READ-ONLY (for discovery and status)\n - apiGroups: [\"\"]\n resources: [\"pods\"]\n verbs: [\"get\", \"list\", \"watch\"]\n\n # Kubernetes Endpoints - READ-ONLY (for service discovery)\n - apiGroups: [\"\"]\n resources: [\"endpoints\"]\n verbs: [\"get\", \"list\", \"watch\"]\n\n # Events for logging (no delete needed)\n - apiGroups: [\"\"]\n resources: [\"events\"]\n verbs: [\"create\", \"patch\"]\n\n # Leases for leader election (no delete needed for HA)\n - apiGroups: [\"coordination.k8s.io\"]\n resources: [\"leases\"]\n verbs: [\"get\", \"create\", \"update\", \"patch\"]\n";Expand description
Embedded RBAC YAML files — compiled into the binary so bootstrap is self-contained.