Peut-on vraiment retrouver la dernière modification d’un code avec VS, DevOps, et Git ?

Quand on utilise Git, il arrive qu’un collègue fasse une petite bourde en fusionnant deux branches (du style : annulation des modifications d’un autre collègue, ou suppression de fichiers).

Via Azure DevOps, on ne voit pas que des Commits ont été annulés. Ils sont bien présents dans la branche de destination. Mais si on regarde l’historique d’un fichier impacté par un de nos Commits via Visual Studio, ou Azure DevOps, le commit n’est pas visible. Bien évidemment le fichier résultant n’est pas bon.

Heureusement, il existe une petite commande qui peut vous sauver :


git log --full-history -1 -- .\chemin-vers-un-fichier.cs

Par rapport à VS et DevOps, cette commande l’avantage est que d'afficher le commit de fusion qui a annulé vos modifications. De plus, cette commande est utilisable pour identifier un Commit qui a supprimé un fichier par erreur.

À partir de ce Commit, on peut retrouver la date de la fusion. Via Azure DevOps, il suffit alors d’aller consulter la liste des Push pour avoir une idée plus claire des problèmes posés par cette fusion et établir un plan d’action.

Jérémy Jeanson

Il n’est jamais trop tard…

Désolé pour le silence de ces dernières semaines. La fin d’année a été plutôt compliquée pour moi, et il m’a fallu quelques semaines pour reprendre ma plume.

Je profite de ce post pour vous souhaiter une bonne année 2024, et de beaux projets. Mais aussi la chance d’avoir quelques problèmes techniques à résoudre (juste ce qu’il faut pour progresser).

De mon côté, je reprends mon rythme d’articles hebdomadaire. Pour 2024, je conserve le format d’articles courts qui semble avoir été beaucoup apprécié l’an dernier. Bien évidemment, je rédigerai quelques articles plus longs, avec plusieurs solutions, et arguments. Je privilégierai ce format pour répondra aux questions qui me sont posées hors-ligne, et fournir des retours d’expérience (cela m’a beaucoup été demandé). Vous voyez, je vous écoute ;).

J’en profite pour remercier toutes les personnes qui m’ont contacté via mail, ou LinkedIn en 2023, pour échanger sur .net, et DevOps. J’ai encore un peu de retards, mais je répondrai à tout le monde.

Jérémy Jeanson

Retour sur dependency-check, et son intégration dans Azure DevOps

Cela fait maintenant deux ans que je suis amené à utiliser dependecy-check quotidiennement. Il est temps de vous faire un petit retour sur cet outil, et son intégration dans Azure DevOps.


De quoi s'agit-il ?

OWASP dependency-check sert à identifier les dépendances vulnérables d'une application. Pour atteindre cet objectif, dependency-check doit scanner vos projets, et interroger l'API NVD afin de vérifier celles-ci.


Par où commencer ?

La documentation de dependency-check se trouve ici. Le scan d'une application pouvant être long, on préfèrera confier celui-ci à un serveur de builds.

Même si la documention n'en parle pas beaucoup, il existe une extension pour Azure DevOps. On peut la trouver sur le marketplace de Azure DevOps.

Après installation de celle-ci, il faudra veiller à se procurer une clé pour l'API NVD. Cela se passe ici.


QUID de la configuration ?

La configuration de dedendency-check ne se fait pas au niveau de l'extension, mais sein de chaque pipeline. J'opte habituellement pour les librairies d'Azure DevOps pour stocker la clé de l'API NVD, mais Azure KeyVault fait aussi très bien l'affaire.

Voici un petit exemple de paramétrage de la tâche dependency-check-build-task@6 via YAML:


  - task: dependency-check-build-task@6
    displayName: Dependency Check
    continueOnError: True
    inputs:
      projectName: $(product) $(version)
      scanPath: $(Build.BinariesDirectory)\bin
      additionalArguments: --nvdApiKey ${{ nvdApiKey }}}
      warnOnCVSSViolation: true


La documentation pour Azure DevOps, n'est malheureusement pas très fournie. Mais on peut modifier ou créer sa définition de build via Azure DevOps pour consulter l'ensemble de propriétés de la tâche dependency-check-build-task@6.

Voici quelques captures d'écran pour que vous vous fassiez une petite idée :

Options de la tâche dependency-check

Comme on peut le voir, beaucoup d'options sont disponibles. Certaines peuvent surprendre, comme le fait de pouvoir limiter la version du dependency-check utilisée. J'en parlerai un peu plus tard dans cet article. Au moment de livrer mes conclusions. D'autres permettent d'utiliser pour faire du "quality gate". Ce qui est beaucoup plus intéressant.

