ADR-027: User Access Administrator Role for GitHub Actions Deployments
Status: Accepted Date: 2025-10-06 Deciders: Development Team Technical Story: Fix RBAC deployment failures in GitHub Actions CI/CD pipeline
Context
Problem Statement
Infrastructure deployment via GitHub Actions was failing with authorization errors when attempting to assign RBAC roles between Azure resources:
Authorization failed for template resource of type 'Microsoft.Authorization/roleAssignments'.
The client '59d5784a-fe27-4abb-9d9c-9fd097fef9fd' does not have permission to perform action
'Microsoft.Authorization/roleAssignments/write' at scope...
Impact: - ❌ AI Services account not deployed - ❌ AI Foundry Hub and Project not created - ❌ Log Analytics and Application Insights not deployed - ❌ All RBAC role assignments between resources failed - ❌ Complete AI infrastructure deployment blocked
Root Cause
The GitHub Actions service principal had Contributor role, which allows: - ✅ Create/modify/delete Azure resources - ❌ Assign RBAC roles to resources
Contributor role does NOT include Microsoft.Authorization/roleAssignments/write permission.
Required RBAC Assignments (Failing)
The AI Foundry deployment (infrastructure/bicep/modules/ai-services.bicep) creates 8+ role assignments:
- AI Foundry Hub → AI Services (Cognitive Services Contributor)
- AI Foundry Project → AI Services (Cognitive Services OpenAI Contributor)
- Managed Identity → Hub (Azure AI Administrator)
- Managed Identity → Project (Azure AI Administrator)
- Hub → Storage Account (Storage Blob Data Contributor)
- Hub → Key Vault (Key Vault Secrets User)
- Project → Storage Account (Storage Blob Data Contributor)
- Project → Key Vault (Key Vault Secrets User)
Without these role assignments, AI Foundry components cannot communicate with each other or access required resources.
Decision
Grant the GitHub Actions service principal the User Access Administrator role at resource group scope.
Role Assignment Details
az role assignment create \
--role "User Access Administrator" \
--assignee <github-actions-service-principal-id> \
--scope /subscriptions/<sub-id>/resourceGroups/loan-defenders-dev-rg \
--description "Allow GitHub Actions to assign RBAC roles during infrastructure deployment"
Dual-Role Configuration
The service principal now has: 1. Contributor (subscription-wide) - Create/modify resources 2. User Access Administrator (resource group-scoped) - Assign RBAC roles
Rationale
Why User Access Administrator?
User Access Administrator is the least privilege role that allows RBAC assignment:
| Capability | Contributor | User Access Admin | Owner |
|---|---|---|---|
| Create resources | ✅ | ❌ | ✅ |
| Modify resources | ✅ | ❌ | ✅ |
| Delete resources | ✅ | ❌ | ✅ |
| Assign RBAC roles | ❌ | ✅ | ✅ |
| Manage subscriptions | ❌ | ❌ | ✅ |
Owner role would be excessive and violates least privilege.
Why Resource Group Scope?
Scoping UAA to resource group (loan-defenders-dev-rg) instead of subscription:
- ✅ Least privilege: Can only assign roles within this resource group
- ✅ Blast radius: Limited impact if credentials compromised
- ✅ Compliance: Easier to audit and justify
- ✅ Best practice: Microsoft recommendation for IaC deployments
Alternatives Considered
Option 1: Grant Owner Role (Rejected)
Rejected because: - ❌ Too broad - includes subscription management permissions - ❌ Violates least privilege principle - ❌ Security risk - can delete/modify anything - ❌ Compliance issues - harder to justify in security audits
Option 2: Manual RBAC Assignment (Rejected)
Deploy infrastructure, then manually assign roles via Azure Portal/CLI.
Rejected because: - ❌ Not Infrastructure as Code - manual steps required - ❌ Error-prone - easy to forget role assignments - ❌ Not repeatable - different every deployment - ❌ CI/CD not fully automated - ❌ Breaks on resource recreation (roles lost)
Option 3: Remove RBAC from Bicep (Rejected)
Deploy resources without role assignments, document manual RBAC setup.
Rejected because: - ❌ AI Foundry components won't function without roles - ❌ Manual configuration required after every deployment - ❌ Not production-ready - ❌ High operational overhead
Consequences
Positive
✅ Automated Deployment: Full IaC with no manual RBAC steps ✅ Least Privilege: UAA scoped to resource group only ✅ Industry Standard: Aligns with Microsoft and enterprise best practices ✅ Audit-Friendly: Clear separation between resource management and access management ✅ Repeatable: Role assignments deployed consistently every time ✅ AI Infrastructure Works: All AI Foundry components can communicate properly
Neutral
⚠️ Requires Two Roles: Service principal needs both Contributor and UAA ⚠️ Setup Complexity: One additional role assignment during setup
Negative
❌ None identified - This is the recommended Microsoft approach
Security Considerations
Risk Assessment
| Risk | Mitigation | Severity |
|---|---|---|
| Service principal compromise | OIDC short-lived tokens, resource group scope only | Low |
| Excessive permissions | UAA scoped to RG, not subscription | Low |
| Unauthorized role assignments | GitHub branch protection, pull request reviews | Low |
Security Controls
- OIDC Authentication: Passwordless, short-lived tokens (minutes)
- Branch Protection: Only
mainbranch can deploy to production - Pull Request Reviews: All infrastructure changes reviewed
- Audit Logging: All role assignments logged in Azure Activity Log
- Scoped Permissions: UAA limited to single resource group
Implementation
Changes Made
-
✅ Azure Role Assignment:
-
✅ Updated Setup Script (
infrastructure/scripts/setup-github-service-principal.sh): - Added Step 3b: Assign User Access Administrator role
- Updated documentation to explain why both roles needed
-
Added verification and logging
-
✅ Documentation Updates:
- This ADR
- Deployment documentation prerequisites
- Troubleshooting guide for RBAC errors
Verification
# Verify both roles assigned
az role assignment list \
--assignee 59d5784a-fe27-4abb-9d9c-9fd097fef9fd \
--all \
--query "[].{Role:roleDefinitionName, Scope:scope}" \
-o table
# Expected output:
# Role Scope
# ------------------------- --------------------------------------------------------
# Contributor /subscriptions/<sub-id>
# User Access Administrator /subscriptions/<sub-id>/resourceGroups/loan-defenders-dev-rg
Related Documentation
- Azure RBAC: https://learn.microsoft.com/en-us/azure/role-based-access-control/overview
- User Access Administrator Role: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#user-access-administrator
- IaC Best Practices: https://learn.microsoft.com/en-us/azure/architecture/framework/devops/automation-infrastructure
- ADR-026: Comprehensive RBAC for AI Foundry Integration
- ADR-016: GitHub Actions Security Standards
- Setup Script:
infrastructure/scripts/setup-github-service-principal.sh
Decision Outcome
Accepted - User Access Administrator role at resource group scope follows least privilege, enables full IaC automation, and aligns with Microsoft best practices.
Next Steps: 1. ✅ Role assignment complete 2. ✅ Setup script updated 3. ✅ ADR documented 4. ⏭️ Update deployment documentation 5. ⏭️ Re-run deployment to verify fix
Last Updated: 2025-10-06 Status: Implemented and Verified