Dans le monde du config management l’une des plus grandes difficultés reste la gestion des secrets, et notamment de manière dynamique. Bien qu’il comment à y avoir des solutions intéressantes, notamment dans vault, ce ne fût pas le cas pendant très longtemps.
Il y a maintenant presque 10 ans, des personnes se posaient déjà la question pour l’intégration avec Puppet. Malheureusement, le choix fût assez limité, vault que je citais n’existait pas par exemple.
Après réflexion trocla fût choisi. Il s’agit d’une simple librairie ruby qui permet de faire de la gestion clé/valeur. Ce choix a été fait pour plusieurs raisons:
L’intégration dans Puppet se fait par le module duriton/trocla. En plus de pouvoir gérer l’installation de votre contexte Puppet, cela va permettre d’utiliser des helpers spécifiques à Puppet. Pour l’installation cela se fera en deux étapes, l’installation puis la configuration.
Comme dit précédemment, le module contient également des helpers. Le plus intéressant est trocla(KEY, FORMAT, [optional options])
. Celui-ci va nous permettre de récupérer le secret et de le créer si ce dernier n’existe pas. Couplé d’une option d’expiration de votre secret, on se retrouve avec un secret qui effectue des rotations de manière totalement autonome.
Évidemment il est très intéressant d’utiliser trocla dans le dsl Puppet avec vos classes de profiles afin de pouvoir faire des secrets propres à un agent ou bien à un facts de cluster (notamment pour les mots de passe de bdd). Mais il est également possible de faire des appels directement depuis vos hiera avec un petit bout de code en plus dans votre configuration hiera:
---
version: 5
defaults:
datadir: '/etc/puppetlabs/code/hieradata'
data_hash: yaml_data
hierarchy:
- name: Common
path: common.yaml
- name: trocla
lookup_key: trocla_lookup_key
options:
trocla_hierarchy:
- defaults
config: '/etc/puppetlabs/puppet/troclarc.yaml'
Les secrets seront accessibles par la suite de cette manière: "%{lookup('trocla_lookup::<format de la cle>::<nom de la cle>')}"
. Deux cas spécifiques sont à traiter:
.
dans le nom de la clé, caractère interdit qui est utilisé pour définir des clés de hash au format dotPar chance les deux cas se résolvent de la même manière, un exemple regroupant les deux où je souhaite récupérer la clé privée la clé my.key
au format x509 (je stockerais le contenue dans la clé hiera my_variable
:
# I use a fake trocla key with name my_key
my_variable: "%{hiera('trocla_lookup::x509::my_key')}"
# I set some option on my fake key
trocla_options::my_key:
x509: # I use a specifique format to use for this options
render:
keyonly: true
Par la suite une interaction de la part des ops et de certains outils internes ce sont vite fait resentir. Une première version d’un API fût réalisé en interne, mais très restreinte à un cas d’usage. En 2016 j’avais dont initié de refaire une nouvelle API REST afin de pouvoir apprendre le ruby. Bien que je n’ai jamais réussis à finir de coder quelques options (notamment sur la gestion d’acl) j’ai fait le code de troclapi, ce qui a permis aux ops de pouvoir interagir avec trocla sans avoir besoin d’avoir d’accès particuliers (à l’époque backend mysql + chiffrement x509), mais aussi de pouvoir utiliser trocla avec ansible.
Il n’y a pas de ci sur la troclapi car tout était fait sur un Gitlab interne, il y a donc tout ce qu’il faut en gitlab-ci pour faire des tests unitaires, une image docker, de la documentation, une charts helm… (avec intégration harbor)