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/mainOne per environment in environmentsrepo:<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 |
Related pages¶
- Prepare spoke integrations
- Module source access for GitHub Enterprise
- Spoke JSON reference and New spoke