Skip to content

Spoke Integrations: Azure DevOps and GitHub

A spoke can create the resources that its team needs to deploy a workload: an Azure DevOps repository and service connection, or a GitHub repository with federated credentials. Both are optional. This page describes the spoke file blocks and what the deployment does with them. The one-time preparation (permissions, GitHub App, pipeline settings) is in Prepare spoke integrations.

If a block is absent from the spoke file, nothing is created and no preparation is needed.

How the service principal gets its credentials

Every spoke has a service principal. How it authenticates depends on the integration you choose:

Configuration Credential
Azure DevOps block with useFederatedCredentials: true, or GitHub extension enabled No secret. The service connection or workflow uses workload identity federation (OIDC).
Azure DevOps block without useFederatedCredentials (default) A secret is generated and stored in the spoke Key Vault together with the client ID.
Neither integration, Key Vault deployed A secret is generated and stored in the Key Vault.
Neither integration, Key Vault not deployed The service principal has no credentials. The team sets them up outside the spoke deployment.

Prefer federated credentials. No secret has to be stored, rotated or leaked.

Azure DevOps

"azdo": {
  "projectName": "<existing project>",
  "repoName": "repo-##wlshortname##-##environment##",
  "serviceConnectionName": "sc-sub-##wlshortname##-##environment##",
  "useFederatedCredentials": true
}
Field Description
projectName Name of the existing Azure DevOps project in which the resources are created.
repoName Repository to create. The repository is created once, if it does not exist. There is one repository, not one per lifecycle environment.
serviceConnectionName Azure Resource Manager service connection to create, for the spoke service principal.
useFederatedCredentials true: workload identity federation, no secret. false (default): secret-based. A federated credential is created on the app registration of the service principal.

The placeholders ##wlshortname## and ##environment## are replaced.

The pipeline that runs the spoke deployment needs project settings and permissions to create these resources. They are listed in Prepare spoke integrations.

GitHub extension

"extensions": {
  "github": {
    "enabled": true,
    "repository": "##wlshortname##-##environment##-repo",
    "repository_visibility": "private",
    "environments": ["dev", "test", "prod"]
  }
}
Field Required Description
enabled yes Default false.
repository yes Name of the repository to create.
organization no GitHub organization. Default: ghinfo.OrganizationName from the common settings.
oidc_issuer no OIDC issuer URL. Default: ghinfo.OidcIssuer.
repository_description no Default: Repository managed by Azure Spoke deployment.
repository_visibility no public, private or internal. Default private.
repository_auto_init no Initialize with a README. Default true.
environment no One environment name for the federated credential. Kept for backward compatibility.
environments no List of environment names. When set, it replaces environment.

Schema support

The extensions block in the spoke schema of some versions allows only apim, acr, servicebus and eventhub (Spoke JSON reference). If the config test rejects extensions.github, the schema of the code version you pin does not include it yet. Check the version before you plan a spoke with this extension.

What is created

  • A repository with the settings above.
  • Federated identity credentials on the spoke service principal, so that workflows sign in to Azure without a secret:

    Credential Subject
    Main branch repo:<organization>/<repository>:ref:refs/heads/main
    One per environment in environments repo:<organization>/<repository>:environment:<environment-name>
  • Actions secrets in the repository for the Azure sign-in.

The secrets that the workflow reads are AZURE_CLIENT_ID, AZURE_TENANT_ID and AZURE_SUBSCRIPTION_ID.

Use it in a workflow

A workflow in the new repository signs in with the federated credential. It needs the id-token: write permission, and for an environment-specific credential, the environment: key of the job:

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production   # must match an environment in the spoke file
    steps:
      - uses: actions/checkout@v4
      - uses: azure/login@v1
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

Environment names

A workflow job can only use a federated credential for an environment that the spoke file lists. If the sign-in fails with a subject mismatch, compare the environment name of the job with environments.

Variants

Scenario Spoke file
Defaults from the common settings enabled, repository, environments
Another organization add organization
GitHub Enterprise Server add organization and oidc_issuer (https://<github host>/_services/token), or set both in ghinfo
One environment (older style) environment instead of environments