From 6da5ef70aa96b6379e0ce5bba2faeacd3e9935e0 Mon Sep 17 00:00:00 2001 From: Justin Linenkohl <83235841+jlinenkohl@users.noreply.github.com> Date: Wed, 14 Oct 2026 22:17:00 -0400 Subject: [PATCH] fix(bicep): emit sandbox egress parameters from the PowerShell assembler bicep/assemble-agent.sh passes seven egress parameters to the template -- egressMode, allowedHosts, allowedRegistries, allowedCodeRepositories, allowHttpMcpServerNetworkAccess, usePrivateDnsResolution and vnetSubnetId -- reading each from .networkConfiguration in agent.json. bicep/Assemble-Agent.ps1 emits none of them. A clone taken through the PowerShell path therefore cannot inherit its source's egress configuration at all: whatever the export contains, the deployment falls back to the template default. Cloning an agent running Limited behind a 13-host allowlist produced parameters of egressMode null with an empty host list. This is the mirror of the two bash-side divergences fixed earlier in this series. Each implementation is ahead of the other in different places, so the fix in both directions is to adopt what the other already does. Properties are probed rather than dereferenced because the script runs under StrictMode and an export predating the networkConfiguration key would otherwise throw. Verified against an export of an agent running Limited: the assembled parameters now carry egressMode Limited, 13 allowed hosts, 4 registries and 3 code-repository kinds. --- sreagent-templates/bicep/Assemble-Agent.ps1 | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sreagent-templates/bicep/Assemble-Agent.ps1 b/sreagent-templates/bicep/Assemble-Agent.ps1 index 3a367a5ed..dcb43fe7e 100644 --- a/sreagent-templates/bicep/Assemble-Agent.ps1 +++ b/sreagent-templates/bicep/Assemble-Agent.ps1 @@ -228,6 +228,29 @@ print(json.dumps(sub(data))) Write-Info 'Reading agent.json' $agentJson = Get-Content (Join-Path $ConfigDir 'agent.json') -Raw +# Sandbox egress, read from the same .networkConfiguration key assemble-agent.sh uses. +# Properties are probed rather than dereferenced: the script runs under StrictMode and an +# export predating this key would otherwise throw. +$netObj = $null +try { $netObj = ($agentJson | ConvertFrom-Json).networkConfiguration } catch { } +function Get-NetProp { + param($Obj, [string]$Name, $Default) + if ($Obj -and $Obj.PSObject.Properties[$Name] -and $null -ne $Obj.$Name) { return $Obj.$Name } + return $Default +} +$netType = [string](Get-NetProp $netObj 'type' 'unrestricted') +$egressMode = switch ($netType.ToLowerInvariant()) { + { $_ -in @('vnet', 'azurevnet') } { 'AzureVNet'; break } + 'limited' { 'Limited'; break } + default { 'Unrestricted' } +} +$netAllowedHosts = @(Get-NetProp $netObj 'allowedHosts' @()) +$netAllowedRegistries = @(Get-NetProp $netObj 'allowedRegistries' @()) +$netAllowedCodeRepos = @(Get-NetProp $netObj 'allowedCodeRepositories' @()) +$netAllowMcp = [bool](Get-NetProp $netObj 'allowHttpMcpServerNetworkAccess' $true) +$netPrivateDns = [bool](Get-NetProp $netObj 'usePrivateDnsResolution' $false) +$netSubnetId = [string](Get-NetProp $netObj 'vnetSubnetId' '') + $agentName = $agentJson | jq -r '.identity.agentName' $agentRg = $agentJson | jq -r '.identity.resourceGroup' $agentSub = $agentJson | Invoke-Jq -Raw -Filter '.identity.subscription // empty' @@ -543,6 +566,16 @@ $paramsObj = [ordered]@{ 'enableSafetyRulesPrompt' = @{ value = [bool](Get-Prop $togglesObj 'enableSafetyRulesPrompt' $false) } 'enableWebhookBridge' = @{ value = [bool](Get-Prop $togglesObj 'enableWebhookBridge' $false) } 'webhookBridgeTriggerUrl' = @{ value = [string](Get-Prop $togglesObj 'webhookBridgeTriggerUrl' '') } + # Sandbox egress. assemble-agent.sh emits all seven of these; without them a + # PowerShell clone cannot inherit the source's egress at all and deploys with the + # template default, which is more permissive than a Limited source. + 'egressMode' = @{ value = $egressMode } + 'allowedHosts' = @{ value = $netAllowedHosts } + 'allowedRegistries' = @{ value = $netAllowedRegistries } + 'allowedCodeRepositories' = @{ value = $netAllowedCodeRepos } + 'allowHttpMcpServerNetworkAccess' = @{ value = $netAllowMcp } + 'usePrivateDnsResolution' = @{ value = $netPrivateDns } + 'vnetSubnetId' = @{ value = $netSubnetId } 'connectors' = @{ value = $bicepConnectors } 'tools' = @{ value = @() } # deployed via data-plane (apply-extras) 'skills' = @{ value = @() } # deployed via data-plane (apply-extras)