Costa Rica
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)
- What is Artifact Signing?
- Artifact Signing
- Artifact Signing pricing
- Quickstart: Set up Artifact Signing
- Set up signing integrations to use Artifact Signing
- List of Participants - Microsoft Trusted Root Program
- Microsoft Included CA Certificate List
- Artifact Signing trust models
- Artifact Signing resources and roles
- Artifact Signing - The Artifact Signing Action allows you to digitally sign your files using a Artifact Signing certificate during a GitHub Actions run - repo
- Tutorial: Assign roles in Artifact Signing
- Artifact Signing certificate management
- Signing example with PowerShell Scripts
- Tutorial: Import a certificate in Azure Key Vault
Table of Content (Click to expand)
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).
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).
-
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
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
Tip
You could branch logic:
- External release → Artifact Signing
- Internal build and test → Key Vault
-
Resource group
-
Artifact Signing account (
Microsoft.CodeSigning/codeSigningAccounts) -
Key Vault (RBAC-enabled) for pipeline variables/secrets (created by default)
Note
identity validation + Certificate profile are created in the Azure Portal (service requirement).
Optional advanced paths:
- Terraform can create the certificate profile if you set
identity_validation_idand re-runterraform 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 RGContributor).
When github_enabled = true, Terraform also creates:
- Entra app registration + service principal for GitHub Actions (OIDC)
- Federated identity credential for
token.actions.githubusercontent.com
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.
Terraform files live in
terraform-infrastructure/.
- Edit
terraform-infrastructure/terraform.tfvarsand set a globally-unique account name. By default (github_autodetect = true), Terraform will auto-detectgithub_owner/github_repoduringterraform apply(from GitHub Actions env vars if present, otherwise from your local gitorigin).github_refdefaults torefs/heads/mainunless you set it explicitly. If this repo is not a git clone (for example, you downloaded a zip) ororiginis 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.ps1Not using the bootstrap script? See the internal runbook: _docs/README.md.
- Run Terraform:
cd terraform-infrastructure
terraform init
terraform apply -auto-approveWhat 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.
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_idinterraform-infrastructure/terraform.tfvars. - Run
terraform applyagain.
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.
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 |
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:
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.
