chore: clean .gitignore cache

This commit is contained in:
GitHub Actions
2026-01-26 19:21:33 +00:00
parent 1b1b3a70b1
commit e5f0fec5db
1483 changed files with 0 additions and 472793 deletions

View File

@@ -1,489 +0,0 @@
package utils
import (
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
// TestTestURLConnectivity_EnhancedSSRF tests additional SSRF attack vectors.
// ENHANCEMENT: Comprehensive SSRF testing per Supervisor review
func TestTestURLConnectivity_EnhancedSSRF(t *testing.T) {
tests := []struct {
name string
url string
shouldFail bool
errContains string
}{
// Cloud Metadata Endpoints
{
name: "AWS metadata endpoint",
url: "http://169.254.169.254/latest/meta-data/",
shouldFail: true,
errContains: "private IP",
},
{
name: "GCP metadata endpoint",
url: "http://metadata.google.internal/computeMetadata/v1/",
shouldFail: true,
errContains: "DNS resolution failed", // Will fail to resolve
},
{
name: "Azure metadata endpoint",
url: "http://169.254.169.254/metadata/instance",
shouldFail: true,
errContains: "private IP",
},
// RFC 1918 Private Networks
{
name: "Private 10.0.0.0/8",
url: "http://10.0.0.1/admin",
shouldFail: true,
errContains: "private IP",
},
{
name: "Private 172.16.0.0/12",
url: "http://172.16.0.1/admin",
shouldFail: true,
errContains: "private IP",
},
{
name: "Private 192.168.0.0/16",
url: "http://192.168.1.1/admin",
shouldFail: true,
errContains: "private IP",
},
// Loopback Addresses
{
name: "IPv4 loopback",
url: "http://127.0.0.1:6379/",
shouldFail: true,
errContains: "private IP",
},
{
name: "IPv6 loopback",
url: "http://[::1]:6379/",
shouldFail: true,
errContains: "private IP",
},
// Link-Local Addresses
{
name: "Link-local IPv4",
url: "http://169.254.1.1/",
shouldFail: true,
errContains: "private IP",
},
{
name: "Link-local IPv6",
url: "http://[fe80::1]/",
shouldFail: true,
errContains: "private IP",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reachable, _, err := TestURLConnectivity(tt.url)
if tt.shouldFail {
if err == nil {
t.Errorf("Expected test to fail, but it succeeded")
} else if !strings.Contains(err.Error(), tt.errContains) {
t.Errorf("Expected error containing '%s', got: %s", tt.errContains, err.Error())
}
if reachable {
t.Errorf("Expected reachable=false, got true")
}
} else if err != nil {
t.Errorf("Expected test to succeed, but got error: %s", err.Error())
}
})
}
}
// TestTestURLConnectivity_RedirectValidation tests that redirects are properly validated.
// ENHANCEMENT: Critical test per Supervisor review - all redirects must be validated
func TestTestURLConnectivity_RedirectValidation(t *testing.T) {
// Create test servers
privateServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("Private server"))
}))
defer privateServer.Close()
t.Run("Redirect to private IP should be blocked", func(t *testing.T) {
// Note: This test requires actual redirect validation to work
// The validateRedirectTarget function will validate the Location header
// For now, we skip this test as it requires complex mock setup
t.Skip("Redirect validation test requires complex HTTP client mocking")
})
t.Run("Too many redirects should be blocked", func(t *testing.T) {
// Create a server that redirects to itself multiple times
redirectCount := 0
var redirectServerURL string
redirectServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
redirectCount++
if redirectCount < 5 {
http.Redirect(w, r, redirectServerURL+fmt.Sprintf("/%d", redirectCount), http.StatusFound)
} else {
w.WriteHeader(http.StatusOK)
}
}))
defer redirectServer.Close()
redirectServerURL = redirectServer.URL
transport := redirectServer.Client().Transport
reachable, _, err := testURLConnectivity(redirectServerURL, withAllowLocalhostForTesting(), withTransportForTesting(transport))
// Should fail due to too many redirects (max 2)
if err == nil {
t.Errorf("Expected too many redirects to fail, but it succeeded")
}
if !strings.Contains(err.Error(), "redirect") {
t.Errorf("Expected error about redirects, got: %s", err.Error())
}
if reachable {
t.Errorf("Expected reachable=false, got true")
}
})
}
// TestTestURLConnectivity_UnicodeHomograph tests Unicode homograph attack prevention.
// ENHANCEMENT: Tests for internationalized domain name attacks
func TestTestURLConnectivity_UnicodeHomograph(t *testing.T) {
tests := []struct {
name string
url string
}{
{
name: "Cyrillic homograph",
url: "https://gооgle.com", // Uses Cyrillic 'о' instead of Latin 'o'
},
{
name: "Mixed script attack",
url: "https://раypal.com", // Uses Cyrillic 'а' and 'y'
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// These should fail DNS resolution since they're not real domains
reachable, _, err := TestURLConnectivity(tt.url)
if err == nil {
t.Logf("Warning: homograph domain %s resolved - may indicate IDN issue", tt.url)
}
if reachable {
t.Errorf("Homograph domain %s appears reachable - security concern", tt.url)
}
})
}
}
// TestTestURLConnectivity_LongHostname tests extremely long hostname handling.
// ENHANCEMENT: DoS prevention via hostname length validation
func TestTestURLConnectivity_LongHostname(t *testing.T) {
// Create hostname exceeding RFC 1035 limit (253 chars)
longHostname := strings.Repeat("a", 254) + ".com"
url := "https://" + longHostname + "/path"
reachable, _, err := TestURLConnectivity(url)
if err == nil {
t.Errorf("Expected long hostname to be rejected, but it was accepted")
}
if reachable {
t.Errorf("Expected reachable=false for long hostname, got true")
}
}
// TestTestURLConnectivity_RequestTracingHeaders tests that tracing headers are added.
// ENHANCEMENT: Verifies request tracing per Supervisor review
func TestTestURLConnectivity_RequestTracingHeaders(t *testing.T) {
var capturedHeaders http.Header
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
capturedHeaders = r.Header.Clone()
w.WriteHeader(http.StatusOK)
}))
defer testServer.Close()
transport := testServer.Client().Transport
_, _, err := testURLConnectivity(testServer.URL, withAllowLocalhostForTesting(), withTransportForTesting(transport))
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
// Verify headers were set
if capturedHeaders.Get("User-Agent") != "Charon-Health-Check/1.0" {
t.Errorf("Expected User-Agent header, got: %s", capturedHeaders.Get("User-Agent"))
}
if capturedHeaders.Get("X-Charon-Request-Type") != "url-connectivity-test" {
t.Errorf("Expected X-Charon-Request-Type header, got: %s", capturedHeaders.Get("X-Charon-Request-Type"))
}
if capturedHeaders.Get("X-Request-ID") == "" {
t.Errorf("Expected X-Request-ID header to be set")
}
if !strings.HasPrefix(capturedHeaders.Get("X-Request-ID"), "test-") {
t.Errorf("Expected X-Request-ID to start with 'test-', got: %s", capturedHeaders.Get("X-Request-ID"))
}
}
// TestTestURLConnectivity_MetricsIntegration tests that metrics are recorded.
// ENHANCEMENT: Validates metrics collection per Supervisor review
func TestTestURLConnectivity_MetricsIntegration(t *testing.T) {
// This test verifies that metrics functions are called
// Full metrics validation requires integration tests with Prometheus
t.Run("Valid URL records metrics", func(t *testing.T) {
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
defer testServer.Close()
transport := testServer.Client().Transport
reachable, latency, err := testURLConnectivity(testServer.URL, withAllowLocalhostForTesting(), withTransportForTesting(transport))
if err != nil {
t.Errorf("Unexpected error: %s", err)
}
if !reachable {
t.Errorf("Expected reachable=true, got false")
}
if latency <= 0 {
t.Errorf("Expected positive latency, got %f", latency)
}
// Metrics recorded: URLValidation (allowed), URLTestDuration
})
t.Run("Blocked URL records metrics", func(t *testing.T) {
reachable, _, err := TestURLConnectivity("http://127.0.0.1:6379/")
if err == nil {
t.Errorf("Expected private IP to be blocked")
}
if reachable {
t.Errorf("Expected reachable=false, got true")
}
// Metrics recorded: SSRFBlock, URLValidation (blocked)
})
t.Run("Invalid URL records metrics", func(t *testing.T) {
reachable, _, err := TestURLConnectivity("not-a-valid-url")
if err == nil {
t.Errorf("Expected invalid URL to fail")
}
if reachable {
t.Errorf("Expected reachable=false, got true")
}
// Metrics recorded: URLValidation (error, unsupported_scheme)
})
}
// TestValidateRedirectTarget tests the redirect validation function directly.
// ENHANCEMENT: Direct unit tests for redirect validation per Phase 2 requirements
func TestValidateRedirectTarget(t *testing.T) {
tests := []struct {
name string
url string
viaCount int
shouldErr bool
errContains string
viaURL string
allowLocal bool
}{
{
name: "Localhost redirect allowed",
url: "http://localhost/path",
viaCount: 0,
shouldErr: false,
allowLocal: true,
},
{
name: "127.0.0.1 redirect allowed",
url: "http://127.0.0.1:8080/path",
viaCount: 0,
shouldErr: false,
allowLocal: true,
},
{
name: "IPv6 loopback allowed",
url: "http://[::1]:8080/path",
viaCount: 0,
shouldErr: false,
allowLocal: true,
},
{
name: "Too many redirects",
url: "http://localhost/path",
viaCount: 2,
shouldErr: true,
errContains: "too many redirects",
allowLocal: true,
},
{
name: "Three redirects",
url: "http://localhost/path",
viaCount: 3,
shouldErr: true,
errContains: "too many redirects",
allowLocal: true,
},
{
name: "Scheme downgrade blocked (https -> http)",
url: "http://localhost/next",
viaURL: "https://localhost/start",
viaCount: 1,
shouldErr: true,
errContains: "scheme change blocked",
allowLocal: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Create a request for the redirect target
req, err := http.NewRequest("GET", tt.url, http.NoBody)
if err != nil {
t.Fatalf("Failed to create request: %v", err)
}
// Create via slice (previous requests)
via := make([]*http.Request, 0, tt.viaCount)
if tt.viaCount > 0 {
viaURL := tt.viaURL
if viaURL == "" {
viaURL = "http://localhost/prev"
}
prevReq, prevErr := http.NewRequest("GET", viaURL, http.NoBody)
if prevErr != nil {
t.Fatalf("Failed to create via request: %v", prevErr)
}
via = append(via, prevReq)
for i := 1; i < tt.viaCount; i++ {
via = append(via, prevReq)
}
}
err = validateRedirectTargetStrict(req, via, 2, true, tt.allowLocal)
if tt.shouldErr {
if err == nil {
t.Errorf("Expected error, got nil")
} else if tt.errContains != "" && !strings.Contains(err.Error(), tt.errContains) {
t.Errorf("Expected error containing '%s', got: %s", tt.errContains, err.Error())
}
} else {
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
}
})
}
}
// TestTestURLConnectivity_AuditLogging tests that audit logging is integrated.
// ENHANCEMENT: Validates audit logging integration per Phase 3 requirements
func TestTestURLConnectivity_AuditLogging(t *testing.T) {
// Note: In production, audit logs go to the configured logger.
// These tests verify the code paths execute without panic.
t.Run("Invalid URL format logs audit event", func(t *testing.T) {
// This should trigger audit logging for invalid format
reachable, _, err := TestURLConnectivity("://invalid")
if err == nil {
t.Errorf("Expected error for invalid URL")
}
if reachable {
t.Errorf("Expected reachable=false")
}
})
t.Run("Invalid scheme logs audit event", func(t *testing.T) {
// This should trigger audit logging for unsupported scheme
reachable, _, err := TestURLConnectivity("ftp://example.com/file")
if err == nil {
t.Errorf("Expected error for unsupported scheme")
}
if reachable {
t.Errorf("Expected reachable=false")
}
})
t.Run("Private IP logs SSRF block audit event", func(t *testing.T) {
// This should trigger SSRF block audit logging
reachable, _, err := TestURLConnectivity("http://10.0.0.1/admin")
if err == nil {
t.Errorf("Expected error for private IP")
}
if reachable {
t.Errorf("Expected reachable=false")
}
})
t.Run("Metadata endpoint logs SSRF block audit event", func(t *testing.T) {
// This should trigger metadata endpoint block audit logging
reachable, _, err := TestURLConnectivity("http://169.254.169.254/latest/meta-data/")
if err == nil {
t.Errorf("Expected error for metadata endpoint")
}
if reachable {
t.Errorf("Expected reachable=false")
}
})
t.Run("Valid URL with mock transport logs success", func(t *testing.T) {
// Create a test server
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
defer testServer.Close()
// Note: With mock transport, audit logging is skipped (isTestMode=true)
// This test verifies the code path doesn't panic
transport := testServer.Client().Transport
reachable, _, err := testURLConnectivity(testServer.URL, withAllowLocalhostForTesting(), withTransportForTesting(transport))
if err != nil {
t.Errorf("Unexpected error: %s", err)
}
if !reachable {
t.Errorf("Expected reachable=true")
}
})
}
// TestTestURLConnectivity_RequestIDConsistency tests that request ID is consistent.
// ENHANCEMENT: Validates request tracing per Phase 3 requirements
func TestTestURLConnectivity_RequestIDConsistency(t *testing.T) {
var capturedRequestID string
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
capturedRequestID = r.Header.Get("X-Request-ID")
w.WriteHeader(http.StatusOK)
}))
defer testServer.Close()
transport := testServer.Client().Transport
_, _, err := testURLConnectivity(testServer.URL, withAllowLocalhostForTesting(), withTransportForTesting(transport))
if err != nil {
t.Fatalf("Unexpected error: %s", err)
}
if capturedRequestID == "" {
t.Error("X-Request-ID header was not set")
}
if !strings.HasPrefix(capturedRequestID, "test-") {
t.Errorf("X-Request-ID should start with 'test-', got: %s", capturedRequestID)
}
}