Les coulisses du passage en open source de Cap Collectif #1

5 min de lecture.

Après sept années en tant que logiciel propriétaire Cap Collectif a décidé de mettre à disposition l'intégralité du code en open source. Une très bonne nouvelle mais un sacré challenge pour notre équipe de développeurs ! Je vous en dévoile sur ce blog, les coulisses, avec une série d'articles techniques.

Les développeurs travaillent depuis le début de l'aventure sur GitHub dans un dépôt Git privé qui s'appelle cap-collectif/platform. La première étape du passage en open source a consisté à nettoyer celui-ci !

Étape 1 : retirer les secrets du code

Pour fonctionner la plateforme Cap Collectif a besoin de nombreuses informations qui doivent rester confidentielles, comme des mots de passe, des identifiants d'API, etc. : c'est ce qu'on appelle les secrets.

Avec un passage en open source, il n'est plus envisageable de garder ces secrets directement dans le code source. Les retirer est l'étape qui nous a demandé le plus de travail, et ce pour plusieurs raisons :

  • Les secrets utilisés par tous nos environements : développement, intégration continue et production étaient essentiellement en dur dans le code ;
  • Les certificats et secrets utilisés dans les Single Sign On de nos clients étaient également en dur dans le code ;
  • Des IPs de notre infrastructure étaient visibles dans le code pour sécuriser certains accès ;
  • Des identifiants d'API GitHub étaient eux aussi dans le code afin d'accéder à certaines dépendances présentent sur des dépôts Git privés.

Par exemple, les clés d'API étaient en valeur par défaut pour les variables d'environnement dans le fichier config/services.yaml :

parameters:
  mandrill_api_key: '%env(SYMFONY_MANDRILL_API_KEY)%'
  env(SYMFONY_MANDRILL_API_KEY): TOP_SECRET_API_KEY

Pour masquer TOP_SECRET_API_KEY nous avons procédé de la manière suivante :

  • Pour l'environement de dev, nous avons mis en place un fichier .env.local accessible aux développeurs de Cap Collectif via 1Password avec la configuration par défaut de l'environnement de développement. Pour les développeurs externes, un fichier avec des valeurs par défaut est généré, qui devront être remplacées par de véritables secrets.

  • Pour l'environement d'intégration continue, nous précisons les variables d'environnement et leurs valeurs via CircleCI, elles sont ainsi privées et en dehors du code. Il ne reste qu'à les injecter sur notre conteneur docker, pour cela, on utilise la clé environment de la configuration docker-compose :

# docker-compose.yml
services:
  application:
    environment:
      # Set the following variables on CircleCI
      # https://app.circleci.com/settings/project/github/xyz/xyz/environment-variables
      SYMFONY_MANDRILL_API_KEY: ${SYMFONY_MANDRILL_API_KEY}
  • Pour l'environement de production, on a modifié le script de la création de notre image docker, en ajoutant des arguments de build. Lors de la création de l'image docker, on injecte les variables d'environnement directement depuis notre intégration continue :
docker build \
  --file infrastructure/services/production/Dockerfile . \
  --build-arg SYMFONY_MANDRILL_API_KEY=$SYMFONY_MANDRILL_API_KEY

Pour récupèrer la valeur de l'argument dans le Dockerfile, afin de l'injecter en variable d'environnement dans l'image, il resre à ajouter 2 lignes :

# Dockerfile
ARG SYMFONY_MANDRILL_API_KEY="INSERT_A_DEFAULT_VALUE"
ENV SYMFONY_MANDRILL_API_KEY=$SYMFONY_MANDRILL_API_KEY

On est désormais prêt à tout retirer du code !

Avant de commencer, nous avons mis en place en interne un fichier qui recense tous les secrets qui vont être nettoyé, cela nous sera utile pour la suite (voir le prochain article) ! On liste ainsi un secret sur chaque ligne :

# passwords.txt
toto
tata
1234

C'est là que le travail chronophage commence puisqu'il faut identifier chaque secret problématique puis :

  • L'ajouter dans le fichier passwords.txt ;
  • On en profite pour renouveler le secret (mettre à jour sa valeur) ;
  • Ajouter la variable d'environnement et sa valeur en développement, intégration continue et production ;
  • Mettre à jour le code du dépôt Git pour supprimer la valeur présente en dur dans le code.

Évidemment, identifier tous les secrets de presque un million de lignes de code, n'est pas une chose simple…

Une fois que nous pensions avoir tout corrigé, nous avons utilisé GitGuardian afin de faciliter la détection des secrets restants. Cet outil nous a permis d'analyser non seulement l'état actuel du code mais également tout l'historique du dépôt Git, de quoi nous donner encore plus de travail !

Mais il y a une bonne nouvelle, c'est que GitGuardian nous permet désormais de nous assurer qu'aucun nouveau secret ne sera ajouté dans le code, puisque l'intégration continue échouera si c'est le cas, parfait !

Depuis l'écriture de cet article, cette fonctionnalité est désormais également intégrée à GitHub.

Pour les configurations des Single Sign On de nos clients nous avons :

  • Permis une configuration directement intégrée au back-office de l'instance du client, pour les technlogies les plus populaires ;
  • Injecté la configuration à l'aide d'un volume docker depuis notre outil d'infrastructure, lorsque nous avons manqué de temps.

Après avoir passé autant de temps à retirer tous les secrets d'un code source vieux de 7 ans, je peux vous dire que même pour un projet propriétaire, j'adopterais désormais une politique de zéro secrets dans le code dès le démarrage d'un nouveau projet !

Une fois que le code source ne contenait plus de secrets, les choses sérieuses ont commencées…

Voir la partie 2, réécrire définitivement l'historique

Publié le