Skip to content

Commit 3003301

Browse files
committed
Creating skill for setting up integration test workflow.
1 parent 99edb78 commit 3003301

1 file changed

Lines changed: 169 additions & 0 deletions

File tree

  • .github/skills/integration-test-prerequisites
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
name: "integration-test-prerequisites"
3+
description: "Set up Azure and GitHub prerequisites for the integration-test workflow using a user-assigned managed identity, OIDC federated credentials, RBAC roles, and environment secrets. Use when troubleshooting AADSTS70025/AADSTS700213 or authorization failures during integration-test workflow runs."
4+
domain: "ci-cd"
5+
confidence: "high"
6+
source: "manual + observed from integration-test OIDC and RBAC troubleshooting"
7+
---
8+
9+
## Context
10+
11+
Use this skill when preparing or repairing prerequisites for `.github/workflows/integration-test.yml`.
12+
13+
This workflow expects:
14+
- OIDC login through `azure/login@v2`
15+
- GitHub environment `integration-test`
16+
- Azure identity with enough permissions to deploy resources and create role assignments in test resource groups
17+
18+
Preferred identity model: user-assigned managed identity (UAMI).
19+
20+
## Required Inputs
21+
22+
Set these values before running commands:
23+
24+
```bash
25+
set -euo pipefail
26+
27+
SUBSCRIPTION_ID="<your-subscription-id>"
28+
TENANT_ID="<your-tenant-id>"
29+
IDENTITY_RESOURCE_GROUP="<resource-group-for-uami>"
30+
IDENTITY_NAME="apiops-cli-integration-test-uami"
31+
APIM_PUBLISHER_EMAIL="<publisher-email>"
32+
33+
GITHUB_OWNER="Azure"
34+
GITHUB_REPO="apiops-cli"
35+
GITHUB_ENVIRONMENT="integration-test"
36+
37+
OIDC_ISSUER="https://token.actions.githubusercontent.com"
38+
OIDC_AUDIENCE="api://AzureADTokenExchange"
39+
```
40+
41+
## Patterns
42+
43+
### 1) Build Correct OIDC Subject Dynamically
44+
45+
Do not hard-code numeric GitHub IDs. Build the subject based on repo OIDC customization settings.
46+
47+
```bash
48+
OIDC_SUBJECT="repo:${GITHUB_OWNER}/${GITHUB_REPO}:environment:${GITHUB_ENVIRONMENT}"
49+
50+
USE_DEFAULT_SUB="$(gh api repos/${GITHUB_OWNER}/${GITHUB_REPO}/actions/oidc/customization/sub --jq '.use_default')"
51+
if [[ "${USE_DEFAULT_SUB}" == "false" ]]; then
52+
OWNER_ID="$(gh api repos/${GITHUB_OWNER}/${GITHUB_REPO} --jq '.owner.id')"
53+
REPO_ID="$(gh api repos/${GITHUB_OWNER}/${GITHUB_REPO} --jq '.id')"
54+
OIDC_SUBJECT="repository_owner_id:${OWNER_ID}:repository_id:${REPO_ID}:environment:${GITHUB_ENVIRONMENT}"
55+
fi
56+
57+
echo "OIDC_SUBJECT=${OIDC_SUBJECT}"
58+
```
59+
60+
### 2) Provision/Reuse UAMI
61+
62+
```bash
63+
az account set --subscription "${SUBSCRIPTION_ID}"
64+
65+
# Create resource group if it doesn't exist
66+
az group create \
67+
--name "${IDENTITY_RESOURCE_GROUP}" \
68+
--location eastus 1>/dev/null || true
69+
70+
# Create or reuse UAMI
71+
az identity create \
72+
--resource-group "${IDENTITY_RESOURCE_GROUP}" \
73+
--name "${IDENTITY_NAME}" 1>/dev/null
74+
75+
IDENTITY_CLIENT_ID="$(az identity show \
76+
--resource-group "${IDENTITY_RESOURCE_GROUP}" \
77+
--name "${IDENTITY_NAME}" \
78+
--query clientId -o tsv)"
79+
80+
IDENTITY_PRINCIPAL_ID="$(az identity show \
81+
--resource-group "${IDENTITY_RESOURCE_GROUP}" \
82+
--name "${IDENTITY_NAME}" \
83+
--query principalId -o tsv)"
84+
```
85+
86+
### 3) Configure Federated Credential
87+
88+
```bash
89+
az identity federated-credential create \
90+
--resource-group "${IDENTITY_RESOURCE_GROUP}" \
91+
--identity-name "${IDENTITY_NAME}" \
92+
--name "github-env-integration-test" \
93+
--issuer "${OIDC_ISSUER}" \
94+
--subject "${OIDC_SUBJECT}" \
95+
--audiences "${OIDC_AUDIENCE}"
96+
```
97+
98+
### 4) Assign Azure RBAC at Subscription Scope
99+
100+
`User Access Administrator` is required for `Microsoft.Authorization/roleAssignments/write` during deployment.
101+
102+
```bash
103+
SCOPE="/subscriptions/${SUBSCRIPTION_ID}"
104+
105+
for ROLE in "Contributor" "User Access Administrator" "Key Vault Administrator" "API Management Service Contributor"; do
106+
az role assignment create \
107+
--assignee-object-id "${IDENTITY_PRINCIPAL_ID}" \
108+
--assignee-principal-type ServicePrincipal \
109+
--role "${ROLE}" \
110+
--scope "${SCOPE}" \
111+
1>/dev/null
112+
done
113+
```
114+
115+
### 5) Set GitHub Environment Secrets
116+
117+
```bash
118+
unset GITHUB_TOKEN GH_TOKEN
119+
120+
gh secret set AZURE_CLIENT_ID \
121+
--repo "${GITHUB_OWNER}/${GITHUB_REPO}" \
122+
--env "${GITHUB_ENVIRONMENT}" \
123+
--body "${IDENTITY_CLIENT_ID}"
124+
125+
gh secret set AZURE_TENANT_ID \
126+
--repo "${GITHUB_OWNER}/${GITHUB_REPO}" \
127+
--env "${GITHUB_ENVIRONMENT}" \
128+
--body "${TENANT_ID}"
129+
130+
gh secret set AZURE_SUBSCRIPTION_ID \
131+
--repo "${GITHUB_OWNER}/${GITHUB_REPO}" \
132+
--env "${GITHUB_ENVIRONMENT}" \
133+
--body "${SUBSCRIPTION_ID}"
134+
135+
gh secret set APIM_PUBLISHER_EMAIL \
136+
--repo "${GITHUB_OWNER}/${GITHUB_REPO}" \
137+
--env "${GITHUB_ENVIRONMENT}" \
138+
--body "${APIM_PUBLISHER_EMAIL}"
139+
```
140+
141+
## Verification
142+
143+
```bash
144+
az identity federated-credential list \
145+
--resource-group "${IDENTITY_RESOURCE_GROUP}" \
146+
--identity-name "${IDENTITY_NAME}" \
147+
--query "[].{name:name,subject:subject,issuer:issuer,audience:audiences[0]}" -o table
148+
149+
az role assignment list \
150+
--assignee-object-id "${IDENTITY_PRINCIPAL_ID}" \
151+
--scope "/subscriptions/${SUBSCRIPTION_ID}" \
152+
--query "[].{role:roleDefinitionName,scope:scope}" -o table
153+
154+
unset GITHUB_TOKEN GH_TOKEN
155+
gh api repos/${GITHUB_OWNER}/${GITHUB_REPO}/environments/${GITHUB_ENVIRONMENT}/secrets --jq '.secrets[].name'
156+
```
157+
158+
## Failure Mapping
159+
160+
- `AADSTS70025`: Missing federated credential for presented subject.
161+
- `AADSTS700213`: Subject mismatch between token claim and federated credential.
162+
- `Microsoft.Authorization/roleAssignments/write`: Missing `User Access Administrator` or `Owner`.
163+
164+
## Anti-Patterns
165+
166+
- Hard-coding `repository_owner_id` and `repository_id` values in docs/scripts.
167+
- Assuming `repo:<owner>/<repo>:environment:<env>` subject when customization is enabled.
168+
- Using only `Contributor` when deployment creates RBAC assignments.
169+
- Using ephemeral `GITHUB_TOKEN` integration auth for `gh secret` management without checking scopes.

0 commit comments

Comments
 (0)