Skip to content

Commit fcd4cce

Browse files
testing deployment via CICD
1 parent 49f291b commit fcd4cce

3 files changed

Lines changed: 229 additions & 12 deletions

File tree

infrastructure/modules/gateway-test-vm/vm.tf

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,40 @@ resource "azurerm_virtual_machine_run_command" "arc_setup" {
104104
virtual_machine_id = module.gateway_test_vm.resource_id
105105

106106
source {
107-
script = templatefile(
108-
"${path.module}/../../../scripts/powershell/arc-setup.ps1.tftpl",
109-
{
110-
subscription_id = data.azurerm_client_config.current.subscription_id
111-
tenant_id = data.azurerm_client_config.current.tenant_id
112-
resource_group = var.arc_enabled_servers_resource_group
113-
location = var.region
114-
service_principal_id = var.arc_onboarding_spn_client_id
115-
service_principal_secret_b64 = base64encode(data.azurerm_key_vault_secret.arc_onboarding_spn_secret.value)
116-
}
117-
)
107+
script = file("${path.module}/../../../scripts/powershell/arc-setup.ps1")
108+
}
109+
110+
parameter {
111+
name = "SubscriptionId"
112+
value = data.azurerm_client_config.current.subscription_id
113+
}
114+
115+
parameter {
116+
name = "TenantId"
117+
value = data.azurerm_client_config.current.tenant_id
118+
}
119+
120+
parameter {
121+
name = "ResourceGroup"
122+
value = var.arc_enabled_servers_resource_group
123+
}
124+
125+
parameter {
126+
name = "Location"
127+
value = var.region
128+
}
129+
130+
parameter {
131+
name = "ServicePrincipalId"
132+
value = var.arc_onboarding_spn_client_id
133+
}
134+
135+
protected_parameter {
136+
name = "ServicePrincipalSecret"
137+
value = data.azurerm_key_vault_secret.arc_onboarding_spn_secret.value
118138
}
119139

120140
lifecycle {
121-
ignore_changes = [source]
141+
ignore_changes = [source, parameter, protected_parameter]
122142
}
123143
}

