diff --git a/pkg/workflow/claude_engine.go b/pkg/workflow/claude_engine.go index 8dcf71639b..e88152558d 100644 --- a/pkg/workflow/claude_engine.go +++ b/pkg/workflow/claude_engine.go @@ -331,6 +331,10 @@ func (e *ClaudeEngine) GetExecutionSteps(workflowData *WorkflowData, logFile str sslBumpArgs := getSSLBumpArgs(firewallConfig) awfArgs = append(awfArgs, sslBumpArgs...) + // Add API proxy support for HTTP/HTTPS request interception + apiProxyArgs := getAPIProxyArgs(firewallConfig) + awfArgs = append(awfArgs, apiProxyArgs...) + // Add custom args if specified in firewall config if firewallConfig != nil && len(firewallConfig.Args) > 0 { awfArgs = append(awfArgs, firewallConfig.Args...) diff --git a/pkg/workflow/codex_engine.go b/pkg/workflow/codex_engine.go index fc93bac545..73c008704b 100644 --- a/pkg/workflow/codex_engine.go +++ b/pkg/workflow/codex_engine.go @@ -252,6 +252,10 @@ func (e *CodexEngine) GetExecutionSteps(workflowData *WorkflowData, logFile stri sslBumpArgs := getSSLBumpArgs(firewallConfig) awfArgs = append(awfArgs, sslBumpArgs...) + // Add API proxy support for HTTP/HTTPS request interception + apiProxyArgs := getAPIProxyArgs(firewallConfig) + awfArgs = append(awfArgs, apiProxyArgs...) + // Add custom args if specified in firewall config if firewallConfig != nil && len(firewallConfig.Args) > 0 { awfArgs = append(awfArgs, firewallConfig.Args...) diff --git a/pkg/workflow/copilot_engine_execution.go b/pkg/workflow/copilot_engine_execution.go index 592d75c627..df50d0968e 100644 --- a/pkg/workflow/copilot_engine_execution.go +++ b/pkg/workflow/copilot_engine_execution.go @@ -313,6 +313,10 @@ func (e *CopilotEngine) GetExecutionSteps(workflowData *WorkflowData, logFile st sslBumpArgs := getSSLBumpArgs(firewallConfig) awfArgs = append(awfArgs, sslBumpArgs...) + // Add API proxy support for HTTP/HTTPS request interception + apiProxyArgs := getAPIProxyArgs(firewallConfig) + awfArgs = append(awfArgs, apiProxyArgs...) + // Add custom args if specified in firewall config if firewallConfig != nil && len(firewallConfig.Args) > 0 { awfArgs = append(awfArgs, firewallConfig.Args...) diff --git a/pkg/workflow/firewall.go b/pkg/workflow/firewall.go index f5d11d78c6..34341b3321 100644 --- a/pkg/workflow/firewall.go +++ b/pkg/workflow/firewall.go @@ -12,13 +12,14 @@ var firewallLog = logger.New("workflow:firewall") // FirewallConfig represents AWF (gh-aw-firewall) configuration for network egress control. // These settings are specific to the AWF sandbox and do not apply to Sandbox Runtime (SRT). type FirewallConfig struct { - Enabled bool `yaml:"enabled,omitempty"` // Enable/disable AWF (default: true for copilot when network restrictions present) - Version string `yaml:"version,omitempty"` // AWF version (empty = latest) - Args []string `yaml:"args,omitempty"` // Additional arguments to pass to AWF - LogLevel string `yaml:"log_level,omitempty"` // AWF log level (default: "info") - CleanupScript string `yaml:"cleanup_script,omitempty"` // Cleanup script path (default: "./scripts/ci/cleanup.sh") - SSLBump bool `yaml:"ssl_bump,omitempty"` // AWF-only: Enable SSL Bump for HTTPS content inspection (allows URL path filtering) - AllowURLs []string `yaml:"allow_urls,omitempty"` // AWF-only: URL patterns to allow for HTTPS (requires SSLBump), e.g., "https://github.com/githubnext/*" + Enabled bool `yaml:"enabled,omitempty"` // Enable/disable AWF (default: true for copilot when network restrictions present) + Version string `yaml:"version,omitempty"` // AWF version (empty = latest) + Args []string `yaml:"args,omitempty"` // Additional arguments to pass to AWF + LogLevel string `yaml:"log_level,omitempty"` // AWF log level (default: "info") + CleanupScript string `yaml:"cleanup_script,omitempty"` // Cleanup script path (default: "./scripts/ci/cleanup.sh") + SSLBump bool `yaml:"ssl_bump,omitempty"` // AWF-only: Enable SSL Bump for HTTPS content inspection (allows URL path filtering) + AllowURLs []string `yaml:"allow_urls,omitempty"` // AWF-only: URL patterns to allow for HTTPS (requires SSLBump), e.g., "https://github.com/githubnext/*" + EnableAPIProxy bool `yaml:"enable_api_proxy,omitempty"` // AWF-only: Enable API proxy for HTTP/HTTPS request interception } // isFirewallDisabledBySandboxAgent checks if the firewall is disabled via sandbox.agent: false @@ -216,3 +217,21 @@ func getSSLBumpArgs(firewallConfig *FirewallConfig) []string { return args } + +// getAPIProxyArgs returns the AWF arguments for API proxy configuration. +// Returns the --enable-api-proxy flag if API proxy is enabled. +// API proxy enables HTTP/HTTPS request interception for advanced filtering. +// +// Note: This feature is specific to AWF (Agent Workflow Firewall) and does not +// apply to Sandbox Runtime (SRT) or other sandbox configurations. +func getAPIProxyArgs(firewallConfig *FirewallConfig) []string { + if firewallConfig == nil || !firewallConfig.EnableAPIProxy { + return nil + } + + var args []string + args = append(args, "--enable-api-proxy") + firewallLog.Print("Added --enable-api-proxy for HTTP/HTTPS request interception") + + return args +} diff --git a/pkg/workflow/firewall_args_test.go b/pkg/workflow/firewall_args_test.go index 09c548ed14..a1357a9227 100644 --- a/pkg/workflow/firewall_args_test.go +++ b/pkg/workflow/firewall_args_test.go @@ -330,4 +330,62 @@ func TestFirewallArgsInCopilotEngine(t *testing.T) { t.Error("Expected AWF command to NOT contain '--allow-urls' flag when SSLBump is false") } }) + + t.Run("AWF command includes enable-api-proxy when enabled", func(t *testing.T) { + workflowData := &WorkflowData{ + Name: "test-workflow", + EngineConfig: &EngineConfig{ + ID: "copilot", + }, + NetworkPermissions: &NetworkPermissions{ + Firewall: &FirewallConfig{ + Enabled: true, + EnableAPIProxy: true, + }, + }, + } + + engine := NewCopilotEngine() + steps := engine.GetExecutionSteps(workflowData, "test.log") + + if len(steps) == 0 { + t.Fatal("Expected at least one execution step") + } + + stepContent := strings.Join(steps[0], "\n") + + // Check that --enable-api-proxy flag is included + if !strings.Contains(stepContent, "--enable-api-proxy") { + t.Error("Expected AWF command to contain '--enable-api-proxy' flag") + } + }) + + t.Run("AWF command does not include enable-api-proxy when disabled", func(t *testing.T) { + workflowData := &WorkflowData{ + Name: "test-workflow", + EngineConfig: &EngineConfig{ + ID: "copilot", + }, + NetworkPermissions: &NetworkPermissions{ + Firewall: &FirewallConfig{ + Enabled: true, + EnableAPIProxy: false, + }, + }, + } + + engine := NewCopilotEngine() + steps := engine.GetExecutionSteps(workflowData, "test.log") + + if len(steps) == 0 { + t.Fatal("Expected at least one execution step") + } + + stepContent := strings.Join(steps[0], "\n") + + // Check that --enable-api-proxy flag is NOT included + if strings.Contains(stepContent, "--enable-api-proxy") { + t.Error("Expected AWF command to NOT contain '--enable-api-proxy' flag when EnableAPIProxy is false") + } + }) }