Skip to content

github-workflows-dojo360-azure-infrastructure

Deploy Azure infrastructure using Terraform with PCAM vaulted access and native Azure authentication through Dojo360 Azure Infrastructure workflow

active
IDE:
claude
codex
vscode
Version:
1.0.0
Owner:pcorazao
github-actions
workflow
dojo360

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 azurerm for 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 tfvars files (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_TOKEN secret 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:

InputTypeDescription
aide-idstringAIDE ID to fetch metadata
backend-typestringBackend type for Terraform state (default: azurerm)
cloud-typestringCloud type for metadata (use azureOptum)
domainstringDomain to fetch metadata
environmentstringDeployment environment (dev, qa, crt, prd)
team-namestringTeam name to fetch metadata
terraform-directorystringDirectory path relative to repository with Terraform code

Optional Inputs

InputTypeDefaultDescription
azurerm-backend-configure-inlinebooleantrueConfigure Azure RM backend inline
azure-rolestringcontributorRole assigned to Service Principal for Azure
terraform-prm-secretsstring""Comma-separated list of PRM secrets for Terraform
terraform-vars-filesstring""Comma-separated list of tfvars files
terraform-vars-valuesstring""JSON string of Terraform variables
terraform-versionstring1.9.2Terraform version to use
using-azurebooleantrueConfigure 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:

  1. 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
  2. Setup PCAM Vaulted Access:

  3. 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 resources
  • owner: Full control including RBAC assignments
  • reader: 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:

  1. Verify PCAM setup in HCP Console
  2. Check Service Principal has appropriate roles
  3. Validate vault credentials are active
  4. 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:

  1. Verify backend storage account exists
  2. Check container name and resource group configuration
  3. Ensure Service Principal has Storage Blob Data Contributor role on backend
  4. Validate azurerm-backend-configure-inline is 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-secrets input
  • Secret not configured in PRM
  • Insufficient permissions to access PRM

Solution:

  1. Verify secret names in PRM match exactly
  2. Check PRM configuration at https://prm.optum.com
  3. Ensure team has access to required secrets
  4. 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:

  1. Validate tfvars files exist at specified paths
  2. Check JSON syntax in terraform-vars-values input
  3. Ensure all required variables have values
  4. 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:

  1. Configure required reviewers in GitHub environment settings
  2. Verify environment name matches exactly
  3. Check notification settings for approvers
  4. Review environment protection rule configuration

Related Workflows

Additional Resources

Support

For assistance with this workflow:

Related Assets