L’option continueOnError:true trouvera son explication dans la conclusion ;)

Les options de formats sont les plus intéressantes. Ce sont elles qui permettent de gérer la manière dont dependency-check remonte ses résultats. On peut distinguer deux usages :

  • Le format HTML. Celui-ci produit un fichier qui sera téléchargeable avec les artefacts de builds. Mais l'intégration s'arrêtera là.
  • Le format JUNIT : Qui peut être gérée par AzureDevOps et donc s'afficher telle une liste de tests unitaires. Avec une erreur par librairie comportant une faille connue.

Voici un exemple tiré du marketplace Azure DevOps :

List de tests liés à dependency-check


Quelques particularités liées à .net, et Azure DevOps ?

L'analyse d'une solution .net peut poser quelques difficultés à dependency-check.

Parmi celles-ci on en distinguera deux :

  • dependency-check ne sait pas se rendre compte qu'une application .net utilisant plusieurs technologies. Il n'ira regarder que la liste des librairies .net. Si vous utilisez du javascipt, il n'y fera pas attention.
  • dependency-check ne sait pas utiliser un fichier .sln. Il préfèrera avoir un masque de recherche du style *.csproj ou qu'on lui indique un dossier de DLL à scanner (seule solution si vous avez plusieurs solutions ou que vos projets incluent des projets VB.net).

Du côté d'Azure DevOps, je vous encourage vivement à ne pas utiliser dependency-check avec les agents autohébergés de Microsoft. On préfèrera utiliser un agent de build que l'on héberge soit même (sur un serveur on premise, ou dans Azure par exemple).

La raison est toute simple. dependency-check se connecte à l'API NVD afin de construire une base de données locale des vulnérabilités (cela prendra plusieurs minutes) :

  • Avec un agent que l'on héberge soit même, la base est actualisée lors de la première exécution de la journée. Les exécutions suivantes réutilisent ensuite la base.
  • Avec un agent autohébergé par Microsoft, il faudrait pouvoir utiliser les solutions de cache fournies par Azure DevOps. Malheureusement, la tâche dependency-check-build-task@6 ne semble pas fonctionner correctement quand on lui indique une autre localisation pour sa base que celle par défaut. Cette solution n'est donc pas viable.

Note : dependency-check est une application JAVA. Il faut donc disposer d'un JRE. OpenJDK fait très bien l'affaire.


Mon avis après deux ans

Dependency-check est une bonne solution tant que l'on ne se retrouve pas confronté a ses limites. Comme toute solution du genre, me direz-vous. Oui, mais voilà, on se retrouve encore avec une application qui n’est pas spécialisée dans le .net qui pense pouvoir répondre aux besoins des développeurs .net (oui, ce n'est pas la première fois que je rencontre ce genre de contexte).

Aujourd'hui, les développeurs .net ont des besoins beaucoup plus "pluriels". Ils n'utilisent pas qu'un seul format de projet, n'ont pas qu'un seul langage. Mais surtout, le premier fichier rencontré quand on utilise Visual Studio est un fichier .sln qui n'est pas utilisable ici.

À cela doivent s'ajouter quelques déconvenues :

  • À deux reprises, j'ai constaté que l'interface de gestion des packages nuget de Visual Studio m'indiquait que des dépendances comportaient des failles alors que denpendcy-check ne remontait aucune alerte.
  • Fin décembre, dependency-check m'a remonté une alerte sur une faille qu'il indique lui-même comme aillant été découverte en aout.
  • Durant un peu plus d'une une semaine en novembre dernier, dependency-check n'a pas été utilisable. Quelques erreurs dans dependency-check suite à son passage en version 9 qui ont provoquer quelques problèmes de disponibilité de l'API NVD. C'est dans ces moments que vous découvrez que l'on vous demande d'utiliser un outil Open source qui n'est maintenu que par un développeur. Malheureusement, celui-ci n'est accompagné par aucune entreprise.
  • Le passage en version 9 de dependency-check a été accompagné d'un breacking-change important. Il faut lui fournir une clé d'API NVD. En soi, ce n'est pas un problème. Par défaut, la tâche dependency-check télécharge toujours la dernière version de dependency-check avant de l'utiliser. Sans compter sur le gros bug cité un peu plus tôt qui, le jour où la version 9 a été publiée, il fallait modifier toutes les définitions de builds l'utilisant (quel bonheur, quelle joie). Même s’il est aujourd'hui possible de limiter la version de dependency-check utilisée, empêcheriez-vous la mise à jour d'un produit destiner à garantir la sécurité de vos applications ? De mon côté, j'ai beaucoup de mal à le concevoir.


Conclusion