scripts/powershell/arc-setup.ps1

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# Combined Azure Arc Evaluation and Onboarding Script
2+
# Parameters are injected by Terraform via azurerm_virtual_machine_run_command
3+
# parameter / protected_parameter blocks — no string interpolation in script text.
4+
param(
5+
[string]$SubscriptionId,
6+
[string]$TenantId,
7+
[string]$ResourceGroup,
8+
[string]$Location,
9+
[string]$ServicePrincipalId,
10+
[string]$ServicePrincipalSecret
11+
)
12+
13+
$ErrorActionPreference = 'Stop'
14+
$logFile = "C:\ArcSetup\ArcSetup.log"
15+
16+
New-Item -Path "C:\ArcSetup" -ItemType Directory -Force | Out-Null
17+
18+
function Write-Log {
19+
param([string]$Message, [string]$Level = 'INFO')
20+
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
21+
$logMessage = "[$timestamp] [$Level] $Message"
22+
Add-Content -Path $logFile -Value $logMessage -Force
23+
Write-Output $logMessage
24+
}
25+
26+
try {
27+
Write-Log "=========================================" "INFO"
28+
Write-Log "Azure Arc Combined Setup Started" "INFO"
29+
Write-Log "=========================================" "INFO"
30+
31+
$CorrelationId = [guid]::NewGuid().ToString()
32+
33+
$env:SUBSCRIPTION_ID = $SubscriptionId
34+
$env:RESOURCE_GROUP = $ResourceGroup
35+
$env:TENANT_ID = $TenantId
36+
$env:LOCATION = $Location
37+
$env:AUTH_TYPE = "principal"
38+
$env:CORRELATION_ID = $CorrelationId
39+
$env:CLOUD = "AzureCloud"
40+
41+
# ============================================
42+
# PHASE 1: Azure Arc Evaluation Preparation
43+
# ============================================
44+
Write-Log "PHASE 1: Preparing VM for Azure Arc Evaluation" "INFO"
45+
Write-Log "-------------------------------------------" "INFO"
46+
47+
Write-Log "STEP 1: Setting MSFT_ARC_TEST environment variable..." "INFO"
48+
[System.Environment]::SetEnvironmentVariable('MSFT_ARC_TEST', 'true', [System.EnvironmentVariableTarget]::Machine)
49+
Write-Log "MSFT_ARC_TEST set to 'true'" "SUCCESS"
50+
51+
Write-Log "STEP 2: Disabling Azure VM Guest Agent..." "INFO"
52+
$service = Get-Service -Name 'WindowsAzureGuestAgent' -ErrorAction SilentlyContinue
53+
if ($service) {
54+
Set-Service WindowsAzureGuestAgent -StartupType Disabled -Verbose
55+
Stop-Service WindowsAzureGuestAgent -Force -Verbose
56+
Get-Process -Name 'WindowsAzureGuestAgent', 'WaAppAgent' -ErrorAction SilentlyContinue | Stop-Process -Force
57+
Start-Sleep -Seconds 3
58+
$serviceStatus = (Get-Service -Name 'WindowsAzureGuestAgent').Status
59+
Write-Log "Azure Guest Agent status: $serviceStatus" "SUCCESS"
60+
} else {
61+
Write-Log "WindowsAzureGuestAgent service not found" "WARNING"
62+
}
63+
64+
Write-Log "STEP 3: Blocking Azure IMDS endpoint (169.254.169.254)..." "INFO" # gitleaks:allow
65+
$existingRule = Get-NetFirewallRule -Name 'BlockAzureIMDS' -ErrorAction SilentlyContinue
66+
if ($existingRule) {
67+
Remove-NetFirewallRule -Name 'BlockAzureIMDS' -Confirm:$false
68+
}
69+
New-NetFirewallRule -Name BlockAzureIMDS `
70+
-DisplayName "Block access to Azure IMDS" `
71+
-Enabled True `
72+
-Profile Any `
73+
-Direction Outbound `
74+
-Action Block `
75+
-RemoteAddress 169.254.169.254 | Out-Null # gitleaks:allow
76+
Write-Log "Azure IMDS endpoint blocked" "SUCCESS"
77+
78+
Write-Log "STEP 4: Verifying Arc Evaluation readiness..." "INFO"
79+
try {
80+
$null = Invoke-RestMethod -Headers @{'Metadata' = 'true' } -Method GET `
81+
-Uri 'http://169.254.169.254/metadata/instance?api-version=2021-02-01' -TimeoutSec 5 -ErrorAction Stop # gitleaks:allow
82+
Write-Log "WARNING: IMDS is still accessible — Arc onboarding may fail." "WARNING"
83+
} catch {
84+
Write-Log "IMDS is blocked as expected" "SUCCESS"
85+
}
86+
87+
Write-Log "Phase 1 completed successfully" "SUCCESS"
88+
89+
# ============================================
90+
# PHASE 2: Azure Arc Agent Installation
91+
# ============================================
92+
Write-Log "PHASE 2: Installing Azure Arc Agent" "INFO"
93+
Write-Log "-------------------------------------------" "INFO"
94+
95+
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072
96+
97+
$azcmagentPath = Join-Path $env:SystemRoot "AzureConnectedMachineAgent"
98+
$tempPath = Join-Path $azcmagentPath "temp"
99+
New-Item -Path $azcmagentPath -ItemType Directory -Force | Out-Null
100+
New-Item -Path $tempPath -ItemType Directory -Force | Out-Null
101+
102+
$installScriptPath = Join-Path $tempPath "install_windows_azcmagent.ps1"
103+
Write-Log "Downloading Azure Connected Machine Agent installer..." "INFO"
104+
Invoke-WebRequest -UseBasicParsing `
105+
-Uri "https://gbl.his.arc.azure.com/azcmagent-windows" `
106+
-TimeoutSec 30 -OutFile "$installScriptPath"
107+
Write-Log "Installer downloaded" "SUCCESS"
108+
109+
Write-Log "Installing Azure Connected Machine Agent..." "INFO"
110+
& "$installScriptPath"
111+
if ($LASTEXITCODE -ne 0) { throw "Installation failed with exit code $LASTEXITCODE" }
112+
Write-Log "Arc agent installed" "SUCCESS"
113+
114+
Start-Sleep -Seconds 5
115+
116+
# ============================================
117+
# PHASE 3: Azure Arc Agent Connection
118+
# ============================================
119+
Write-Log "PHASE 3: Connecting to Azure Arc" "INFO"
120+
Write-Log "-------------------------------------------" "INFO"
121+
122+
$azcmagentExe = "$env:ProgramW6432\AzureConnectedMachineAgent\azcmagent.exe"
123+
if (-Not (Test-Path $azcmagentExe)) { throw "azcmagent.exe not found at $azcmagentExe" }
124+
125+
Write-Log "Subscription : $SubscriptionId" "INFO"
126+
Write-Log "Resource Group: $ResourceGroup" "INFO"
127+
Write-Log "Location : $Location" "INFO"
128+
129+
& "$azcmagentExe" connect `
130+
--service-principal-id "$ServicePrincipalId" `
131+
--service-principal-secret "$ServicePrincipalSecret" `
132+
--resource-group "$ResourceGroup" `
133+
--tenant-id "$TenantId" `
134+
--location "$Location" `
135+
--subscription-id "$SubscriptionId" `
136+
--cloud "$env:CLOUD" `
137+
--tags 'ArcSQLServerExtensionDeployment=Disabled' `
138+
--correlation-id "$CorrelationId"
139+
140+
if ($LASTEXITCODE -ne 0) { throw "Connection failed with exit code $LASTEXITCODE" }
141+
Write-Log "Successfully connected to Azure Arc!" "SUCCESS"
142+
143+
# ============================================
144+
# PHASE 4: Verification
145+
# ============================================
146+
Write-Log "PHASE 4: Final Verification" "INFO"
147+
Write-Log "-------------------------------------------" "INFO"
148+
149+
try {
150+
& "$azcmagentExe" show
151+
Write-Log "Arc agent status retrieved" "SUCCESS"
152+
} catch {
153+
Write-Log "Could not retrieve Arc agent status: $($_.Exception.Message)" "WARNING"
154+
}
155+
156+
try {
157+
Unregister-ScheduledTask -TaskName "ArcSetup" -Confirm:$false -ErrorAction SilentlyContinue
158+
Write-Log "Scheduled task removed" "SUCCESS"
159+
} catch {
160+
Write-Log "Could not remove scheduled task: $($_.Exception.Message)" "WARNING"
161+
}
162+
163+
Write-Log "=========================================" "SUCCESS"
164+
Write-Log "Azure Arc Setup Completed Successfully!" "SUCCESS"
165+
Write-Log "=========================================" "SUCCESS"
166+
exit 0
167+
168+
} catch {
169+
Write-Log "=========================================" "ERROR"
170+
Write-Log "Azure Arc Setup Failed" "ERROR"
171+
Write-Log "=========================================" "ERROR"
172+
Write-Log "Error: $($_.Exception.Message)" "ERROR"
173+
Write-Log "Stack Trace: $($_.ScriptStackTrace)" "ERROR"
174+
175+
$logBody = @{
176+
subscriptionId = "$env:SUBSCRIPTION_ID"
177+
resourceGroup = "$env:RESOURCE_GROUP"
178+
tenantId = "$env:TENANT_ID"
179+
location = "$env:LOCATION"
180+
correlationId = "$env:CORRELATION_ID"
181+
authType = "$env:AUTH_TYPE"
182+
operation = "onboarding"
183+
messageType = $_.FullyQualifiedErrorId
184+
message = "$_"
185+
}
186+
try {
187+
Invoke-WebRequest -UseBasicParsing -Uri "https://gbl.his.arc.azure.com/log" `
188+
-Method "PUT" -Body ($logBody | ConvertTo-Json) | Out-Null
189+
} catch {
190+
Write-Log "Failed to send error log: $($_.Exception.Message)" "WARNING"
191+
}
192+
193+
exit 1
194+
}

scripts/powershell/arc-setup.ps1.tftpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# SUPERSEDED — use arc-setup.ps1 instead.
2+
# This file is no longer referenced. Parameters are now passed via
3+
# azurerm_virtual_machine_run_command parameter / protected_parameter blocks.
14
# Combined Azure Arc Evaluation and Onboarding Script
25
# Values injected by Terraform at provisioning time — no hardcoded credentials
36
# Runs as SYSTEM via Custom Script Extension (once at VM creation)

0 commit comments

Comments
 (0)