Azure Cloud Setup Guide: Before Your First Runbook¶
Owner: Sagar | Time: ~30 min | Phase: 0 (Pre-Flight)
Overview¶
This guide sets up everything needed to run real Azure cloud-level tests. Complete this once before executing any runbooks in SEQUENCING.md.
After this runbook, you'll have: - Azure subscription credentials configured - Terratest harness validated locally - Ready to run F1 (Baseline) as your first cloud test
Prerequisites¶
- Azure subscription created (new or existing)
- Permissions: Owner on the subscription (minimum) or Contributor + User Access Administrator
- GitHub repo cloned:
git clone https://github.com/snowopscloud/snowops-automation.git - Local machine with: bash, Git, Docker (or Go 1.22+ locally)
Part A — Identify Your Azure IDs (2 min)¶
Step 1: Get your subscription ID¶
Note the subscription ID and tenant ID for the one you want to use as sandbox.
Step 2: Export as environment variables¶
Add to your shell profile (~/.zshrc or ~/.bash_profile):
export SNOWOPS_SANDBOX_SUBSCRIPTION_ID="<your-subscription-guid-here>"
export SNOWOPS_SANDBOX_TENANT_ID="<your-tenant-guid-here>"
Verify they load:
source ~/.zshrc # or ~/.bash_profile
echo "Subscription: $SNOWOPS_SANDBOX_SUBSCRIPTION_ID"
echo "Tenant: $SNOWOPS_SANDBOX_TENANT_ID"
Both should print valid GUIDs (e.g., 12345678-1234-1234-1234-123456789012).
Part B — Configure Azure Authentication (5 min)¶
Choose one approach below. Option A (OIDC) is recommended for CI/CD; Option B (Service Principal) is easiest for local testing.
Option A: Azure AD Federated OIDC (for CI/CD)¶
Skip this if you're testing locally. Use for GitHub Actions later.
GitHub Actions workflows use OIDC to avoid long-lived secrets:
# Create a managed identity
az identity create --name snowops-github-actions --resource-group "<your-rg>"
# Configure federated credentials for GitHub
# (This is done in the workflow templates; see: .github/workflows/terraform-plan-apply.yml)
Reference: .github/workflows/terraform-plan-apply.yml (already configured with OIDC).
Option B: Service Principal with Environment Variables (Local Testing) ⭐¶
- Create a service principal:
SUBSCRIPTION_ID="$SNOWOPS_SANDBOX_SUBSCRIPTION_ID"
TENANT_ID="$SNOWOPS_SANDBOX_TENANT_ID"
az ad sp create-for-rbac \
--name "snowops-terraform" \
--role "Contributor" \
--scopes "/subscriptions/$SUBSCRIPTION_ID" \
--query "{clientId:appId, clientSecret:password, tenantId:tenant}" \
--output json
- Save the output and add to your shell profile:
export ARM_CLIENT_ID="<client-id-from-above>"
export ARM_CLIENT_SECRET="<client-secret-from-above>"
export ARM_TENANT_ID="$SNOWOPS_SANDBOX_TENANT_ID"
export ARM_SUBSCRIPTION_ID="$SNOWOPS_SANDBOX_SUBSCRIPTION_ID"
- Test the connection:
az login --service-principal -u "$ARM_CLIENT_ID" -p "$ARM_CLIENT_SECRET" --tenant "$ARM_TENANT_ID"
az account show
Expected: your subscription details print. ✅
Option C: az login Interactively (Simplest)¶
Terraform automatically picks up credentials from az login.
Part C — Install Local Tooling (5 min)¶
macOS (Homebrew)¶
brew install terraform terragrunt kubectl helm checkov gitleaks go
brew tap terraform-linters/tflint && brew install terraform-linters/tap/tflint
brew install conftest
Linux (Ubuntu/Debian)¶
# Terraform
wget https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
unzip terraform_1.6.0_linux_amd64.zip && sudo mv terraform /usr/local/bin/
# Go 1.22+
wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
# Other tools
sudo apt-get install -y kubectl helm gitleaks checkov
Verify Installation¶
terraform --version # >= 1.6
go version # >= 1.22
az --version # >= 2.50
kubectl version --client
helm version
All should print versions without error.
Part D — Run Schema Validation Tests (No Cloud, 5 min)¶
Before touching Azure, validate that the Terraform modules compile correctly:
Expected output: All tests pass (or skip) with no errors. Example:
=== RUN TestBaselineValidate
baseline: Terraform validate
baseline: Terraform plan (no apply)
--- PASS: TestBaselineValidate (3.50s)
=== RUN TestAKSSecureValidate
...
ok github.com/snowopscloud/snowops-automation/tests/terratest 45.12s
If this fails:
- Run terraform init in each fixtures/*/ directory
- Check that SNOWOPS_SANDBOX_SUBSCRIPTION_ID and SNOWOPS_SANDBOX_TENANT_ID are exported
- Verify no syntax errors: terraform validate in modules/azure/baseline
Part E — Understand the Testing Harness (3 min)¶
The repository uses Terratest (Go + Terraform) for integration testing:
tests/terratest/
├── modules/azure/ # 35+ module test files (*_test.go, *_validate_test.go)
├── sandbox/ # Sandbox-level integration tests
├── fixtures/ # 44 minimal Terraform configs for each module
└── helpers/ # Test utilities (terraform.go, azure.go)
Test Pattern:
- *_validate_test.go — schema + plan-only (no cloud, no credentials)
- *_test.go — full apply → assert → destroy (real Azure)
- Both use -tags integration flag to gate cloud tests
Your first cloud test will be F1 (Baseline):
This: 1. Creates a resource group in your sandbox subscription 2. Deploys a Log Analytics workspace + Azure Policy 3. Validates outputs (workspace ID, policy assignment scope) 4. Destroys everything cleanly
Part F — Configure Sandbox Backend (Optional, but Recommended) (5 min)¶
For stateful testing, Terraform can store remote state in Azure Storage. The template exists:
cd sandbox
cp backend.hcl.example backend.hcl
cp terraform.tfvars.example terraform.tfvars
# Edit both files:
# backend.hcl: update storage account name, container, key
# terraform.tfvars: update your subscription ID, resource group, etc.
For now, local state is fine (tests use in-memory state). You'll set this up properly when you reach Phase 8 (Core Infrastructure).
Part G — Verify Everything Works (3 min)¶
Run this final sanity check:
# 1. Env vars
echo "Sub: $SNOWOPS_SANDBOX_SUBSCRIPTION_ID"
echo "Tenant: $SNOWOPS_SANDBOX_TENANT_ID"
# 2. Azure CLI
az account show --query "{subscriptionId:id, displayName:name}" -o table
# 3. Terraform
cd snowops-automation
terraform -v
# 4. Go & Terratest
cd tests/terratest
go version
go test -v -timeout 5m ./... -run TestBaselineValidate
Expected: All commands print output without error. ✅
What's Next?¶
Immediately After This Runbook¶
- Read
docs/runbooks/SEQUENCING.md(full sequence of 44 runbooks) - Start Phase 1 with V2 (offline, ~10 min, no cloud credentials)
- Proceed through phases in order (dependencies matter!)
- When you reach F1 (Phase 8, item 16), you'll run your first cloud test
Milestone: First Cloud Test (F1 Baseline)¶
Once this setup is complete, F1 is your next real cloud test:
cd tests/terratest
go test -v -tags integration -timeout 25m ./modules/azure/... -run TestBaselineModule
Then follow docs/runbooks/test/F1.md (Parts A, B, C).
Troubleshooting¶
| Error | Solution |
|---|---|
go test: can't load package: ... |
Run go mod download in tests/terratest/ |
az: command not found |
Install Azure CLI: brew install azure-cli (macOS) or apt install azure-cli (Linux) |
SNOWOPS_SANDBOX_SUBSCRIPTION_ID not set |
Export in your shell: export SNOWOPS_SANDBOX_SUBSCRIPTION_ID="..." |
unauthorized: authentication required |
Check Azure credentials: az account show should return your subscription |
terraform: command not found |
Add /usr/local/bin to $PATH or reinstall Terraform |
Terratest hangs on InitAndApply |
Azure provisioning is slow (5–15 min for large resources like AKS). Don't interrupt. |
Sign-off¶
- Tester:Sagar Chhabra_ | Date: _14/6/2026___ | Result: PASS
- Notes: (e.g., "Env vars configured, schema tests pass, ready for Phase 1")