En tant que développeur .net, je déconseille dependency-check. Un développeur JAVA y trouvera peut-être son bonheur, à condition de ne pas utiliser d'outils automatisant le déploiement et la mise à jour des outils de builds (ce que nous sommes tous amenés à faire un jour afin de gagner en efficacité).

À la place, je recommande Ment Bold (anciennement WhitSource). Celui-ci a en plus l'avantage de vous fournir un rapport relatif aux différentes licences utilisées ainsi que les risques associés. Cela fait quelque temps que je ne l’utilise plus régulièrement, mais j’en ai gardé un très bon souvenir.

Jérémy Jeanson

Comment résoudre l'erreur WIX0217 avec une solution .net 8 ?

Suite à la mise à jour de serveurs de build, je me suis retrouvé avec une bonne grosse erreur de Wix Toolset :

##[error]wix.exe(0,0): Error WIX0217: Error executing ICE action 'ICE02'. The following string format was not expected by the external UI message logger: "Impossible d'accéder au service Windows Installer. Ceci peut se produire si le programme d'installation de Windows n'est pas bien installé. Contactez votre support technique pour assistance.".

Celle-ci se produit lors de l'usage de la tâche DotNetCoreCLI d'Azure Pipeline. Cette tâche cherche à compiler une solution Wix Toolset 4 avec le SDK de .net 8.

Petite étrangeté : la même opération fonctionne très bien dans Visual Studio, ou via la CLI de .net 8.

Quand on connait un peu wix toolset, et que l'on consulte les logs, on se rend vite compte que le problème se produit lors de la validation du msi. La tentation est grande de désactiver cette validation. Surtout, ne faites pas cela. Ne touchez pas à votre projet. Même pas pour ajouter un RunWixToolsOutOfProc (cela ne sert à rien). Le problème n'est pas là. Le problème est lié au serveur de build, et au contexte dans lequel celui-ci s'exécute.

Historiquement, l'erreur 217 se produisait avec wix toolset 3. Celui-ci utilisait un bon vieux vbscript pour exécuter la validation. Aujourd'hui, vbscript n'est plus utilisé, mais le code d'erreur reste le même. J'ai jugé bon de tenter la solution que j'avais déjà documentée il y a quelques années ici.

Il se trouve que le changement du compte du service Windows de l'agent en Compte système local avec l'autorisation d'interagir avec le Bureau résout le problème.

Affectation du Compte système local dans le gestionnaire des services de Windows

Important : ne pas oublier de redémarrer le service après changement de ce compte.

Il s'agit certainement d'un problème pour accéder à une ressource de type PATH, DLL, ou un enregistrement de ressource qui ne peuvent pas être utilisés en dehors de ce contexte.

Jérémy Jeanson

Comment résoudre les problèmes d'accès à Azure Artefact via une build utilisant le SDK de .net 8 ?

Voici un problème qui a un petit goût de réchauffé. Il y a quelques moi j'expliquais ici même la démarche à suivre quand Azure Pipeline dit qu’il est impossible de charger l'index nuget d’Azure Artefact. Aujourd'hui, je reviens avec un sujet très similaire.

Suite à l'installation du SDK .net 8 sur un serveur de build, je me suis retrouvé avec quelques problèmes de builds. Des pipelines hébergés via Azure DevOps Server indiquent avoir des problèmes pour charger l'index d'un repository Azure Artefact.

L'erreur se produit sur une tâche DotNetCoreCLI se trouvant pourtant derrière une tâche NugetCommand(restore).

Si on regarde le log (que je n'ai malheureusement plus sous la main), on constate que la tâche tente d'accéder à Azure Artefact malgré la présence des packages fraichement téléchargés via nuget. La présence du SDK de .net 8 semble changer le comportement par défaut de la CLI.

Pour résoudre ce problème une bonne fois pour toutes, il suffit donc de dire à DotNetCoreCLI de ne pas restaurer les packages nuget. Pour cela, on peut utiliser sa propriété argument et lui passer l'argument --no-restore.

Voici un exemple complet :


steps:
  - task: NuGetToolInstaller@1
  - task: NuGetCommand@2
    displayName: 'NuGet restore'
    inputs:
      restoreSolution: $(solution)
      command: restore
      feedsToUse: config
      nugetConfigPath: 'Sources/nuget.config'
          
  - task: DotNetCoreCLI@2
    displayName: 'Compilation'
    inputs:
      command: build
      projects: '$(solution)'
      arguments: '--no-restore --configuration $(buildConfiguration) --property:Platform=$(buildPlatform)'

Moralité

Les paramètres par défaut, c'est mal. Surtout si vos pipelines reposent dessus.

Jérémy Jeanson