Security¶
Supply-chain controls¶
The Grafana provider manifest (platform/provider/provider-grafana.yaml):
- Pins the v2.13.0 OCI digest.
- Verifies Grafana's keyless signature against the exact tag workflow identity, using a PreSync Argo CD hook Job running Cosign 3.1.2 at an immutable digest.
- Runs the provider with
--safe-start. - Activates only the managed-resource kinds used by this reference, through a
ManagedResourceActivationPolicy.
The repository's function workflow:
- Tidies and checks the Go module.
- Runs race-enabled tests and
go vet. - Builds amd64 and arm64 distroless images from pinned bases.
- Assembles a multi-platform Crossplane package.
- Publishes an immutable commit-derived version.
- Signs the OCI index with keyless Cosign.
platform/function/install.yaml pins the signed digest and verifies it against this repository's exact main-branch workflow identity before Crossplane installs it — the same PreSync-hook pattern as the provider. The verification Job name contains the digest prefix, so changing the digest creates a new gate rather than reusing an old successful Job.
Forking this repository means changing the package repository and the expected Cosign workflow identity in install.yaml. If the package is private, provide a dedicated read-only registry credential through an external secret — do not commit a Docker config or reuse a developer token.
Credential handling¶
No Grafana credential belongs in Git, a request object, Composition input, status, or function log. See Secrets for the full organization-credential and rotating-token model. Key properties:
- The organization credential and every generated per-stack token are rotated automatically (30-day lifetime, 7-day early rotation window) rather than issued as static, indefinite-lived values.
- Static
StackServiceAccountToken,AccessPolicyToken, andServiceAccountTokenresources remain available in the upstream provider but are deliberately not used — their rotating counterparts avoid a permanent credential lifecycle outside the control plane. - OAuth client secrets and SAML key material are always
LocalSecretKeySelector/Secret references, never literal fields copied into a managed resource. - AWS access should come from workload identity (EKS Pod Identity, IRSA, or the equivalent for your platform), never long-lived keys in the
SecretStore.
Non-destructive lifecycle¶
This reference contains no one-command destructive path. Deletion protection and the omission of provider Delete permissions are deliberate:
- The
StacksetsdeleteProtection. - Every composed managed resource omits the
Deletemanagement policy. - Rotating tokens set
deleteOnDestroy: false. PushSecretusesdeletionPolicy: None.
Pruning a request from Git deletes the Kubernetes composite and composed objects but orphans the external Grafana stack and its credential documents rather than destroying them. A destructive decommission must be a separately reviewed operation — see the decommission runbook in the project README, which covers resolving the exact stack identity, revoking credentials, and confirming external deletion before removing the request from Git.
Public-release scanning¶
scripts/validate.sh runs scripts/public-release-scan.sh, which scans the working tree and reachable Git history for source identifiers, credential prefixes, private keys, local paths, private endpoints, account IDs, JWT-like values, Kubernetes Secret manifests, sensitive file names, and tracked archives/key containers. Run it before making a fork public — see Troubleshooting.
This scan covers reachable local Git objects; it cannot inspect deleted remote refs or external artefacts no longer present in a checkout. Before making a repository public, also review its GitHub settings, issues, workflow logs, releases, packages, and commit-author metadata by hand.
Known limitations¶
- The Grafana provider is experimental and may lag the Terraform provider it is generated from.
- Provider schemas and Grafana APIs may expose fields that do not round-trip cleanly — test drift rather than assuming it behaves correctly.
- The reference has no destructive workflow by design.
- It does not provision Kubernetes, AWS infrastructure, DNS, identity providers, or incident relays.
- It uses generic starter dashboards rather than a full observability content library.
- Report, Enterprise, OnCall, plugin, and other resources require the relevant Grafana Cloud capabilities and entitlements.
- SSO profiles shipped in this repository are examples and must be replaced with reviewed identity settings.
- Built-in Viewer, Editor, and Admin basic-role definitions cannot be globally rewritten through the current provider — use SSO mapping, fixed/custom roles, and content ACLs instead.
- Fixed-role UIDs and available RBAC actions vary by Grafana version, edition, and entitlement — inventory and test them before assignment.
FolderPermission,DashboardPermission,RoleAssignment,NotificationPolicy, and similar whole-set APIs need exactly one declarative owner per external target.- Crossplane readiness reports only the child resources currently desired — an optional disabled domain is not health-checked.
- Secret-store publication is eventually consistent with the configured ESO refresh interval.
- A successful render or unit test does not prove acceptance by a specific Grafana Cloud region or account — use a disposable stack for live acceptance.
Next steps¶
- Secrets — the organization credential and rotating-token model.
- Architecture — the ownership boundaries that keep controllers from stepping on each other.