Comment stocker les configurations d'accès aux environnements de façon sécurisée

icon Tags de l'article : , , ,

Septembre 13, 2019
Bonjour à tous et toutes,

Aujourd'hui on va parler fichiers de configuration, variables d'environnement, stockage, sécurité et contrôleur de source.

Quand je parle de variables d'environnement, je parle par exemple des identifiants pour se connecter à la BDD, des clefs analytics, ou encore d'autres identifiants critiques.
Il s'agit en général de variables que les développeurs doivent posséder pour les environnements intermédiaires (développement, qualification, préproduction) mais pas pour certains environnements (production, analytics, BI, etc.).
Ces variables sont, en général, stockées dans un gros fichier de configuration qui sera utilisé par le logiciel pour ses différentes connexions.

Du coup la question qui revient à CHAQUE fois : comment stocker de façon sécurisée quelque part ces variables, afin que les développeurs puissent y avoir accès facilement, sans pour autant les rendre récupérables par n'importe qui de passage dans la société ?
Exit donc la feuille collée au mur avec les mots de passe.

Dans ces 5 dernières années, je suis passé par plusieurs solutions :
  • Le service production/exploitation qui s'occupe lui-même de renseigner les clefs de production dans le fichier de configuration. Avantage : sécurité, inconvénient : mise à jour des clefs de configuration ultra complexe. (on doit spécifier à chaque fois les champs ajoutés, les champs modifiés, les champs supprimés, etc. et les fails arrivent souvent)
  • Les développeurs ont toutes les clefs de tous les environnements, et ils les remplacent eux-même pour faire des builds en production. Avantage : simple, inconvénient : sécurité très faible.
  • Les fichiers de configuration sont archivés avec la solution. Avantage : ultra simple, inconvénient : aucune sécurité, n'importe qui ayant accès aux sources a accès à tous les environnements.
  • Les clefs sont enregistrés dans un keepass archivé avec la solution, et seules les personnes concernées connaissent son mot de passe. Avantage : sécurité, inconvénient : très chiant à modifier et saisie constante du mot de passe.

Afin de simplifier les choses sur le projet sur lequel je suis, j'ai proposé la solution suivante :
1) Nous avons un fichier config.zip archivé et chiffré avec mot de passe à la racine du projet
2) Nous avons développé un script nommé init.sh, qui a pour mission d'initialiser le projet.
3) Lorsqu'on lance le script init.sh, il va se charger :
  • De vérifier les versions des packages globaux installés (par exemple les versions de NPM, d'Ionic, de Cordova, ...)
  • De demander le mot de passe du fichier config.zip
  • De dézipper le fichier config.zip grâce au mot de passe renseigné, pour récupérer le fichier de configuration .config
  • De supprimer tous les dossiers générés (nodes_modules, www, plugins, etc.)
  • De lancer les commandes nécessaires à l'initialisation du projet (npm i par exemple)
4) Nous avons ajouté une commande "zip:config" qui sert à chiffrer notre fichier de configuration (en saisissant à nouveau le mot de passe)
5) Nous avons ajouté dans le gitignore notre fichier de configuration.

Ainsi, nous pouvons archiver le fichier config.zip qui n'est dézippable qu'avec le mot de passe.
Dès qu'une personne doit mettre à jour le fichier de configuration, elle fait un "npm run zip:config", tape le mot de passe, et archive ensuite le nouveau fichier config.zip.
Dès qu'une personne change de branche ou merge la branche principale dans sa branche, elle a juste à faire un "npm run init", puis de saisir le mot de passe.

Cette solution nous permet de garder un process très simple sans pour autant sacrifier la sécurité du projet !

Voici le fichier init.sh que nous utilisons :

#!/usr/bin/env bash
expectedIonicVersion="5.2."
expectedCordovaVersion="9.0."

echo "Config file password (ask your colleagues):"
read -s password

ionicVersion="$(ionic -v)"

if [[ "$ionicVersion" != "$expectedIonicVersion"* ]]; then
    echo "Wrong Ionic version, you need to install the $expectedIonicVersion"
    exit;
else
    echo Ionic version OK"
fi

cordovaVersion="$(cordova -v | cut -c-5)"

if [[ "$cordovaVersion" != "$expectedCordovaVersion"* ]]; then
    echo "Wrong Cordova version, you need to install the $expectedCordovaVersion"
    exit;
else
    echo "Cordova version OK"
fi

unzip -o -P "$password" config.zip > /dev/null
if [[ $? == 0 ]]; then
  echo "Successfully unzipped the .env file"
