Skip to content

feat(operator): option pour exiger un selector explicite sur FerrVaultSecret #226

Description

@BryanFRD

Package
Which package does this affect? [x] operator [x] crd [ ] docs

Problem / Motivation

selector.names est optionnel, et son absence a un comportement large et implicite :

// api/ferrvault/v1alpha1/secretspec_types.go
// Names is an explicit list of secret keys to sync. When empty, every
// secret in the vault is synced.
//
// +optional
Names []string `json:"names,omitempty"`
// internal/controller/ferrvaultsecret_controller.go:107
reveal, err = ffc.RevealFromVault(ctx, cr.Spec.Vault, cr.Spec.Selector.Names)

Combiné au motif habituel côté consommateur (envFrom: secretRef), toute clé présente dans la vault devient une variable d'environnement du pod. Un administrateur de cluster n'a aujourd'hui aucun moyen d'interdire ce cas.

Deux conséquences, la seconde étant la plus gênante :

  1. Portée initiale trop large. Cas réel rencontré cette semaine sur l'instance FerrTrack interne : la vault ferrtrack, environnement internal, contient 9 clés. L'API n'a besoin que de JWT_ISSUER et JWT_SECRET ; les 7 autres sont les identifiants de la GitHub App, dont GITHUB_APP_PRIVATE_KEY_PEM. Sans selector, cette clé privée se retrouve dans l'environnement du pod de l'API.

  2. Élargissement silencieux dans le temps. Ajouter une clé à la vault modifie l'environnement de tous les pods qui la consomment sans selector, sans changement de CR, sans diff, sans revue. Le rayon d'action d'un secret grandit hors du dépôt GitOps, ce qui est exactement ce qu'on cherche à éviter en le versionnant.

Le comportement actuel est un défaut raisonnable pour démarrer vite. Ce qui manque, c'est la possibilité de le refuser à l'échelle d'un cluster.

Proposed solution

Un flag d'opérateur, sur le modèle de --default-refresh-interval qui existe déjà :

--require-selector   (défaut: false)

Quand il est actif, une FerrVaultSecret dont selector.names est vide n'est pas synchronisée. Le Secret cible n'est ni créé ni modifié, et la condition passe à :

Ready=False  reason=SelectorRequired
message="selector.names is required (operator started with --require-selector)"

SelectorRequired s'aligne sur les motifs existants (MissingKeys, InvalidConnection, AuthFailed, ConnectionNotFound).

Le défaut reste false pour ne rien casser. Les clusters qui veulent la contrainte l'activent, et les CR existantes deviennent visiblement non conformes plutôt que de changer de comportement en silence.

Acceptance

  • Avec --require-selector, une FerrVaultSecret sans selector.names reste Ready=False avec reason=SelectorRequired, et le Secret cible n'est pas écrit.
  • Sans le flag, le comportement actuel est strictement inchangé.
  • Une FerrVaultSecret avec un selector.names non vide se comporte pareil dans les deux modes.
  • Un test couvre le passage de non conforme à conforme : ajouter le selector fait repasser la CR en Ready=True sans redémarrage de l'opérateur.

Out of scope

  • Rendre selector obligatoire dans le schéma du CRD. Ce serait une rupture pour toutes les CR existantes et empêcherait le mode permissif.
  • Une politique par connexion ou par namespace. Le flag global couvre le besoin ; un affinement pourra suivre s'il se révèle nécessaire.

Alternatives considered

Refus à l'admission plutôt qu'à la réconciliation. C'est la meilleure expérience utilisateur : kubectl apply échoue tout de suite au lieu de laisser une CR en Ready=False. Cela relève de #41, qui propose déjà un ValidatingWebhookConfiguration. Les deux sont complémentaires : le webhook attrape à l'écriture, le flag protège les clusters qui ne le déploient pas, et reste le filet quand une CR a été appliquée avant l'installation du webhook. Si #41 est implémenté d'abord, cette règle a naturellement sa place dedans, le flag servant alors à l'activer.

Avertissement sans blocage. Un simple log ou un événement quand selector est vide. Moins intrusif, mais sans effet réel : le cas problématique passe inaperçu jusqu'à l'audit.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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