github-workflows-dojo360-azure-infrastructure
Deploy Azure infrastructure using Terraform with PCAM vaulted access and native Azure authentication through Dojo360 Azure Infrastructure workflow
GitHub Copilot Skill: Azure Infrastructure Deployment Workflow
Overview
The Azure Infrastructure workflow (infra-azure.yml) is a specialized Dojo360 workflow for deploying infrastructure to Azure Cloud using HashiCorp Terraform with PCAM (Privileged Cloud Access Management) vaulted access. Unlike the general infrastructure workflow that supports multiple cloud types, this workflow is Azure-specific and leverages native Azure authentication through PRM Privileged workflows.
Key Distinction: This workflow uses PCAM vaulted access exclusively and does not support Service Principals created by end-users. All Azure deployments must use vaulted credentials managed through HCP's PCAM system.
When to Use This Workflow:
- Deploying Azure-specific infrastructure using Terraform
- Leveraging PCAM vaulted access for enhanced security
- Working with Azure environments that require privileged access management
- Deploying Azure resources with AzureRM backend for state management
- Implementing infrastructure as code (IaC) for Azure Cloud subscriptions
Key Features
1. Native Azure Authentication
- Uses Azure-native authentication mechanisms
- Leverages PCAM vaulted access through HashiCorp Vault
- No dependency on user-created Service Principals
- Integrated with HCP Service Principal Management
2. PCAM Vaulted Access
- Secure, managed credential access through HCP
- Dynamic credential generation for Azure operations
- Centralized access management and auditing
- Compliance with enterprise security policies
3. AzureRM Backend Support
- Default backend type is
azurermfor Terraform state - Configurable inline backend configuration
- Support for state management in Azure Storage Accounts
- Resource group, storage account, container, and key configuration
4. Terraform Variable Management
- Support for multiple
tfvarsfiles (comma-separated) - JSON-based variable values for dynamic configuration
- PRM secret integration for sensitive data
- Environment-specific variable management
5. Security & Compliance
- Role-based access control (default: contributor)
- Vaulted credential management
- Audit trail through PCAM
- Enterprise-grade security standards
Prerequisites
Before using this workflow, ensure the following requirements are met:
1. Dojo360 Metadata API Onboarding
- Product must be onboarded to Dojo360 Metadata API
- Alternatively, create a local metadata file
- Reference: Working with CloudBricks
2. PCAM Cloud Account Setup
- Cloud Account (
cloud-account.v2) configured with vaulted access - Verify "Manage Programmatic Access" tab is available in HCP Console
- Setup guide: HCP Manage Programmatic Access
3. Azure Subscription Access
- Valid Azure subscription with appropriate permissions
- Resource group for backend state management (if using azurerm backend)
- Storage account for Terraform state (if using azurerm backend)
4. GitHub Repository Configuration
- Repository must be configured in GitHub with appropriate environments
- Environment-specific approvals configured for production deployments
GH_TOKENsecret configured at repository or organization level
Requirements
- Terraform Version: ~> 1.9.x (default: 1.9.2)
- AzureRM Provider: ~> 3.xx (for Azure operations)
- Backend Type: azurerm (default, configurable)
- GitHub Runner: uhg-runner (for Optum security compliance)
Input Reference
Required Inputs
All Azure Infrastructure deployments require the following inputs:
| Input | Type | Description |
|---|---|---|
aide-id | string | AIDE ID to fetch metadata |
backend-type | string | Backend type for Terraform state (default: azurerm) |
cloud-type | string | Cloud type for metadata (use azureOptum) |
domain | string | Domain to fetch metadata |
environment | string | Deployment environment (dev, qa, crt, prd) |
team-name | string | Team name to fetch metadata |
terraform-directory | string | Directory path relative to repository with Terraform code |
Optional Inputs
| Input | Type | Default | Description |
|---|---|---|---|
azurerm-backend-configure-inline | boolean | true | Configure Azure RM backend inline |
azure-role | string | contributor | Role assigned to Service Principal for Azure |
terraform-prm-secrets | string | "" | Comma-separated list of PRM secrets for Terraform |
terraform-vars-files | string | "" | Comma-separated list of tfvars files |
terraform-vars-values | string | "" | JSON string of Terraform variables |
terraform-version | string | 1.9.2 | Terraform version to use |
using-azure | boolean | true | Configure Azure secrets for Azure Provider |
Required Secrets
GitHub Token (GH_TOKEN)
The workflow requires GH_TOKEN to be configured as a secret:
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Note: GH_TOKEN is automatically passed by GitHub during runtime and must have appropriate permissions for repository operations.
Azure Credentials
Azure credentials are managed through PCAM vaulted access and do not need to be configured as GitHub secrets. The workflow retrieves credentials dynamically from HashiCorp Vault.
Usage Examples
1. Basic Azure Infrastructure Deployment
name: Azure Infrastructure Deployment
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
type: choice
options:
- dev
- qa
- crt
- prd
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: uhg-runner
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
aide-id: "<change me>"
backend-type: "azurerm"
cloud-type: "azureOptum"
domain: "<change me>"
environment: ${{ github.event.inputs.environment }}
team-name: "<change me>"
terraform-directory: "terraform/azure"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
2. Azure Deployment with Custom Backend Configuration
name: Azure Infrastructure with Custom Backend
on:
push:
branches:
- main
paths:
- 'terraform/azure/**'
pull_request:
branches:
- main
paths:
- 'terraform/azure/**'
permissions:
id-token: write
contents: read
jobs:
deploy-azure:
runs-on: uhg-runner
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
aide-id: "<change me>"
backend-type: "azurerm"
cloud-type: "azureOptum"
domain: "<change me>"
environment: "dev"
team-name: "<change me>"
terraform-directory: "terraform/azure"
azurerm-backend-configure-inline: true
azure-role: "contributor"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
3. Azure Deployment with PRM Secrets
name: Azure Infrastructure with PRM Secrets
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
type: choice
options:
- dev
- qa
- prd
permissions:
id-token: write
contents: read
jobs:
deploy-with-secrets:
runs-on: uhg-runner
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
aide-id: "<change me>"
backend-type: "azurerm"
cloud-type: "azureOptum"
domain: "<change me>"
environment: ${{ github.event.inputs.environment }}
team-name: "<change me>"
terraform-directory: "terraform/azure"
terraform-prm-secrets: "db_password,api_key,storage_connection_string"
azure-role: "contributor"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
4. Azure Deployment with Multiple tfvars Files
name: Azure Multi-Environment Deployment
on:
workflow_dispatch:
inputs:
environment:
description: 'Target Environment'
required: true
type: choice
options:
- dev
- qa
- crt
- prd
permissions:
id-token: write
contents: read
jobs:
deploy-multi-env:
runs-on: uhg-runner
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
aide-id: "<change me>"
backend-type: "azurerm"
cloud-type: "azureOptum"
domain: "<change me>"
environment: ${{ github.event.inputs.environment }}
team-name: "<change me>"
terraform-directory: "terraform/azure"
terraform-vars-files: "common.tfvars,${{ github.event.inputs.environment }}.tfvars"
azurerm-backend-configure-inline: true
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
5. Azure Deployment with JSON Variable Values
name: Azure Infrastructure with Dynamic Variables
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
location:
description: 'Azure Location'
required: true
default: 'eastus'
vm_size:
description: 'VM Size'
required: true
default: 'Standard_D2s_v3'
permissions:
id-token: write
contents: read
jobs:
deploy-with-json-vars:
runs-on: uhg-runner
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
aide-id: "<change me>"
backend-type: "azurerm"
cloud-type: "azureOptum"
domain: "<change me>"
environment: ${{ github.event.inputs.environment }}
team-name: "<change me>"
terraform-directory: "terraform/azure"
terraform-vars-values: |
{
"location": "${{ github.event.inputs.location }}",
"vm_size": "${{ github.event.inputs.vm_size }}",
"environment": "${{ github.event.inputs.environment }}"
}
azure-role: "contributor"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
6. Azure Deployment with Custom Role
name: Azure Infrastructure with Custom Role
on:
push:
branches:
- main
paths:
- 'infrastructure/azure/**'
permissions:
id-token: write
contents: read
jobs:
deploy-custom-role:
runs-on: uhg-runner
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
aide-id: "<change me>"
backend-type: "azurerm"
cloud-type: "azureOptum"
domain: "<change me>"
environment: "dev"
team-name: "<change me>"
terraform-directory: "infrastructure/azure"
azure-role: "owner" # Custom role for specific permissions
terraform-version: "1.9.2"
secrets:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
Azure-Specific Configuration
PCAM Vaulted Access Setup
The Azure Infrastructure workflow requires PCAM (Privileged Cloud Access Management) to be configured for your Azure subscription:
-
Verify PCAM Configuration:
- Navigate to HCP Console
- Find your Cloud Account Resource
- Check for "Manage Programmatic Access" tab
- If not present, follow setup guide below
-
Setup PCAM Vaulted Access:
- Follow HCP Manage Programmatic Access Guide
- Configure Service Principal with appropriate roles
- Vault credentials in HashiCorp Vault
- Test access from workflow
-
Verify Authentication:
# In your Terraform code, the Azure provider will use vaulted credentials provider "azurerm" { features {} # Credentials automatically injected by workflow }
AzureRM Backend Configuration
The workflow defaults to using AzureRM backend for Terraform state:
# Example backend configuration (automatically managed by workflow)
terraform {
backend "azurerm" {
resource_group_name = "terraform-state-rg"
storage_account_name = "tfstatestorage"
container_name = "tfstate"
key = "terraform.tfstate"
}
}
Backend Configuration Options:
azurerm-backend-configure-inline: true- Configure backend inline (default)- Backend details fetched from metadata or environment configuration
- State managed in Azure Storage Account
- Locking supported through blob storage
Best Practices
1. Environment-Specific Deployments
Structure your Terraform code to support environment-specific configurations:
terraform/
├── azure/
│ ├── main.tf
│ ├── variables.tf
│ ├── outputs.tf
│ ├── common.tfvars
│ ├── dev.tfvars
│ ├── qa.tfvars
│ ├── crt.tfvars
│ └── prd.tfvars
Use terraform-vars-files input to combine common and environment-specific variables:
terraform-vars-files: "common.tfvars,${{ inputs.environment }}.tfvars"
2. PRM Secret Management
Use PRM secrets for sensitive data instead of hardcoding in tfvars:
with:
terraform-prm-secrets: "db_password,api_key,connection_string"
In your Terraform code:
variable "db_password" {
description = "Database password from PRM"
type = string
sensitive = true
}
3. Role-Based Access Control
Use the azure-role input to specify appropriate permissions:
contributor: Default, can create/manage resourcesowner: Full control including RBAC assignmentsreader: Read-only access (for validation/testing)- Custom roles: Specify custom role names as needed
4. Terraform Version Pinning
Pin Terraform versions for consistency:
with:
terraform-version: "1.9.2" # Specific version for reproducibility
5. Backend State Management
Always use remote backend for state management:
with:
backend-type: "azurerm"
azurerm-backend-configure-inline: true
Ensure backend storage account and container exist before deployment.
6. Approval Gates for Production
Configure GitHub environment protection rules for production deployments:
jobs:
deploy-to-production:
runs-on: uhg-runner
environment:
name: prd
url: https://portal.azure.com
uses: dojo360/pipelines-workflows/.github/workflows/infra-azure.yml@beta
with:
environment: "prd"
# ... other inputs
7. Terraform Directory Structure
Organize Terraform code by cloud provider and environment:
repository-root/
├── terraform/
│ └── azure/
│ ├── networking/
│ ├── compute/
│ ├── storage/
│ └── security/
└── .github/
└── workflows/
└── azure-infrastructure.yml
8. Variable Validation
Validate inputs before deployment:
with:
terraform-vars-values: |
{
"location": "${{ github.event.inputs.location }}",
"environment": "${{ github.event.inputs.environment }}"
}
Troubleshooting
Issue 1: PCAM Authentication Failure
Symptom: Workflow fails with authentication errors or cannot access Azure resources.
Possible Causes:
- PCAM vaulted access not configured
- Service Principal permissions insufficient
- Vault credentials expired or invalid
Solution:
- Verify PCAM setup in HCP Console
- Check Service Principal has appropriate roles
- Validate vault credentials are active
- Review OIDC & Flexible Identity Credential (FIC) documentation
Issue 2: Backend Configuration Errors
Symptom: Terraform fails to initialize backend or cannot access state.
Possible Causes:
- Backend storage account or container does not exist
- Insufficient permissions on backend resources
- Backend configuration mismatch
Solution:
- Verify backend storage account exists
- Check container name and resource group configuration
- Ensure Service Principal has
Storage Blob Data Contributorrole on backend - Validate
azurerm-backend-configure-inlineis set correctly
Issue 3: PRM Secret Not Found
Symptom: Terraform variables from PRM secrets are not populated.
Possible Causes:
- Secret name mismatch in
terraform-prm-secretsinput - Secret not configured in PRM
- Insufficient permissions to access PRM
Solution:
- Verify secret names in PRM match exactly
- Check PRM configuration at https://prm.optum.com
- Ensure team has access to required secrets
- Review PRM secret path configuration
Issue 4: Terraform Variable Errors
Symptom: Terraform plan fails with missing or invalid variable values.
Possible Causes:
- Variable defined in tfvars file but not in variables.tf
- JSON format error in
terraform-vars-values - File path incorrect in
terraform-vars-files
Solution:
- Validate tfvars files exist at specified paths
- Check JSON syntax in
terraform-vars-valuesinput - Ensure all required variables have values
- Review Terraform error messages for specific variable issues
Issue 5: Environment Approval Timeout
Symptom: Workflow waits indefinitely for environment approval.
Possible Causes:
- No reviewers configured for environment
- Incorrect environment name
- Approval notification not received
Solution:
- Configure required reviewers in GitHub environment settings
- Verify environment name matches exactly
- Check notification settings for approvers
- Review environment protection rule configuration
Related Workflows
- Infrastructure Deployment: General multi-cloud infrastructure workflow
- Infrastructure Promotion: Multi-environment promotion workflow
- Terraform Destroy: Infrastructure teardown workflow
- Terraform Operations: State management and lock resolution
Additional Resources
- Dojo360 Workflows Documentation
- HCP Service Principal Management
- HCP PCAM Guide
- Azure Terraform Provider
- Terraform AzureRM Backend
- PRM Documentation
Support
For assistance with this workflow:
- Dojo360 Support: https://dojo360.optum.com/support
- HCP Support: https://docs.hcp.uhg.com/support
- GitHub Issues: Report issues in your repository
- Team Channels: Contact your CloudBricks° team in Microsoft Teams
Related Assets
github-workflows-dojo360-container-cd
Deploy containerized applications to AWS ECS/Azure ACS using Dojo360 Container CD workflow with blue-green and rolling update strategies
Owner: pcorazao
github-workflows-dojo360-container-promotion
Multi-environment container deployment promotion through prescribed deployment paths with automated approval gates and E2E testing
Owner: pcorazao
github-workflows-dojo360-database
Automate database schema updates using Liquibase via the Dojo360 database workflow (with rollback and validation patterns)
Owner: pcorazao
github-workflows-dojo360-database-promotion
Promote Liquibase database changes across environments (dev→qa→cert→prod) with deployment-path validation and approval gates
Owner: pcorazao
github-workflows-dojo360-dockerfile-ci
Build and scan container images from a Dockerfile using Optum golden images and the recommended UHG reusable workflow
Owner: pcorazao
github-workflows-dojo360-dotnet-ci
Build, test, and scan .NET apps using the recommended UHG reusable CI workflow, with optional publish/pack and container builds
Owner: pcorazao

