Skip to Content
Nouvelle version 12 disponible 🎉

Azure DevOps

Exécutez Babel Obfuscator sur Azure Pipelines en référençant le package NuGet Babel Obfuscator depuis un flux Azure Artifacts privé, la licence étant fournie dans une variable secrète.

Azure Pipelines génère le projet avec le SDK .NET, et le package Babel.Obfuscator insère la tâche Babel dans ce build. Babel n’a pas besoin d’être installé sur l’agent : le package contient les outils de build, et le pipeline doit seulement s’authentifier auprès du flux qui l’héberge et fournir une licence à Babel.

L’exemple utilisé sur cette page est une petite application console :

git clone https://github.com/babelfornet/devops-integration.git

Héberger le package sur un flux Azure Artifacts

Le package Babel.Obfuscator n’est pas publié sur nuget.org : vous le recevez avec l’édition Ultimate ou avec une édition de site de Babel Licensing. Envoyez-le sur un flux privé que seule votre organisation peut lire.

N’envoyez jamais le package Babel Obfuscator sur un flux public. Le package contient les outils de build de Babel, et le republier enfreint les conditions de votre licence.

Dans Azure DevOps, ouvrez Artifacts, créez un flux nommé Babel, puis envoyez-y le package :

dotnet nuget push Babel.Obfuscator.12.0.0.nupkg \ --source "https://pkgs.dev.azure.com/ORGANISATION/_packaging/Babel/nuget/v3/index.json" \ --api-key az

Ajoutez un fichier NuGet.config à côté de la solution afin que votre machine et l’agent de build résolvent tous deux le package depuis ce flux :

NuGet.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <clear /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="babel" value="https://pkgs.dev.azure.com/ORGANISATION/_packaging/Babel/nuget/v3/index.json" /> </packageSources> </configuration>

Les identifiants sont volontairement absents de ce fichier. Sur une machine de développement, l’Azure Artifacts Credential Provider  les demande une seule fois ; dans le pipeline, la tâche NuGetAuthenticate fournit le jeton de l’identité de build. Ni l’un ni l’autre n’écrit de secret dans le dépôt.

Référencer le package

Ajoutez la référence de package à chaque projet dont vous voulez obfusquer l’assembly :

DevOpsIntegration.csproj
<ItemGroup> <PackageReference Include="Babel.Obfuscator" Version="12.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup>

PrivateAssets exclut la référence des packages que produit votre projet : Babel est un outil utilisé à la génération, pas une dépendance de l’assembly livré.

Fournir la licence sous forme de secret

Babel a besoin d’une licence pour produire un assembly qui fonctionne sans limite de durée ; sans licence, il s’exécute en mode d’évaluation et la sortie cesse de fonctionner après une courte période.

Ne validez pas babel.licenses dans le dépôt. Un fichier de licence placé dans un dépôt est lisible par toute personne qui peut lire ce dépôt et par toute personne qui en crée un fork, y compris après la suppression du fichier, car le blob reste accessible dans le fork et dans l’historique du dépôt d’origine.

Stockez plutôt la clé de licence dans une variable secrète. Dans le pipeline, sous Variables, ajoutez BabelLicense et marquez-la comme secrète. Mappez-la ensuite sur une variable d’environnement dans l’étape de build et lisez-la depuis le projet :

DevOpsIntegration.csproj
<PropertyGroup Condition="'$(BABEL_LICENSE)' != ''"> <BabelLicense>$(BABEL_LICENSE)</BabelLicense> </PropertyGroup>

La propriété BabelLicense accepte le chemin d’un fichier de licence, une clé de licence ou une clé utilisateur de licence flottante écrite sous la forme floating:<user key>. Sur un agent de build, ce sont les deux dernières qu’il faut utiliser, car aucune n’exige de fichier sur le disque. En local, la propriété n’est pas définie et Babel utilise le fichier babel.licenses du dossier du projet ou d’un dossier parent : les développeurs continuent donc à travailler sans aucune configuration du pipeline. Voir Configuration du package.

Le pipeline

azure-pipelines.yml
trigger: - main pool: vmImage: ubuntu-latest variables: buildConfiguration: Release steps: - task: UseDotNet@2 displayName: Install the .NET SDK inputs: version: 10.0.x - task: NuGetAuthenticate@1 displayName: Authenticate to the Babel feed - script: dotnet restore DevOpsIntegration.sln displayName: Restore - script: dotnet build DevOpsIntegration.sln --configuration $(buildConfiguration) --no-restore displayName: Build and obfuscate env: BABEL_LICENSE: $(BabelLicense) - task: PublishPipelineArtifact@1 displayName: Publish the obfuscated output inputs: targetPath: DevOpsIntegration/bin/$(buildConfiguration)/net10.0 artifact: DevOpsIntegration

Deux détails méritent d’être signalés.

NuGetAuthenticate@1 est ce qui rend le flux privé accessible. Cette tâche configure le fournisseur d’identifiants avec l’identité propre au pipeline, si bien que le fichier NuGet.config ci-dessus n’a besoin ni d’une section packageSourceCredentials ni d’un jeton personnel.

Les variables secrètes ne sont pas transmises automatiquement aux scripts : c’est tout l’intérêt de les marquer comme secrètes. C’est le bloc env: de l’étape de build qui mappe BabelLicense dans le processus, et c’est le seul endroit où la clé apparaît.

L’obfuscation s’exécute dans le cadre de dotnet build ; il n’y a pas d’étape Babel distincte. Le journal de Babel apparaît dans la sortie du build, et une erreur de licence ou de configuration fait échouer l’étape.

L’image de l’agent doit seulement pouvoir exécuter le SDK .NET. ubuntu-latest est le choix le moins coûteux et convient à tout runtime cible, car Babel travaille sur l’IL : un agent Linux peut obfusquer des assemblies destinés à Windows. Utilisez windows-latest lorsque le build lui-même exige Windows, c’est-à-dire pour les cibles .NET Framework, WPF ou Windows Forms.

Configurer l’obfuscation

Babel se configure avec des propriétés MSBuild dans le fichier de projet. Une organisation courante consiste à ne pas toucher aux builds Debug, pour que le débogage local se comporte normalement, et à protéger les builds Release :

DevOpsIntegration.csproj
<PropertyGroup Condition="'$(Configuration)' == 'Debug'"> <BabelEnabled>false</BabelEnabled> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)' == 'Release'"> <StringEncryption>stream</StringEncryption> <ControlFlowObfuscation>if=on;goto=on;switch=on;case=on;call=on</ControlFlowObfuscation> <ControlFlowIterations>3</ControlFlowIterations> <ResourceEncryption>true</ResourceEncryption> </PropertyGroup>

Toutes les propriétés sont répertoriées dans Référence du package, et Configurer l’obfuscation explique à quelles fonctionnalités de Babel elles correspondent.

Pour tout réglage plus fin qu’une option appliquée à tout l’assembly, ajoutez un fichier de règles. La règle ci-dessous écarte l’obfuscation du flux de contrôle des méthodes courtes, où l’aplatissement coûte plus qu’il ne masque :

babelRules.xml
<?xml version="1.0" encoding="utf-8" ?> <Rules> <Rule name="reduce control flow" feature="control flow" exclude="false" applyToMembers="true"> <Target>Classes,Structures</Target> <Pattern>*</Pattern> <Properties> <MaxSwitchTargets>5</MaxSwitchTargets> <MinInstructionCount>18</MinInstructionCount> <UseValueEncryption>false</UseValueEncryption> </Properties> <Description>Do not scramble methods with few instructions.</Description> </Rule> </Rules>

Indiquez ce fichier au build avec la propriété BabelRules :

<PropertyGroup> <BabelRules>$(MSBuildThisFileDirectory)babelRules.xml</BabelRules> </PropertyGroup>

Vérifier le résultat

Téléchargez l’artefact du pipeline et vérifiez que l’assembly est réellement obfusqué, au lieu de le supposer. L’exemple Détecter l’obfuscation Babel montre comment tester cela automatiquement. Ce test mérite d’être ajouté au pipeline comme point de contrôle : sans lui, une licence mal configurée ou une étape de build ignorée livre un assembly non obfusqué sans rien faire échouer.

Conservez le fichier de mappage produit par le build si vous comptez décoder les traces de pile qui remontent de la production. Voir Décoder les traces de pile.

Last updated on