Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions pkg/cli/firewall_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,14 +317,26 @@ func analyzeFirewallLogs(runDir string, verbose bool) (*FirewallAnalysis, error)
// Look for firewall logs in the run directory
// The logs could be in several locations depending on how they were uploaded

// First, check for a squid-logs or firewall-logs directory
possibleDirs := []string{
filepath.Join(runDir, "squid-logs"),
filepath.Join(runDir, "firewall-logs"),
// First, check for directories starting with squid-logs or firewall-logs
// The actual directories may have workflow-specific suffixes like:
// - squid-logs-smoke-copilot-firewall
// - squid-logs-changeset-generator
// - firewall-logs-{workflow-name}
entries, err := os.ReadDir(runDir)
if err != nil {
return nil, fmt.Errorf("failed to read run directory: %w", err)
}

for _, logsDir := range possibleDirs {
if stat, err := os.Stat(logsDir); err == nil && stat.IsDir() {
for _, entry := range entries {
if !entry.IsDir() {
continue
}
name := entry.Name()
if strings.HasPrefix(name, "squid-logs") || strings.HasPrefix(name, "firewall-logs") {
logsDir := filepath.Join(runDir, name)
if verbose {
fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Found firewall logs directory: %s", name)))
}
return analyzeMultipleFirewallLogs(logsDir, verbose)
}
}
Expand Down
62 changes: 62 additions & 0 deletions pkg/cli/firewall_log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,3 +495,65 @@ func TestSanitizeWorkflowName(t *testing.T) {
})
}
}

func TestAnalyzeFirewallLogsWithWorkflowSuffix(t *testing.T) {
// Create a temporary directory structure that mimics actual workflow artifact layout
tmpDir := t.TempDir()

// Create a directory with workflow-specific suffix (like squid-logs-smoke-copilot-firewall)
logsDir := filepath.Join(tmpDir, "squid-logs-smoke-copilot-firewall")
err := os.MkdirAll(logsDir, 0755)
if err != nil {
t.Fatalf("Failed to create logs directory: %v", err)
}

// Create a sample access.log file
accessLog := filepath.Join(logsDir, "access.log")
logContent := `1761332530.474 172.30.0.20:35288 api.enterprise.githubcopilot.com:443 140.82.112.22:443 1.1 CONNECT 200 TCP_TUNNEL:HIER_DIRECT api.enterprise.githubcopilot.com:443 "-"
1761332531.123 172.30.0.20:35289 blocked.example.com:443 140.82.112.23:443 1.1 CONNECT 403 NONE_NONE:HIER_NONE blocked.example.com:443 "-"
1761332532.456 172.30.0.20:35290 api.github.com:443 140.82.112.5:443 1.1 CONNECT 200 TCP_TUNNEL:HIER_DIRECT api.github.com:443 "-"
`
err = os.WriteFile(accessLog, []byte(logContent), 0644)
if err != nil {
t.Fatalf("Failed to write access.log: %v", err)
}

// Analyze the logs - this should find the squid-logs-* directory
analysis, err := analyzeFirewallLogs(tmpDir, false)
if err != nil {
t.Fatalf("analyzeFirewallLogs failed: %v", err)
}

if analysis == nil {
t.Fatal("Expected firewall analysis but got nil")
}

// Verify the analysis found our logs
if analysis.TotalRequests != 3 {
t.Errorf("TotalRequests: got %d, want 3", analysis.TotalRequests)
}

if analysis.AllowedRequests != 2 {
t.Errorf("AllowedRequests: got %d, want 2", analysis.AllowedRequests)
}

if analysis.DeniedRequests != 1 {
t.Errorf("DeniedRequests: got %d, want 1", analysis.DeniedRequests)
}

// Verify allowed domains
expectedAllowed := map[string]bool{
"api.enterprise.githubcopilot.com:443": true,
"api.github.com:443": true,
}
for _, domain := range analysis.AllowedDomains {
if !expectedAllowed[domain] {
t.Errorf("Unexpected allowed domain: %s", domain)
}
}

// Verify denied domains
if len(analysis.DeniedDomains) != 1 || analysis.DeniedDomains[0] != "blocked.example.com:443" {
t.Errorf("DeniedDomains: got %v, want [blocked.example.com:443]", analysis.DeniedDomains)
}
}