Skip to Content
Nueva versión 12 disponible 🎉

Azure DevOps

Ejecute Babel Obfuscator en Azure Pipelines haciendo referencia al paquete NuGet de Babel Obfuscator desde una fuente privada de Azure Artifacts, con la licencia proporcionada como variable secreta.

Azure Pipelines compila el proyecto con el SDK de .NET, y el paquete Babel.Obfuscator inserta la tarea Babel en esa compilación. No hace falta instalar Babel en el agente: el paquete lleva las herramientas de compilación, y el pipeline solo tiene que autenticarse en la fuente que lo aloja y entregar una licencia a Babel.

El ejemplo que se usa en esta página es una pequeña aplicación de consola:

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

Alojar el paquete en una fuente de Azure Artifacts

El paquete Babel.Obfuscator no está publicado en nuget.org: se recibe con la edición Ultimate o con una edición de sitio de Babel Licensing. Súbalo a una fuente privada que solo su organización pueda leer.

No suba nunca el paquete de Babel Obfuscator a una fuente pública. El paquete contiene las herramientas de compilación de Babel, y volver a publicarlo infringe los términos de su licencia.

En Azure DevOps, abra Artifacts (artefactos), cree una fuente con el nombre Babel y, a continuación, suba el paquete a ella:

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

Añada un archivo NuGet.config junto a la solución para que tanto su equipo como el agente de compilación resuelvan el paquete desde esa fuente:

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>

Las credenciales no figuran en este archivo de forma deliberada. En el equipo de un desarrollador, el Azure Artifacts Credential Provider  las solicita una sola vez; en el pipeline, la tarea NuGetAuthenticate proporciona el token de la identidad de compilación. Ninguno de los dos escribe un secreto en el repositorio.

Hacer referencia al paquete

Añada la referencia de paquete a cada proyecto cuyo ensamblado quiera ofuscar:

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 mantiene la referencia fuera de los paquetes que produce su proyecto: Babel es una herramienta de tiempo de compilación, no una dependencia del ensamblado que se distribuye.

Proporcionar la licencia como secreto

Babel necesita una licencia para producir un ensamblado que funcione de forma permanente; sin ella se ejecuta en modo de evaluación y la salida deja de funcionar al cabo de poco tiempo.

No añada babel.licenses al repositorio. Un archivo de licencia en un repositorio puede leerlo cualquiera que pueda leer el repositorio y cualquiera que lo bifurque, incluso después de que usted elimine el archivo, porque el blob sigue siendo accesible en la bifurcación y en el historial del repositorio original.

En su lugar, guarde la clave de licencia como variable secreta. En el pipeline, en Variables, añada BabelLicense y márquela como secreta. A continuación, asígnela a una variable de entorno en el paso de compilación y léala desde el proyecto:

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

La propiedad BabelLicense acepta la ruta de un archivo de licencia, una clave de licencia o una clave de usuario de licencia flotante escrita como floating:<user key>. En un agente de compilación conviene usar las dos últimas, porque ninguna necesita un archivo en disco. En el equipo local, la propiedad se deja sin definir y Babel toma el archivo babel.licenses de la carpeta del proyecto o de una carpeta superior, de modo que los desarrolladores siguen trabajando sin ninguna configuración del pipeline. Consulte Configuración del paquete.

El 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

Conviene señalar dos detalles.

NuGetAuthenticate@1 es lo que hace accesible la fuente privada. Configura el proveedor de credenciales con la identidad del propio pipeline, de modo que el NuGet.config anterior no necesita ninguna sección packageSourceCredentials ni ningún token suyo.

Las variables secretas no se pasan a los scripts de forma automática: para eso se marcan como secretas. El bloque env: del paso de compilación es el que asigna BabelLicense al proceso, y es el único lugar donde aparece la clave.

La ofuscación se ejecuta como parte de dotnet build; no hay un paso de Babel aparte. El registro de Babel aparece en la salida de la compilación, y un error de licencia o de configuración hace fallar el paso.

La imagen del agente solo tiene que ejecutar el SDK de .NET. ubuntu-latest es la opción más económica y sirve para cualquier entorno de ejecución de destino, porque Babel trabaja sobre el IL: un agente Linux puede ofuscar ensamblados destinados a Windows. Use windows-latest cuando la propia compilación necesite Windows: destinos de .NET Framework, WPF o Windows Forms.

Configurar la ofuscación

Babel se configura con propiedades de MSBuild en el archivo de proyecto. Una práctica habitual es dejar intactas las compilaciones Debug, para que la depuración local se comporte con normalidad, y proteger las compilaciones 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>

Todas las propiedades figuran en Referencia del paquete, y Configuración de la ofuscación explica a qué funciones de Babel corresponden.

Para todo lo que requiera más detalle que un ajuste aplicado a todo el ensamblado, añada un archivo de reglas. La regla siguiente deja la ofuscación del flujo de control fuera de los métodos cortos, donde el aplanamiento cuesta más de lo que oculta:

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>

Indique el archivo a la compilación con la propiedad BabelRules:

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

Verificar el resultado

Descargue el artefacto del pipeline y compruebe que el ensamblado está realmente ofuscado, en lugar de darlo por supuesto. El ejemplo Detección de la ofuscación de Babel muestra cómo comprobarlo de forma automática, y merece la pena añadirlo al pipeline como control: de lo contrario, una licencia mal configurada o un paso de compilación omitido distribuyen un ensamblado sin proteger sin que nada falle.

Conserve el archivo map que produce la compilación si tiene previsto descodificar las trazas de pila que lleguen de producción. Consulte Descodificación de trazas de pila.

Last updated on