FerrFlow-Operator

module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2026 License: MPL-2.0

README

ferrflow-operator

CI Release Latest release Coverage License

Kubernetes operator that syncs secrets stored in FerrFlow into native Kubernetes Secret resources.

Status: alpha. The MVP reconciler is in place — it reads secrets from a FerrFlow vault via the bulk-reveal API and materialises them into a Kubernetes Secret, with owner-ref GC and status conditions. Rolling restarts, Helm chart, and integration tests are tracked in issue #1.

Custom resources

Two CRDs under ferrflow.io/v1alpha1:

FerrFlowConnection (shortname ffc)

Declares how to reach a FerrFlow instance. One per (namespace, org). Shared by every FerrFlowSecret in that namespace that targets the same organization.

apiVersion: ferrflow.io/v1alpha1
kind: FerrFlowConnection
metadata:
  name: prod
spec:
  url: https://ferrflow.example.com
  organization: acme
  tokenSecretRef:
    name: ferrflow-api-token
    key: token

The referenced Secret must hold a FerrFlow API token (fft_...) with at least the secrets:read scope.

FerrFlowSecret (shortname ffs)

Declares a sync from a vault to a Kubernetes Secret.

apiVersion: ferrflow.io/v1alpha1
kind: FerrFlowSecret
metadata:
  name: web-env
spec:
  connectionRef: { name: prod }
  project: web
  vault: production          # FerrFlow vault name (often the environment)
  selector:
    names: [DATABASE_URL, STRIPE_KEY]   # omit to sync every key in the vault
  target:
    name: web-env            # target Secret name; defaults to metadata.name
    type: Opaque
  refreshInterval: 30m       # Go time.Duration; 0s disables scheduled refresh

On reconciliation the operator calls GET /api/v1/orgs/:org/projects/:project/vaults/by-name/:vault/secrets/reveal once, writes the returned {name: value} map into spec.target.name, and sets the CR's Ready condition based on whether any requested keys were missing upstream.

The generated Secret is owned by the CR — deleting the CR garbage-collects the Secret.

Value transforms

Revealed values can be reshaped before they land in the target Secret via spec.transforms. Transforms are applied in order; each one sees the output of the previous step.

spec:
  connectionRef: { name: prod }
  project: web
  vault: production
  selector:
    names: [DATABASE_URL, STRIPE_KEY, CONFIG_JSON]
  transforms:
    - type: rename
      from: DATABASE_URL
      to: DB_URL
    - type: base64Decode
      keys: [STRIPE_KEY]          # omit `keys` to decode every value
    - type: jsonExpand
      key: CONFIG_JSON            # {"db":{"host":"pg"}} → CONFIG_JSON_DB_HOST=pg
    - type: prefix
      value: APP_                 # stamps APP_ on every remaining key

Supported types:

type Fields Effect
prefix value Prepends value to every key.
suffix value Appends value to every key.
rename from, to Projects one key. Missing from is a no-op; collisions fail.
base64Decode keys (optional) Decodes listed keys (or all when empty) from base64.
jsonExpand key Flattens a JSON object under <KEY>_<SUB>. Drops the source.

Malformed transforms (unknown type, invalid base64, non-object JSON, destination-key collisions) leave the CR in Ready=False with Reason=TransformError and increment ferrflow_secret_sync_errors_total{reason="TransformError"}. The target Secret is not written on failure — workloads keep the last known-good value.

Running

helm install ferrflow-operator oci://ghcr.io/ferrlabs/charts/ferrflow-operator \
  --namespace ferrflow-operator-system --create-namespace

Upgrade: helm upgrade against the same release. CRDs carry helm.sh/resource-policy: keep so they survive uninstall (protects your CRs + managed Secrets). See charts/ferrflow-operator/README.md for the full values.yaml reference.

Locally against a cluster
make install-crds   # CRDs only
make run            # runs the manager as your user, not as a Pod
Raw manifests (without Helm at runtime)

The Helm chart is the single source of truth for all manifests (CRDs, RBAC, ServiceAccount, Deployment). If your cluster policy forbids running Helm at deploy time, render once and commit/apply the plain YAML:

kubectl create namespace ferrflow-operator-system
helm template ferrflow-operator charts/ferrflow-operator \
  --namespace ferrflow-operator-system \
  > manager.yaml
kubectl apply -f manager.yaml

No duplicate config/rbac/ or config/crd/ lives in the repo — anything rendered from the chart is the canonical version.

Prerequisites in FerrFlow

The operator relies on endpoints in FerrLabs/Application that shipped in api@v4.0.0:

  • API token auth (Authorization: Bearer fft_...) with granular scopes — #268
  • secrets:read scope enforcement on all secrets routes — #268
  • Bulk reveal endpoint — #277

Contributing

See CONTRIBUTING.md. Code of conduct in CODE_OF_CONDUCT.md. Vulnerability reports via SECURITY.md.

License

MPL-2.0

Directories

Path Synopsis
api
v1alpha1
Package v1alpha1 holds the CRD types for ferrflow.io/v1alpha1 — the FerrFlow-Operator's first API version.
Package v1alpha1 holds the CRD types for ferrflow.io/v1alpha1 — the FerrFlow-Operator's first API version.
Command manager is the entry point for the ferrflow-operator binary.
Command manager is the entry point for the ferrflow-operator binary.
internal
controller
Package controller — FerrFlowConnection reconciler.
Package controller — FerrFlowConnection reconciler.
ferrflow
Package ferrflow is the HTTP client the operator uses to talk to a FerrFlow API instance.
Package ferrflow is the HTTP client the operator uses to talk to a FerrFlow API instance.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL