Firma de MSIX y canalización de CI/CD con Azure Key Vault
La firma es una de las tareas críticas que se deben realizar cuando se trabaja con paquetes MSIX. Si un paquete MSIX no está firmado con un certificado de confianza, los usuarios no podrán instalar la aplicación. Al mismo tiempo, la firma también es una de las tareas más críticas en términos de seguridad. Los certificados se deben almacenar de forma segura para evitar que actores malintencionados puedan volver a usarlos para firmar sus aplicaciones con nuestra identidad. Azure Key Vault es la mejor opción para admitir este requisito.
En este artículo, veremos cómo puede usar Azure Key Vault en una canalización de CI/CD para que podamos firmar automáticamente nuestro paquete MSIX como parte del proceso.
Importante
El proceso que se describe en este artículo se basa en una herramienta de código abierto denominada Azure SignTool, que funciona tanto con Azure Pipelines como con Acciones de GitHub. Si usa Azure Pipelines, también puede usar las extensiones MSIX en combinación con la tarea de Azure Key Vault.
Requisitos previos
- Una cuenta de Azure. Si aún no tiene una cuenta de Azure, comience aquí.
- Una instancia de Azure Key Vault. Para más información, consulte Creación de un almacén.
- Un certificado de firma de paquetes válido importado en Azure Key Vault. El certificado predeterminado generado por Azure Key Vault no funcionará para la firma de código. Para obtener más información sobre cómo crear un certificado de firma de paquetes, vea Crear un certificado para la firma de paquetes.
- Una canalización de CI/CD que genera un paquete de MSIX hospedado en Azure Pipelines o en Acciones de GitHub. Para obtener más información, consulte Configuración de la canalización de CI/CD con el archivo YAML.
Registro de una aplicación en Azure
Para firmar el paquete como parte de la canalización de CI/CD, usaremos una herramienta denominada Azure SignTool. Funciona como la utilidad SignTool estándar incluida en el SDK de Windows 10, pero, en lugar de usar un certificado local, se conecta a Azure Key Vault para usar uno de los certificados disponibles. Sin embargo, para establecer la conexión, primero tenemos que registrar una aplicación en Azure, lo que nos proporcionará las credenciales necesarias para permitir que Azure SignTool se autentique en nuestro servicio de Azure Key Vault.
Abra Azure Portal y elija Azure Active Directory entre los servicios disponibles. Haga clic en Registros de aplicaciones y elija Nuevo registro para iniciar el proceso. Asigne un nombre a la aplicación (por ejemplo, es SignToolForContoso en la siguiente imagen) y, a continuación, deje la configuración predeterminada.
El siguiente paso consiste en tratar la aplicación como un cliente público, ya que estamos en un escenario en el que no se necesita un URI de redireccionamiento. Vaya a la sección Autenticación y, en Configuración avanzada, defina la opción Trate la aplicación como cliente público en Sí.
El último paso consiste en crear un secreto de cliente, que es la contraseña que necesitaremos para la autenticación desde Azure SignTool. Vaya a la sección Certificados y secretos y haga clic en Nuevo secreto de cliente. Asígnele un nombre, elija una expiración y, a continuación, presione el botón Agregar. Se le redirigirá de nuevo a la página principal, donde el secreto se mostrará junto con su valor. Asegúrese de copiarlo y almacenarlo en un lugar seguro. No podrá recuperarlo de nuevo. Al actualizar la página, se aplicará una máscara al secreto y no habrá forma de revelarlo. Su única opción será generar uno nuevo.
Hay un último dato que necesitará guardar junto con el secreto de cliente: el identificador de la aplicación. Vuelva a la página principal de la aplicación (al hacer clic en Información general) y, en la sección superior, busque el valor de Id. de la aplicación (cliente) :
Habilitación del acceso a Azure Key Vault
El siguiente paso consiste en configurar la aplicación de Azure que acabamos de crear para acceder a nuestro servicio de Azure Key Vault. Desde Azure Portal, vaya a la instancia de Azure Key Vault que contiene el certificado que quiere usar para firmar el paquete de MSIX. Vaya a la sección Directivas de acceso y haga clic en Agregar directiva de acceso. La herramienta permite elegir una de las plantillas disponibles para definir los permisos que queremos conceder pero, en nuestro escenario, ninguna de estas opciones es la adecuada. Por lo tanto, es necesario establecer manualmente, mediante las listas desplegables, las siguientes opciones:
- En Permisos clave, habilite la opción Firmar.
- En Permisos de certificado, habilite la opción Obtener.
El último paso importante consiste en especificar qué aplicación tendrá acceso a esta directiva. Haga clic en Seleccionar la entidad de seguridad y busque la aplicación de Azure que ha creado en el paso anterior mediante su nombre. En el ejemplo, se llama SignToolForContoso.
Cuando la haya encontrado, presione Seleccionar. La directiva debe tener un aspecto similar al siguiente.
Una vez completado el proceso, haga clic en Agregar para crear la directiva.
Uso de Azure SignTool para firmar el paquete localmente
Ahora que se ha completado la configuración de Azure, podemos usar Azure SignTool para firmar el paquete. En esta sección, usaremos la herramienta de forma local para familiarizarnos con ella. En las secciones siguientes, la usaremos como parte de una canalización de CI/CD.
La herramienta está disponible como herramienta global de .NET. Asegúrese de tener instalado el SDK de .NET más reciente. A continuación, abra un símbolo del sistema y ejecute el siguiente comando:
dotnet tool install --global AzureSignTool
Ahora puede firmar el paquete con el comando AzureSignTool, que requiere los siguientes parámetros:
kvu
es la dirección URL de Azure Key Vault. Puede buscarla en la página principal del servicio de Azure Portal, en Nombre DNS.kvi
es el identificador de la aplicación de Azure que ha registrado y anotado previamente.kvs
es el secreto de cliente que ha generado y anotado previamente.kvc
es el nombre descriptivo del certificado que quiere utilizar.tr
es la dirección URL de un servidor de marca de tiempo. Al utilizar esta opción, podemos permitir que el paquete siga funcionando una vez que expire el certificado.v
es la ruta de acceso del paquete de MSIX que queremos firmar.
Este es un comando de ejemplo:
AzureSignTool sign -kvt "<tenantID>" -kvu "https://contosoexpenses-blog.vault.azure.net/" -kvi "64fae35e-cb84-4b9f-86eb-5170d169316d" -kvs "this-is-the-secret" -kvc "MyCertificate" -tr http://timestamp.digicert.com -v .\MyContosoApp.msix
Nota
Para obtener más información sobre AzureSignTool, ejecute AzureSignTool sign --help
.
Uso de Azure SignTool con Azure Pipelines
En esta sección se supone que ya tiene una canalización de CI/CD para una aplicación Windows configurada con un archivo YAML en Azure Pipelines, como se explica aquí.
En primer lugar, tendrá que crear algunas variables para almacenar la información que Azure SignTool requiere para conectarse a Azure Key Vault. En Azure DevOps, seleccione la canalización y presione el botón Editar en la parte superior. Desde el editor de YAML, haga clic en el botón Variables de la parte superior para abrir el panel. A continuación, haga clic en el botón + para agregar las siguientes variables:
- AzureKeyVaultName, con el nombre descriptivo del almacén.
- AzureKeyVaultUrl, con la dirección URL del almacén.
- AzureKeyVaultClientId, con el identificador de la aplicación de Azure.
- AzureKeyVaultClientSecret, con el secreto de cliente de la aplicación de Azure.
Al crear cada variable, asegúrese de habilitar la opción Mantener este valor como secreto. Esto garantizará que otras personas que tienen acceso a la canalización no podrán ver sus valores.
Ahora puede personalizar la canalización de YAML existente mediante la adición de una tarea de .NET Core para instalar Azure SignTool en el agente. Este es el código YAML que se va a agregar:
- task: DotNetCoreCLI@2
displayName: 'Install Azure SignTool'
inputs:
command: custom
custom: tool
arguments: 'install --global AzureSignTool'
El siguiente paso consiste en agregar una tarea de PowerShell para ejecutar el comando que firmará el paquete. Debe realizar esta tarea solo al final del proceso de compilación, una vez creado el paquete MSIX.
- powershell: '& AzureSignTool sign -kvu $(AzureKeyVaultUrl) -kvi $(AzureKeyVaultClientId) -kvs $(AzureKeyVaultClientSecret) -kvc $(AzureKeyVaultName) -tr http://timestamp.digicert.com -v "$(System.DefaultWorkingDirectory)\MyPipeline\MyContosoApp\MyContosoApp.msix"'
displayName: 'Sign the package'
El comando es similar al que hemos usado para firmar el paquete localmente. Las únicas diferencias son:
- En lugar de usar valores fijos para los distintos parámetros, usamos las variables que hemos creado con la sintaxis $(Nombre-Variable) .
- La ruta de acceso del paquete MSIX apunta a la carpeta del agente en que se crea el paquete MSIX al final de la compilación.
Uso de Azure SignTool con Acciones de GitHub
En esta sección se supone que ya tiene una canalización de CI/CD para una aplicación para Windows configurada con un archivo YAML en Acciones de GitHub, como se explica aquí.
Como primer paso, tal y como lo hicimos en Azure Pipelines, es necesario almacenar las credenciales de forma segura. GitHub usa secretos y se pueden agregar en la configuración del repositorio. Una vez que esté en el repositorio de GitHub que hospeda la aplicación para Windows, haga clic en Configuración y, a continuación, pase a Secretos.
De forma similar a lo que hizo con Azure Pipelines, haga clic en Nuevo secreto para crear cuatro secretos:
- AzureKeyVaultName, con el nombre descriptivo del almacén.
- AzureKeyVaultUrl, con la dirección URL del almacén.
- AzureKeyVaultClientId, con el identificador de la aplicación de Azure.
- AzureKeyVaultClientSecret, con el secreto de cliente de la aplicación de Azure.
La diferencia con Azure Pipelines es que los secretos están ocultos implícitamente, por lo que no tendrá que habilitar ninguna opción para protegerlos.
Ahora, desde la pestaña Acciones del repositorio, puede abrir el flujo de trabajo existente y agregar las tareas que necesita para la firma. La primera instalará la herramienta AzureSign en el agente:
- name: Install AzureSignTool
run: dotnet tool install --global AzureSignTool
La segunda firmará el paquete y, como tal, debe ejecutarse una vez completada la compilación de Visual Studio y generado el paquete MSIX.
- name: Sign package
run: |
Get-ChildItem -recurse -Include **.msix | ForEach-Object {
$msixPath = $_.FullName
& AzureSignTool sign -kvu "${{ secrets.AzureKeyVaultUrl }}" -kvi "${{ secrets.AzureKeyVaultClientId }}" -kvs "${{ secrets.AzureKeyVaultClientSecret }}" -kvc ${{ secrets.AzureKeyVaultName }} -tr http://timestamp.digicert.com -v $msixPath
}
Hay algunas diferencias entre esta tarea y la que usamos en Azure Pipelines. La primera es que GitHub usa una sintaxis diferente para acceder a los secretos, que es ${{ secrets.NOMBRE_SECRETO }}. Como tal, los distintos parámetros se rellenan con los valores que hemos creado anteriormente en la sección Secretos. La otra es que necesita usar un enfoque diferente para buscar los paquetes MSIX que se deben firmar. La tarea, en lugar de apuntar a un paquete MSIX concreto, usa un script de PowerShell que recorre en iteración todos los archivos almacenados en la salida de la compilación. Si el archivo tiene la extensión MSIX, usará el comando AzureSignTool para firmarlo.
Implementar el paquete
Independientemente de la plataforma de CI/CD que elija, al final del flujo tendrá un paquete MSIX firmado con el certificado almacenado en Azure Key Vault. Ahora puede usar cualquier otra tarea disponible para implementar el paquete con su opción de distribución preferida: Microsoft Store, un sitio web, Microsoft Intune, etc.