script_automation/arc_endpoint_check/ArcEndpointCheck.ps1 (144 lines of code) (raw):

# Purpose: This script checks the connectivity and status of Azure endpoints, including both static and dynamic endpoints, # and validates Azure Arc functionality. It performs DNS resolution, network connectivity, and HTTP request tests, # logging the results for review. # Disclaimer: This script is intended for use in environments where connectivity to Azure endpoints and Azure Arc services # needs to be validated. It relies on internet access to fetch dynamic endpoints and assumes the presence of `azcmagent.exe` # for Azure Arc checks. Results are logged to a specified file, and proper access control on logs is advised. # Define the region $region = "brazilsouth" # Define the log file path $logFilePath = "C:\temp\Arclogfile.txt" # Ensure log file exists before clearing if (-Not (Test-Path $logFilePath)) { New-Item -ItemType File -Path $logFilePath -Force | Out-Null } else { Clear-Content -Path $logFilePath -ErrorAction SilentlyContinue } # Write start of the log "Script started at $(Get-Date)" | Out-File -FilePath $logFilePath -Append # Define the list of static endpoints $staticEndpoints = @( "login.windows.net", "login.microsoftonline.com", "pas.windows.net", # AAD "management.azure.com", # ARM "global.handler.control.monitor.azure.com", # AMA "gbl.his.arc.azure.com", "agentserviceapi.guestconfiguration.azure.com", # Arc "dataprocessingservice.$region.arcdataservices.com", "telemetry.$region.arcdataservices.com" # ArcData and Telemetry ) # Fetch dynamic endpoints for the specified region try { $logMessage = "Running: Invoke-WebRequest -Uri 'https://guestnotificationservice.azure.com/urls/allowlist?api-version=2020-01-01&location=$region'" $logMessage | Out-File -FilePath $logFilePath -Append $response = Invoke-WebRequest -Uri "https://guestnotificationservice.azure.com/urls/allowlist?api-version=2020-01-01&location=$region" -ErrorAction Stop $dynamicEndpoints = ($response.Content -replace '\[|\]|"|\\n','').Split(',') "Dynamic endpoints fetched: $($dynamicEndpoints -join ', ')" | Out-File -FilePath $logFilePath -Append } catch { "Error fetching dynamic endpoints: $_" | Out-File -FilePath $logFilePath -Append $dynamicEndpoints = @() } # Combine static and dynamic endpoints $allEndpoints = $staticEndpoints + $dynamicEndpoints # List of allowed endpoints for HTTP request $allowedEndpoints = @( "login.windows.net", "login.microsoftonline.com", "dataprocessingservice.$region.arcdataservices.com", "telemetry.$region.arcdataservices.com" ) # Filter the dynamic endpoints to match the allowed list $filteredDynamicEndpoints = $allowedEndpoints # Combine static endpoints with the filtered dynamic endpoints for HTTP requests $finalEndpointsForRequest = $filteredDynamicEndpoints # Iterate over all endpoints to test connectivity, DNS resolution, and HTTP response for the filtered dynamic endpoints foreach ($endpoint in $allEndpoints) { $trimmedEndpoint = $endpoint.Trim() # DNS resolution test $dnsLogMessage = "Testing DNS resolution for: $($trimmedEndpoint)" $dnsLogMessage | Out-File -FilePath $logFilePath -Append try { $logMessage = "Running: Resolve-DnsName -Name $($trimmedEndpoint)" $logMessage | Out-File -FilePath $logFilePath -Append $dnsResult = Resolve-DnsName -Name $trimmedEndpoint -ErrorAction Stop $dnsOutput = "Success: DNS resolution succeeded for $($trimmedEndpoint): $($dnsResult.Name)" Write-Host $dnsOutput -ForegroundColor Green $dnsOutput | Out-File -FilePath $logFilePath -Append } catch { $dnsError = "Error: DNS resolution failed for $($trimmedEndpoint) - $_" Write-Host $dnsError -ForegroundColor Red $dnsError | Out-File -FilePath $logFilePath -Append } # Connectivity test $connectivityLogMessage = "Testing connectivity for: $($trimmedEndpoint)" $connectivityLogMessage | Out-File -FilePath $logFilePath -Append try { $logMessage = "Running: Test-Connection -ComputerName $($trimmedEndpoint) -Count 1" $logMessage | Out-File -FilePath $logFilePath -Append $pingResult = Test-Connection -ComputerName $trimmedEndpoint -Count 1 -ErrorAction Stop $pingOutput = "Success: Connectivity succeeded for $($trimmedEndpoint): Response time: $($pingResult.ResponseTime)ms" Write-Host $pingOutput -ForegroundColor Green $pingOutput | Out-File -FilePath $logFilePath -Append } catch { $pingError = "Error: Connectivity test failed for $($trimmedEndpoint) - $_" Write-Host $pingError -ForegroundColor Red $pingError | Out-File -FilePath $logFilePath -Append } "----------------------------------------" | Out-File -FilePath $logFilePath -Append } # HTTP request test (only for filtered dynamic endpoints) foreach ($endpoint in $finalEndpointsForRequest) { $trimmedEndpoint = $endpoint.Trim() # HTTP request test $httpLogMessage = "Testing HTTP request for: $($trimmedEndpoint)" $httpLogMessage | Out-File -FilePath $logFilePath -Append try { # Measure response time and check for 401 $response_time = Measure-Command { $response = Invoke-WebRequest -Uri "https://$trimmedEndpoint" -Method Get } if ($response.StatusCode -eq 401) { # If status code is 401, treat it as expected and log it as such $httpResult = "Expected (401)" $httpOutput = "Success: HTTP request succeeded for $($trimmedEndpoint): $($httpResult) - Response time: $($response_time.TotalSeconds) seconds" Write-Host $httpOutput -ForegroundColor Green $httpOutput | Out-File -FilePath $logFilePath -Append } else { # For other status codes, log the actual status code $httpResult = "Unexpected Status: $($response.StatusCode)" $httpOutput = "Success: HTTP request succeeded for $($trimmedEndpoint): $($httpResult) - Response time: $($response_time.TotalSeconds) seconds" Write-Host $httpOutput -ForegroundColor Green $httpOutput | Out-File -FilePath $logFilePath -Append } } catch { # Handle exceptions and log them if ($_.Exception.Message -like "*401*") { # If 401 is encountered in the exception message, treat it as expected $httpResult = "Expected (401)" $httpError = "Success: HTTP request succeeded for $($trimmedEndpoint) - $httpResult" Write-Host $httpError -ForegroundColor Green $httpError | Out-File -FilePath $logFilePath -Append } else { # For other exceptions, log the error message $httpResult = "Error: $_" $httpError = "Error: HTTP request failed for $($trimmedEndpoint) - $httpResult" Write-Host $httpError -ForegroundColor Red $httpError | Out-File -FilePath $logFilePath -Append } } "----------------------------------------" | Out-File -FilePath $logFilePath -Append } # Public and Private Azure Arc check $publicAzureArcMessage = "Running public Azure Arc check..." $publicAzureArcMessage | Out-File -FilePath $logFilePath -Append # Check if azcmagent.exe exists in the default path $azcmagentPath = Join-Path $env:PROGRAMFILES "AzureConnectedMachineAgent\azcmagent.exe" if (Test-Path $azcmagentPath) { $logMessage = "Running: & $azcmagentPath check --location $($region) --cloud AzureCloud --extensions sql --enable-pls-check" $logMessage | Out-File -FilePath $logFilePath -Append # Execute azcmagent from the correct path $azcmAgentResult = & $azcmagentPath check --location $($region) --cloud AzureCloud --extensions sql --enable-pls-check $azcmAgentResult | Out-File -FilePath $logFilePath -Append } else { $errorMessage = "Error: azcmagent.exe not found in $azcmagentPath" $errorMessage | Out-File -FilePath $logFilePath -Append } # Write end of the log "Script finished at $(Get-Date)" | Out-File -FilePath $logFilePath -Append