Skip to content

InfisicalSecret force-sync annotation does not trigger reconcile because generation is unchanged #83

Description

@rhaarhoff

Summary

InfisicalSecret annotation-only updates do not trigger reconciliation. The documented/operator-expected force-sync path depends on updating an annotation such as infisical.com/force-sync=<timestamp>, but the controller update predicate skips every update where metadata.generation is unchanged. Kubernetes annotation updates change resourceVersion, not generation, so the event is filtered before Reconcile runs.

Evidence

Installed version in our production cluster: infisical/kubernetes-operator:v0.10.11 / Helm chart secrets-operator 0.10.11.

Live UAT-safe probe on an existing InfisicalSecret:

Before probe:
generation=1
resourceVersion=143173487
force-sync=1777377427
managed Secret resourceVersion=143173484

Command:
kubectl -n idp annotate infisicalsecret idp-backend-infisical \
  infisical.com/force-sync=1779875977 --overwrite

Immediately after:
generation=1
resourceVersion=144324246
force-sync=1779875977
last condition transition=2026-05-05T16:46:12Z
managed Secret resourceVersion=143173484

After 12 seconds:
generation=1
force-sync=1779875977
last condition transition=2026-05-05T16:46:12Z
managed Secret resourceVersion=143173484

I restored the previous annotation value after the probe. No secret values were read or printed.

Source-level cause

At both infisical-k8-operator/v0.10.11 and current latest infisical-k8-operator/v0.10.33, internal/controller/infisicalsecret_controller.go registers an update predicate that returns false when old and new generations match:

UpdateFunc: func(e event.UpdateEvent) bool {
    if e.ObjectOld.GetGeneration() == e.ObjectNew.GetGeneration() {
        return false // Skip reconciliation for status-only changes
    }
    ...
    return true
}

That appears to make annotation-only force-sync updates non-functional by design, unless another periodic requeue happens later.

Expected behavior

If infisical.com/force-sync is a supported manual reconcile trigger, changing that annotation should enqueue reconciliation even though metadata.generation is unchanged.

Requested fix

Please either:

  1. Treat infisical.com/force-sync changes as reconcile-worthy in the update predicate, or
  2. Document that annotation-only force sync is unsupported and operators must change a spec field / wait for periodic requeue instead.

A likely predicate shape would be: allow generation changes, deletion/finalizer cleanup, and explicit force-sync annotation value changes; continue filtering status-only updates.

Impact

During credential incidents, operators may believe the annotation forced an immediate sync, restart workloads, and still reload stale Kubernetes Secret data. The reliable workaround is to patch a spec field such as spec.resyncInterval, which bumps generation and passes the current predicate.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions