Skip to content

Draft: Add the possibility to use an external tool to manage secrets

Frédéric Lespez requested to merge frederic.lespez/tools:secret_management into dev

L'idée de cette MR est de proposer des modifications permettant de gérer les secrets via un outil externe.

Objectifs :

  • Ne jamais avoir de secrets stockés en clair
  • Avoir le choix de l'outil de gestion des secrets
  • Minimiser le couplage entre EOLE3 et l'outil de gestion des secrets
    • Dans le fichiers de configuration (fichiers vars.ini), les secrets seront remplacés par des tokens qui seront utilisés par l'outil identifier le secret correspondant. Le format du token est imposé par l'outil.
      • Exemple : nextcloud_admin_password=my_best_password => nextcloud_admin_password=@@@@nextcloud_admin@@@@
    • L'outil doit accepter une chaîne de caractères en paramètre et envoyer sur la sortie standard (STDOUT) le contenu de la chaîne de caractères avec les tokens remplacés par les secrets correspondants. Autrement dit, l'outil doit se comporter comme une commande 'echo' améliorée remplaçant les tokens par les secrets correspondants
      • Exemple d'utilisation dans un script shell:
        • On transforme la déclaration d'une variable contenant un secret de la façon suivante : adminPassword='mybestsecret' => adminPassword=$(secret_tool '@@@@nextcloud_admin@@@@')
        • Lors de l'exécution la variable adminPassword sera initialisé avec le secret nextcloud_admin
    • L'outil doit lire un fichier (texte) passé en paramètre (values.yaml par exemple) et envoyer sur la sortie standard (STDOUT) le contenu du fichier avec les tokens remplacés par les secrets correspondants. Autrement dit, l'outil doit se comporter comme une commande 'cat' améliorée remplaçant les tokens par les secrets correspondants
      • Exemple d'utilisation avec kubectl:
        • On prépare le fichier values.yaml en remplaçant les secrets par des tokens
        • On transforme l'appel à kubectl de la manière suivante : kubectl apply -f values.yaml => secrets_tool values.yaml|kubectl apply -f -
        • Lors de l'exécution, tous les tokens contenus dans le fichier values.yaml seront remplacés par les secrets correspondants et le résultat sera transmis à kubectl à la volée (sans stockage sur disque).
    • En particulier, le code EOLE3 n'a pas besoin de savoir où sont stockés les secrets, ni sous quelle forme, ni comment ils sont stockés, chiffrés ou déchiffrés.

Configuration au niveau d'EOLE3 (fichier vars.ini)

[secret_management]
enable=false
# Path to secret manager tool
tool_cmd=/path/to/secrets_manager
# Arguments to pass when processing a file containing secrets
tool_args_file=
# Arguments to pass when processing a string containing secrets
tool_args_string=

Exemple de mise en oeuvre avec l'outil secret_manager.py

  • Dans un shell, déclarer une variable SECRETS_MANAGER_MASTER_PASSWORD contenant le "mot de passe maître" utilisé pour chiffrer/déchiffrer les secrets et l'exporter
    read -r -s -p "Enter your master password: " SECRETS_MANAGER_MASTER_PASSWORD
    export SECRETS_MANAGER_MASTER_PASSWORD
  • Remplacer dans tous les fichiers vars.ini les secrets par défaut par des tokens (de la forme @@@@NOM_DU_SECRET@@@@)
    • Exemple :
      adminUser=@@@@keycloak_admin@@@@
  • Dans le fichier vars.ini, paramétrer la section secret_management
    [secret_management]
    enable=true
    # Path to secret manager tool
    tool_cmd=/path/to/secret_handler.py
    # Arguments to pass when processing a file containing secrets
    tool_args_file=-s /path/to/file/secrets.yaml process-file
    # Arguments to pass when processing a string containing secrets
    tool_args_string=-s /path/to/file/secrets.yaml process-string
  • Déployer EOLE3 comme d'habitude. Les secrets seront générés automatiquement et stockés chiffrés dans le fichier /path/to/file/secrets.yaml.
  • Les secrets peuvent être affichés avec la commande suivante
    /chemin/vers/secret_handler.py -s /path/to/file/secrets.yaml display

Notes

  • Certains secrets sont encodés (urlencode) par Jinja2 (lors de l'exécution de la commande build). Comme l'outil de gestion des secrets s'exécute après (dans le deploy par exemple), le token ayant été encodé, il peut ne plus être reconnu par l'outil de gestion des secrets.
    • Pour éviter cela, l'encodage est fait au niveau de curl (paramètres --data-urlencode). La variable peut alors être initialisée avec le secret non encodé.
  • Si la MR !175 (merged) est acceptée, on pourra optimiser un peu le code en centralisant la définition des variables ECHO et CAT.

Limitations

  • Attention aux exécutions simultanées.
    • secrets_manager.py ne gère pas l'exécution de plusieurs instances en simultané.
  • Si les secrets comportent des caractères spéciaux ayant une signification particulière pour bash ou en YAML, cela peut provoquer des erreurs à l'exécution.
    • Pour éviter cela, utiliser, par exemple, des secrets de 30 caractères de long, contenant uniquement des lettres minuscules, majuscules et des chiffres (comportement par défaut de secrets_manager.py).
  • Attention si on utilise des commandes helm ou kubectl comportant plusieurs directives -f
    • secrets_manager.py accepte plusieurs fichiers en paramètres (comme la commande cat). Il faut juste s'assurer que les fichiers values.yaml débute par une ligne --- pour qu'ils puissent être concaténés sans problème

Autre voie pour la gestion des secrets

  • Centraliser tout les secrets dans un objet de type Secret (ou dérivé). Le fichier contenant le description de cet objet est chiffré intégralement ou alors seuls les secrets sont chiffrés.
  • Charger cet objet dans le cluster Kubernetes (en déchiffrant à la volée les secrets ou en utilisant un opérateur dans le cluster pour les déchiffrer à la demande (dans le cluster)
  • Paramétrer tous les charts Helm pour utiliser le nom d'un secret existant au lieu d'utiliser un secret ou un mot de passe en dur

Exemple d'outil : sealed-secrets https://github.com/bitnami-labs/sealed-secrets (anciennement kubeseal)

Inconvénient : Tous les charts doivent offrir la possibilité de donner le nom d'un secret existant. Est-ce le cas de tous les charts ?

Merge request reports