else
  echo "Wrong Password for env file"
  exit;
fi

echo "Now removing generated folders..."

rm -rf ./node_modules/
echo "nodes_modules folder removed"

rm -rf ./plugins/
echo "plugins folder removed"

rm -rf ./platforms/
echo "platforms folder removed"

rm -rf ./www/
echo "www folder removed"

npm i

Enfin, voici les commandes qu'on peut trouver dans notre package.json :
{
  "scripts": {
    "zip:config": "zip -o -re config.zip .config",
    "init": "./build-scripts/init.sh"
  }
}

A noter :
  • zip -o -re target origin permet de zipper un fichier de façon chiffrée en demandant un mot de passe
  • read -s password dans le fichier .sh permet de lire un texte saisi sans qu'il s'affiche à l'écran
  • unzip -o -P "$password" config.zip > /dev/null permet de décompresser et déchiffrer le fichier config.zip à l'aide du mot de passe récupéré préalablement
  • Si vous voulez gérer plusieurs fichiers de configuration, par exemple pour l'environnement dev & l'environnement de production, vous pouvez avoir un fichier dev.config.zip et prod.config.zip, et deux scripts d'initialisation, chaque zip ayant son propre mot de passe. Ainsi seules les personnes habilitées pourront dézipper le fichier prod.config.zip :)

En espérant que ça vous soit utile, bon dev à tous et toutes !

Merge request : la checklist

icon Tags de l'article : , ,

Septembre 10, 2019
Hello,

Comme vous le savez peut-être, en plus d'être développeur, je suis le Scrum Master de mon équipe.

Afin d'améliorer la qualité et la stabilité de notre branche de dev principale, j'ai rédigé une petite checklist à utiliser par les développeurs lors des merge requests.

Pourquoi ?
  • Les listes de choses à faire sont souvent oubliées par l'équipe au moment des merge requests. Parfois partiellement (ah mince je n'ai pas testé sur iPhone), et parfois complètement (ah mince, comme c'était un petit dev je pensais que ça n'avait pas d'intérêt de tester).
  • En effet, une checklist a un impact psychologique bien plus puissant qu'une simple liste de choses à faire. Car en cochant, on indique qu'on a, personnellement, bien réalisé la tâche indiquée.
  • Dans l'idéal cette checklist serait à remplacer par un process CI automatisé. Ou en tout cas les étapes automatisables (build, tests, etc.).
  • La checklist peut aussi faire office de code review cheat sheet.
  • La checklist permet d'avoir un historique des merges, et d'en tirer des tendances.
  • Attention cependant : il ne faut pas que la checklist devienne une trop grosse contrainte. Il faut que le rapport besoin de qualité / contraintes soit optimal. Eviter donc d'avoir une liste de 20 étapes de tests avec 20 cases à cocher. Ca servirait juste à gaver votre équipe.
  • Egalement, il faut que l'équipe accepte et valide cette checklist. Vous devez éviter d'imposer ce type de process de force auprès d'une équipe qui n'en voit pas l'intérêt. A vous de sensibiliser votre équipe sur l'importance de la stabilité de vos branches de développement, du temps que ça fera gagner sur le développement, du nombre de bugs que vous éviterez, du fait que ça protégera des builds qui finissent à 21h, etc.

Voici donc cette petite checklist que j'espère avoir suffisamment teasé (à noter que plein d'éléments dans la partie optionnelle ne concernent qu'Angular/Ionic) :

------------------------------- MERGE REQUEST CHECKLIST -------------------------------

Date :
Dev name :
Reviewer name :
Branch :

MANDATORY
☐ It's a product story ? If yes, the PO validated the dev and gave his/her GO.
☐ The target branch (master/dev) was merged into the current branch
☐ No code / lint warnings or errors
☐ It compiles, starts, and was tested on all target devices/browsers
☐ It builds for all target environments (dev, qual, prod)
☐ The CI pipeline is green
☐ The wiki documentation was updated
☐ If the environment changed (global packages, .env file, …), the CI was updated and the team was warned by email

OPTIONAL (code reminders)
☐ PRODUCT : Every complicated choices are explained somewhere (documentation, specifications, comments, etc.)
☐ CODE QUALITY : No //todo or useless logs
☐ CODE QUALITY : No refactoring planned for later
☐ CODE QUALITY : The code is easy to read and understand
☐ COMPONENTS : OnPush on each component
☐ COMPONENTS : Smart/dumb pattern used
☐ PERFORMANCES : takeUntil($onDestroy) pattern applied on subscriptions
☐ PERFORMANCES : the app is fluid to use, no performances drop
☐ ROUTING : the pages routing is consistent and hierarchical
☐ SCSS : Each component is responsible of its look (not its parents)
☐ SCSS : No size calculations in typescript (only CSS for sizes)
☐ TESTS : tested with 360/375/414/768px of width
☐ TESTS : Unit tests written / updated
☐ ACCESSIBILITY : It works with bigger fonts

------------------------------- /MERGE REQUEST CHECKLIST -------------------------------

En espérant que ça vous soit utile,

Bon dev à tous et toutes !

Exposition d'un jeu, AMOUR, au Numerik Games d'Yverdon

icon Tags de l'article : , , ,

Septembre 06, 2019
Hello tout le monde,

Une fois n'est pas coutume, j'avais envie de communiquer sur un évènement ultra cool auquel j'ai pu participer ce weekend : le Numerik Games d'Yverdon !

Il y a 2 mois j'ai participé à une Game Jam (un genre de hackathon sur le thème du jeu vidéo) à Neuchâtel : l'Epic Game Jam.
Avec un collègue et 2 connaissances à lui, on a développé (via Unity3D) un petit jeu de combat basé sur des formes.
Une sorte de Pierre Papier Ciseaux meets Smash Bros jouable à quatre.

L'idée était d'avoir 3 formes, carré, triangle & rond, et que ces formes correspondent aux boutons de la manette de Playstation. Chaque forme était destinée à absorber la suivante (le carré absorbe le triangle, le triangle absorbe le rond, et le rond absorbe le carré).
Le thème de l'Epic Game Jam était en effet que les jeux ne devaient pas contenir de notion de "mort". Et quoi de mieux qu'une fusion des joueurs pour symboliser ça ?
Nous avions donc nommé le jeu AMOUR.

Du coup quelques caractéristiques :
  • L'objectif du jeu était de créer un jeu de combat simple, auquel on peut jouer à 2, 3, 4 et où tout le monde peut s'amuser et gagner
  • Même vaincu, un joueur n'arrête pas de jouer. En effet, à 3/4 joueurs, si le joueur qui vous a absorbé se fait absorber à son tour, il vous "recrache" au passage !
  • L'idée des formes qui match avec les boutons des manettes de Playstation avait pour objectif de simplifier l'assimilation des contrôles.
  • Le jeu peut vite virer en chaos en sans nom, surtout à 4, mais il reste très fun et parfois un joueur gagne sans le vouloir en mode euh il s'est passé quoi ?
  • Le changement de forme a un cooldown de 2 secondes, rendant le joueur vulnérable (si on change en triangle pour manger un rond, un carré qui arrive dans notre dos peut nous avoir)
  • Le jeu est aussi fun en duel, car tout se joue à la forme choisie au moment du contact... du coup il faut anticiper, calculer, choisir si on fonce ou si on esquive, etc.

Voici le jeu à la fin :


Il faut maintenant savoir qu'un des prix de cette Epic Game Jam était que le jeu qui s'y prêterait le plus serait exposé au Numerik Games d'Yverdon, projeté sur un immeuble !

Et c'est notre jeu qui a été choisi au final !

Nous avons donc pu continuer de travailler sur le jeu (en retravaillant les couleurs et en faisant des tests) afin de le rendre le plus adapté à cet évènement.

Voici le résultat final :


Et enfin, projeté sur un batiment au Numerik Games :


Quelques photos en plus :


Avant l'installation


Les bornes d'arcade derrière nous


Les premiers testeurs


Avec des transats, c'est mieux !


VICTOIRE !


Quand les gens n'osaient pas demander, les transats étaient tristes.

C'était une véritable expérience, d'abord la Game Jam, puis tout ce qui a suivi, le rush pour finaliser le jeu, le modifier pour qu'il s'adapte au support, faire fonctionner les nouvelles manettes (à 18h les manettes ne marchaient pas... alors qu'à 21h le jeu devait être installé et jouable !).

J'espère avoir l'occasion de continuer sur ce jeu, mais aussi à travailler sur d'autres jeux. Je commence à me débrouiller pas mal sur Unity ;)

Encore un grand merci à David Javet et aux organisateurs de l'Epic Game Jam !

Je ferai sûrement un autre article à l'occasion pour parler un peu plus de tout ce qu'implique ce genre de projet, de ce qu'on a réussi, ce qui a été difficile, les pièges dans lesquels il faut éviter de tomber, etc.

A suivre,

Bon dev à tous et toutes !

(A noter que c'est article n'est pas sponsorisé, évidemment)