Param( [string]$Location = "westeurope", [string]$ResourceGroup = "rg-tofu-state", [string]$StorageAccountName = "", [string]$ContainerName = "tfstate", [string]$StateKey = "terraform.tfstate", [switch]$UseAzureAdAuth = $true ) $ErrorActionPreference = "Stop" function Ensure-AzLogin { try { az account show | Out-Null } catch { az login | Out-Null } } Ensure-AzLogin # Resource Group (idempotent) az group create --name $ResourceGroup --location $Location | Out-Null # Storage Account name must be globally unique, 3-24 chars, lowercase letters/numbers if ([string]::IsNullOrWhiteSpace($StorageAccountName)) { $rand = Get-Random -Minimum 100000 -Maximum 999999 $StorageAccountName = ("tofu" + $rand + "state").ToLower() if ($StorageAccountName.Length -gt 24) { $StorageAccountName = $StorageAccountName.Substring(0, 24) } } # Create SA if missing $saExists = $true try { az storage account show -g $ResourceGroup -n $StorageAccountName | Out-Null } catch { $saExists = $false } if (-not $saExists) { az storage account create ` -g $ResourceGroup -n $StorageAccountName -l $Location ` --sku Standard_LRS --kind StorageV2 ` --https-only true --min-tls-version TLS1_2 ` --allow-blob-public-access false | Out-Null } # Enable blob versioning + soft delete (nice safety net for state) az storage account blob-service-properties update ` -g $ResourceGroup -n $StorageAccountName ` --enable-versioning true ` --enable-delete-retention true --delete-retention-days 14 | Out-Null # Create container (try Entra "login" auth first; fallback to account key if needed) $containerCreated = $false try { az storage container create ` --name $ContainerName --account-name $StorageAccountName ` --auth-mode login | Out-Null $containerCreated = $true } catch { $key = az storage account keys list -g $ResourceGroup -n $StorageAccountName --query "[0].value" -o tsv az storage container create ` --name $ContainerName --account-name $StorageAccountName ` --account-key $key | Out-Null $containerCreated = $true } # Write backend.hcl (NO secrets if you keep AzureAD auth + CLI) $backend = @() $backend += "resource_group_name = `"$ResourceGroup`"" $backend += "storage_account_name = `"$StorageAccountName`"" $backend += "container_name = `"$ContainerName`"" $backend += "key = `"$StateKey`"" if ($UseAzureAdAuth) { $backend += "use_azuread_auth = true" } # uses Entra ID :contentReference[oaicite:2]{index=2} Set-Content -Path (Join-Path (Get-Location) "backend.hcl") -Value ($backend -join "`n") -Encoding UTF8 Write-Host "State backend ready:" Write-Host " RG: $ResourceGroup" Write-Host " SA: $StorageAccountName" Write-Host " Container: $ContainerName" Write-Host " Key: $StateKey" Write-Host "Wrote backend.hcl"