Skip to content
Open
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
12 changes: 12 additions & 0 deletions pkg/cli/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"context"
"fmt"
"net"
"net/http"
"net/url"
"os"
Expand Down Expand Up @@ -222,6 +223,8 @@ func GetBackplaneConfiguration() (bpConfig BackplaneConfiguration, err error) {
return bpConfig, nil
}

var lookupHost = net.LookupHost

var testProxy = func(ctx context.Context, testURL string, proxyURL url.URL) error {
// Try call the test URL via the proxy
client := &http.Client{
Expand Down Expand Up @@ -410,6 +413,15 @@ func (config *BackplaneConfiguration) testHTTPRequestToBackplaneAPI() (bool, err
if err != nil {
return false, err
}
scheme := proxyURL.Scheme
if scheme != "http" && scheme != "https" {
return false, fmt.Errorf("proxy URL scheme must be http or https, got: %s", scheme)
}
hostname := proxyURL.Hostname()
_, err = lookupHost(hostname)
if err != nil {
return false, fmt.Errorf("DNS lookup failed for proxy hostname '%s': %v (check network connectivity or VPN if required)", hostname, err)
}
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(proxyURL)}
}

Expand Down
84 changes: 84 additions & 0 deletions pkg/cli/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http/httptest"
"net/url"
"os"
"strings"
"testing"

"github.com/spf13/viper"
Expand Down Expand Up @@ -85,6 +86,89 @@ func TestGetBackplaneConnection(t *testing.T) {
t.Failed()
}
})

t.Run("should pass for valid http proxy URL", func(t *testing.T) {
proxyURL := "http://www.example.com"
config := BackplaneConfiguration{URL: "https://api.example.com", ProxyURL: &proxyURL}
_, err := config.testHTTPRequestToBackplaneAPI()

// Should not get scheme validation error (DNS lookup error is expected)
if err != nil && strings.Contains(err.Error(), "proxy URL scheme must be http or https") {
t.Errorf("unexpected scheme validation error: %v", err)
}
})

t.Run("should pass for valid https proxy URL", func(t *testing.T) {
proxyURL := "https://www.example.com"
config := BackplaneConfiguration{URL: "https://api.example.com", ProxyURL: &proxyURL}
_, err := config.testHTTPRequestToBackplaneAPI()

// Should not get scheme validation error (DNS lookup error is expected)
if err != nil && strings.Contains(err.Error(), "proxy URL scheme must be http or https") {
t.Errorf("unexpected scheme validation error: %v", err)
}
})

t.Run("should fail for proxy URL without scheme", func(t *testing.T) {
proxyURL := "www.example.com"
config := BackplaneConfiguration{URL: "https://api.example.com", ProxyURL: &proxyURL}
_, err := config.testHTTPRequestToBackplaneAPI()

if err == nil {
t.Errorf("expected error but got none")
} else if !strings.Contains(err.Error(), "proxy URL scheme must be http or https, got:") {
t.Errorf("expected scheme validation error, got: %s", err.Error())
}
})

t.Run("should fail for ftp proxy URL", func(t *testing.T) {
proxyURL := "ftp://www.example.com"
config := BackplaneConfiguration{URL: "https://api.example.com", ProxyURL: &proxyURL}
_, err := config.testHTTPRequestToBackplaneAPI()

if err == nil {
t.Errorf("expected error but got none")
} else if !strings.Contains(err.Error(), "proxy URL scheme must be http or https, got: ftp") {
t.Errorf("expected scheme validation error for ftp, got: %s", err.Error())
}
})

t.Run("should fail on DNS lookup error", func(t *testing.T) {
// Mock DNS lookup to return an error
originalLookupHost := lookupHost
lookupHost = func(hostname string) ([]string, error) {
return nil, fmt.Errorf("DNS resolution failed")
}
defer func() { lookupHost = originalLookupHost }()

proxyURL := "https://proxy.example.com"
config := BackplaneConfiguration{URL: "https://api.example.com", ProxyURL: &proxyURL}
_, err := config.testHTTPRequestToBackplaneAPI()

if err == nil {
t.Errorf("expected DNS lookup error but got none")
} else if !strings.Contains(err.Error(), "DNS lookup failed for proxy hostname") {
t.Errorf("expected DNS lookup error, got: %s", err.Error())
}
})

t.Run("should pass on successful DNS lookup", func(t *testing.T) {
// Mock DNS lookup to succeed
originalLookupHost := lookupHost
lookupHost = func(hostname string) ([]string, error) {
return []string{"192.168.1.1"}, nil
}
defer func() { lookupHost = originalLookupHost }()

proxyURL := "https://proxy.example.com"
config := BackplaneConfiguration{URL: "https://api.example.com", ProxyURL: &proxyURL}
_, err := config.testHTTPRequestToBackplaneAPI()

// Should not get DNS lookup error (HTTP request error is expected)
if err != nil && strings.Contains(err.Error(), "DNS lookup failed for proxy hostname") {
t.Errorf("unexpected DNS lookup error: %v", err)
}
})
}

func TestBackplaneConfiguration_getFirstWorkingProxyURL(t *testing.T) {
Expand Down