Skip to content

MicrosoftCloudEssentials-LearningHub/Azure-ArtifactSigning-DevOps

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Demo: Azure Artifact Signing (GitHub Actions + Terraform)

Costa Rica

GitHub brown9804

Last updated: 2026-02-19


In GitHub Actions, code signing is an automated workflow step that runs after build, using a cloud‑hosted certificate where the private key never leaves Azure. The workflow then uses SignTool + the Artifact Signing dlib to call the service endpoint associated with those resources.

  • “Trusted Signing” = service branding/experience
  • “Microsoft.CodeSigning/*” = the deployable Azure resources you manage with Terraform/ARM.
List of References (Click to expand)
Table of Content (Click to expand)
image

Overview

This repo is a minimal, demo-friendly setup for:

  • Provisioning Azure Artifact Signing (Trusted Signing) resources with Terraform.
  • Building a small Windows .NET executable.
  • Signing it in GitHub Actions using SignTool + Artifact Signing dlib (private key stays in Microsoft-managed HSMs).
image

Note

This report Microsoft Included CA Certificate List lists all the Certificate Authorities (CAs) whose root certificates are trusted by Microsoft products (Windows, Azure, etc.) and are included in the Microsoft Root Store. From List of Participants - Microsoft Trusted Root Program. When you use Azure Artifact Signing (Trusted Signing):

  • Microsoft leverages certificates from trusted CAs in this program.
  • For public trust signing, the certificates chain back to one of these Microsoft‑trusted root CAs.
  • For private trust signing, you can use enterprise CAs that are not necessarily in the public root store but are trusted within your organization.
  • Specialized certificates (like VBS enclave signing) are also issued under this framework.

Explicit Certificate Types You’ll Encounter (From both Azure Artifact Signing and the Microsoft Trusted Root Program):

  • Code Signing Certificates (for executables, installers, drivers).
  • SSL/TLS Certificates (for secure communications).
  • S/MIME Certificates (for email signing/encryption).
  • Timestamping Certificates (to ensure signatures remain valid after certificate expiry).

Prereqs

  • Azure CLI installed and logged in (az login)

  • Terraform installed

  • Permission to register resource providers + create resources in your subscription. One-time provider registration (per subscription):

    az provider register --namespace Microsoft.CodeSigning

Artifact Signing → For external/public distribution, where you need Microsoft‑managed certificates that chain to trusted CAs. Read more about it Set up signing integrations to use Artifact Signing

arch_Azure-Artifact-Signing_Demo drawio

Key Vault → For internal/private signing, or when you need to use your own PKI or specialized certs. Read more about Tutorial: Import a certificate in Azure Key Vault

arch_Azure-Artifact-Signing_Demo-BYO

Tip

You could branch logic:

  • External release → Artifact Signing
  • Internal build and test → Key Vault

What Terraform creates

  • Resource group

  • Artifact Signing account (Microsoft.CodeSigning/codeSigningAccounts)

  • Key Vault (RBAC-enabled) for pipeline variables/secrets (created by default)

    image

Note

identity validation + Certificate profile are created in the Azure Portal (service requirement).

image

Optional advanced paths:

  • Terraform can create the certificate profile if you set identity_validation_id and re-run terraform apply.
  • The GitHub Actions workflow can create it if you opt in via AUTO_CREATE_CERT_PROFILE: 'true' in the workflow (requires broader RBAC such as RG Contributor).

When github_enabled = true, Terraform also creates:

  • Entra app registration + service principal for GitHub Actions (OIDC)
  • Federated identity credential for token.actions.githubusercontent.com
image

From What is Artifact Signing?

Note

  • Identity validation itself is portal-only (service requirement). Terraform can’t complete that workflow.
  • The Identity validation Id is not exposed via the Azure management API for the code signing account, so Terraform cannot “wait and fetch” it automatically.
  • Identity validation + certificate profile creation can be done entirely in the portal.
  • If you want Terraform (or the workflow) to create the certificate profile, you must copy the Identity validation Id from the portal.

Deploy with Terraform

Terraform files live in terraform-infrastructure/.

  1. Edit terraform-infrastructure/terraform.tfvars and set a globally-unique account name. By default (github_autodetect = true), Terraform will auto-detect github_owner/github_repo during terraform apply (from GitHub Actions env vars if present, otherwise from your local git origin). github_ref defaults to refs/heads/main unless you set it explicitly. If this repo is not a git clone (for example, you downloaded a zip) or origin is not set to GitHub, autodetect can’t determine the values.

Important

If you're using GitHub Actions, prefer the fully automated bootstrap path below (it configures GitHub OIDC + secrets and runs Terraform for you):

pwsh -NoProfile -ExecutionPolicy Bypass -File .\scripts\bootstrap-github-actions.ps1

Not using the bootstrap script? See the internal runbook: _docs/README.md.

  1. Run Terraform:
cd terraform-infrastructure
terraform init
terraform apply -auto-approve
What this first `terraform apply` does: (Click to expand)
  • Creates the resource group, Artifact Signing account, and Key Vault.
  • Populates Key Vault secrets for the workflow (artifactSigningEndpoint, artifactSigningAccountName, artifactSigningCertificateProfileName).
  • If github_enabled = true: creates the GitHub OIDC Entra app/service principal + federated identity credential, and assigns RBAC so the workflow can read Key Vault secrets and sign.

Important

What it cannot do: Complete Artifact Signing identity validation (this is portal-only).

Identity validation (portal-only). In Azure portal:

  • Open the Artifact Signing account and complete Identity validation.

    image
    Identity.validations.-.Artifact.Signing.Account.mp4
  • Create the certificate profile (use the same name as certificate_profile_name).

certificate.profile.-.how.to.mp4

Optional (Terraform-managed certificate profile):

  • Copy the Identity validation Id (GUID) from the portal.
  • Paste it into identity_validation_id in terraform-infrastructure/terraform.tfvars.
  • Run terraform apply again.

Tip

Goal: You can now, push/merge to main (or run the workflow via workflow_dispatch). The GitHub Actions workflow will build + sign the binaries.

Azure Key Vault for workflow variables

Terraform creates a Key Vault by default and wires RBAC so the workflow can read signing inputs.

Principal Role assigned Why it exists
Your current identity (the identity running terraform apply) Key Vault Secrets Officer Can set secrets during provisioning
GitHub Actions service principal Key Vault Secrets User Can read secrets at workflow runtime

Note

  • This Key Vault is RBAC-enabled (rbac_authorization_enabled = true). You will see access under Key Vault → Access control (IAM) (not under “Access policies”).
  • The GitHub Actions workflow reads them from Key Vault at runtime using the Azure CLI.

Least privilege options:

Setting / choice Effect
keyvault_populate_secrets = false Terraform will not write secrets into Key Vault (you can manage secrets yourself and/or set pipeline variables another way).
keyvault_grant_keys_access_to_current = true Grants your current identity Key Vault Crypto User (lets you view Keys in the portal).
keyvault_grant_certificates_access_to_current = true Grants your current identity Key Vault Certificates User (lets you view Certificates in the portal).
keyvault_grant_administrator_to_current = true Simplest “make the portal work” option (broad permissions): grants your current identity Key Vault Administrator.

Terraform also populates these Key Vault secrets during terraform apply:

Secret name Notes
artifactSigningEndpoint Service endpoint used by the workflow
artifactSigningAccountName Artifact Signing account name
artifactSigningCertificateProfileName Certificate profile name
artifactSigningIdentityValidationId Optional. Only needed if Terraform or the workflow will create the certificate profile.

If signing fails with 403, validate:

Check Expected
Endpoint matches region artifactSigningEndpoint points to the correct region
Role at certificate profile scope GitHub Actions identity has Artifact Signing Certificate Profile Signer at the certificate profile scope

GitHub Actions

This repo includes a GitHub Actions workflow that performs the signing flow:

  • build/publish unsigned exe
  • load signing inputs from Key Vault
  • sign + verify + upload artifact

Workflow file:

GitHub OIDC

In this repo, OIDC + GitHub secrets are configured automatically by the bootstrap step in Deploy with Terraform.

Why this exists:

  • GitHub Actions must authenticate to Azure to (1) read signing inputs from Key Vault and (2) call the Artifact Signing service.
  • OIDC lets GitHub obtain an Azure token without storing an Azure client secret in GitHub.

Note

Manual (service requirement): Complete the Identity validation step in the Azure Portal when prompted.

Total views

Refresh Date: 2026-02-19

About

This demo shows how Azure DevOps can build and digitally sign executables using a cloud‑hosted certificate where the private key never leaves Microsoft managed HSMs. No developer ever touches the certificate. Please refer to Microsoft's official documentation or contact Microsoft directly.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors