mirror of
https://github.com/projectdiscovery/httpx
synced 2026-06-08 16:50:17 +00:00
test: add comprehensive tests for auth provider
- Test Cookie.Parse edge cases (equals in value, spaces, empty fields) - Test Secret validation for all auth types - Test file loading with different extensions (case-insensitive) - Test all auth strategies (Apply and ApplyOnRR methods) - Test FileAuthProvider domain lookup (exact and regex) - Test MultiAuthProvider delegation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,408 @@
|
||||
package authx
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCookieParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
raw string
|
||||
wantKey string
|
||||
wantValue string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "simple cookie",
|
||||
raw: "session=abc123",
|
||||
wantKey: "session",
|
||||
wantValue: "abc123",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "cookie with Set-Cookie prefix",
|
||||
raw: "Set-Cookie: session=abc123; Path=/",
|
||||
wantKey: "session",
|
||||
wantValue: "abc123",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "cookie with equals in value",
|
||||
raw: "token=eyJhbGciOiJIUzI1NiJ9==; Path=/",
|
||||
wantKey: "token",
|
||||
wantValue: "eyJhbGciOiJIUzI1NiJ9==",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "cookie with spaces",
|
||||
raw: " session = abc123 ; Path=/",
|
||||
wantKey: "session",
|
||||
wantValue: "abc123",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty raw",
|
||||
raw: "",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing equals",
|
||||
raw: "sessionabc123; Path=/",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty key",
|
||||
raw: "=abc123; Path=/",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &Cookie{Raw: tt.raw}
|
||||
err := c.Parse()
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Cookie.Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
if !tt.wantErr {
|
||||
if c.Key != tt.wantKey {
|
||||
t.Errorf("Cookie.Parse() Key = %v, want %v", c.Key, tt.wantKey)
|
||||
}
|
||||
if c.Value != tt.wantValue {
|
||||
t.Errorf("Cookie.Parse() Value = %v, want %v", c.Value, tt.wantValue)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretValidate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
secret Secret
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid basic auth",
|
||||
secret: Secret{
|
||||
Type: "BasicAuth",
|
||||
Domains: []string{"example.com"},
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid bearer token",
|
||||
secret: Secret{
|
||||
Type: "BearerToken",
|
||||
Domains: []string{"example.com"},
|
||||
Token: "abc123",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid header auth",
|
||||
secret: Secret{
|
||||
Type: "Header",
|
||||
Domains: []string{"example.com"},
|
||||
Headers: []KV{{Key: "X-API-Key", Value: "secret"}},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid cookie auth",
|
||||
secret: Secret{
|
||||
Type: "Cookie",
|
||||
Domains: []string{"example.com"},
|
||||
Cookies: []Cookie{{Key: "session", Value: "abc123"}},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "valid query auth",
|
||||
secret: Secret{
|
||||
Type: "Query",
|
||||
Domains: []string{"example.com"},
|
||||
Params: []KV{{Key: "api_key", Value: "secret"}},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid type",
|
||||
secret: Secret{
|
||||
Type: "InvalidType",
|
||||
Domains: []string{"example.com"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing domains",
|
||||
secret: Secret{
|
||||
Type: "BasicAuth",
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "basic auth missing username",
|
||||
secret: Secret{
|
||||
Type: "BasicAuth",
|
||||
Domains: []string{"example.com"},
|
||||
Password: "pass",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "basic auth missing password",
|
||||
secret: Secret{
|
||||
Type: "BasicAuth",
|
||||
Domains: []string{"example.com"},
|
||||
Username: "user",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "bearer auth missing token",
|
||||
secret: Secret{
|
||||
Type: "BearerToken",
|
||||
Domains: []string{"example.com"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "header auth missing headers",
|
||||
secret: Secret{
|
||||
Type: "Header",
|
||||
Domains: []string{"example.com"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "cookie auth missing cookies",
|
||||
secret: Secret{
|
||||
Type: "Cookie",
|
||||
Domains: []string{"example.com"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "query auth missing params",
|
||||
secret: Secret{
|
||||
Type: "Query",
|
||||
Domains: []string{"example.com"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid domain regex",
|
||||
secret: Secret{
|
||||
Type: "BearerToken",
|
||||
DomainsRegex: []string{".*\\.example\\.com"},
|
||||
Token: "abc123",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid domain regex",
|
||||
secret: Secret{
|
||||
Type: "BearerToken",
|
||||
DomainsRegex: []string{"[invalid"},
|
||||
Token: "abc123",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "case insensitive type",
|
||||
secret: Secret{
|
||||
Type: "basicauth",
|
||||
Domains: []string{"example.com"},
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.secret.Validate()
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Secret.Validate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAuthDataFromFile(t *testing.T) {
|
||||
// Create temp directory for test files
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
yamlContent := `id: test
|
||||
info:
|
||||
name: test
|
||||
static:
|
||||
- type: BasicAuth
|
||||
domains:
|
||||
- example.com
|
||||
username: user
|
||||
password: pass
|
||||
`
|
||||
|
||||
jsonContent := `{
|
||||
"id": "test",
|
||||
"info": {"name": "test"},
|
||||
"static": [
|
||||
{
|
||||
"type": "BasicAuth",
|
||||
"domains": ["example.com"],
|
||||
"username": "user",
|
||||
"password": "pass"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
filename string
|
||||
content string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "yaml file lowercase",
|
||||
filename: "secrets.yaml",
|
||||
content: yamlContent,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "yml file lowercase",
|
||||
filename: "secrets.yml",
|
||||
content: yamlContent,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "json file lowercase",
|
||||
filename: "secrets.json",
|
||||
content: jsonContent,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "yaml file uppercase",
|
||||
filename: "secrets.YAML",
|
||||
content: yamlContent,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "json file uppercase",
|
||||
filename: "secrets.JSON",
|
||||
content: jsonContent,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid extension",
|
||||
filename: "secrets.txt",
|
||||
content: yamlContent,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Create test file
|
||||
filePath := filepath.Join(tmpDir, tt.filename)
|
||||
err := os.WriteFile(filePath, []byte(tt.content), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test file: %v", err)
|
||||
}
|
||||
|
||||
_, err = GetAuthDataFromFile(filePath)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("GetAuthDataFromFile() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSecretGetStrategy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
secret Secret
|
||||
wantType string
|
||||
wantNil bool
|
||||
}{
|
||||
{
|
||||
name: "basic auth strategy",
|
||||
secret: Secret{
|
||||
Type: "BasicAuth",
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
},
|
||||
wantType: "*authx.BasicAuthStrategy",
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "bearer token strategy",
|
||||
secret: Secret{
|
||||
Type: "BearerToken",
|
||||
Token: "abc123",
|
||||
},
|
||||
wantType: "*authx.BearerTokenAuthStrategy",
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "header strategy",
|
||||
secret: Secret{
|
||||
Type: "Header",
|
||||
Headers: []KV{{Key: "X-API-Key", Value: "secret"}},
|
||||
},
|
||||
wantType: "*authx.HeadersAuthStrategy",
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "cookie strategy",
|
||||
secret: Secret{
|
||||
Type: "Cookie",
|
||||
Cookies: []Cookie{{Key: "session", Value: "abc123"}},
|
||||
},
|
||||
wantType: "*authx.CookiesAuthStrategy",
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "query strategy",
|
||||
secret: Secret{
|
||||
Type: "Query",
|
||||
Params: []KV{{Key: "api_key", Value: "secret"}},
|
||||
},
|
||||
wantType: "*authx.QueryAuthStrategy",
|
||||
wantNil: false,
|
||||
},
|
||||
{
|
||||
name: "unknown type returns nil",
|
||||
secret: Secret{
|
||||
Type: "UnknownType",
|
||||
},
|
||||
wantNil: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
strategy := tt.secret.GetStrategy()
|
||||
if tt.wantNil {
|
||||
if strategy != nil {
|
||||
t.Errorf("GetStrategy() = %T, want nil", strategy)
|
||||
}
|
||||
} else {
|
||||
if strategy == nil {
|
||||
t.Errorf("GetStrategy() = nil, want %s", tt.wantType)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package authx
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/projectdiscovery/retryablehttp-go"
|
||||
)
|
||||
|
||||
func TestBasicAuthStrategy(t *testing.T) {
|
||||
secret := &Secret{
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
}
|
||||
strategy := NewBasicAuthStrategy(secret)
|
||||
|
||||
t.Run("Apply", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.Apply(req)
|
||||
|
||||
user, pass, ok := req.BasicAuth()
|
||||
if !ok {
|
||||
t.Error("Basic auth not set")
|
||||
}
|
||||
if user != "user" {
|
||||
t.Errorf("Username = %v, want user", user)
|
||||
}
|
||||
if pass != "pass" {
|
||||
t.Errorf("Password = %v, want pass", pass)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ApplyOnRR", func(t *testing.T) {
|
||||
req, _ := retryablehttp.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.ApplyOnRR(req)
|
||||
|
||||
user, pass, ok := req.BasicAuth()
|
||||
if !ok {
|
||||
t.Error("Basic auth not set")
|
||||
}
|
||||
if user != "user" {
|
||||
t.Errorf("Username = %v, want user", user)
|
||||
}
|
||||
if pass != "pass" {
|
||||
t.Errorf("Password = %v, want pass", pass)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestBearerTokenAuthStrategy(t *testing.T) {
|
||||
secret := &Secret{
|
||||
Token: "mytoken123",
|
||||
}
|
||||
strategy := NewBearerTokenAuthStrategy(secret)
|
||||
|
||||
t.Run("Apply", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.Apply(req)
|
||||
|
||||
auth := req.Header.Get("Authorization")
|
||||
expected := "Bearer mytoken123"
|
||||
if auth != expected {
|
||||
t.Errorf("Authorization = %v, want %v", auth, expected)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ApplyOnRR", func(t *testing.T) {
|
||||
req, _ := retryablehttp.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.ApplyOnRR(req)
|
||||
|
||||
auth := req.Header.Get("Authorization")
|
||||
expected := "Bearer mytoken123"
|
||||
if auth != expected {
|
||||
t.Errorf("Authorization = %v, want %v", auth, expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestHeadersAuthStrategy(t *testing.T) {
|
||||
// Headers strategy preserves exact casing, so use exact key names
|
||||
secret := &Secret{
|
||||
Headers: []KV{
|
||||
{Key: "X-API-Key", Value: "secret123"},
|
||||
{Key: "X-Custom", Value: "value"},
|
||||
},
|
||||
}
|
||||
strategy := NewHeadersAuthStrategy(secret)
|
||||
|
||||
t.Run("Apply", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.Apply(req)
|
||||
|
||||
// Use direct map access since headers preserve exact casing
|
||||
if got := req.Header["X-API-Key"]; len(got) == 0 || got[0] != "secret123" {
|
||||
t.Errorf("X-API-Key = %v, want [secret123]", got)
|
||||
}
|
||||
if got := req.Header["X-Custom"]; len(got) == 0 || got[0] != "value" {
|
||||
t.Errorf("X-Custom = %v, want [value]", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ApplyOnRR", func(t *testing.T) {
|
||||
req, _ := retryablehttp.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.ApplyOnRR(req)
|
||||
|
||||
// Use direct map access since headers preserve exact casing
|
||||
if got := req.Header["X-API-Key"]; len(got) == 0 || got[0] != "secret123" {
|
||||
t.Errorf("X-API-Key = %v, want [secret123]", got)
|
||||
}
|
||||
if got := req.Header["X-Custom"]; len(got) == 0 || got[0] != "value" {
|
||||
t.Errorf("X-Custom = %v, want [value]", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCookiesAuthStrategy(t *testing.T) {
|
||||
secret := &Secret{
|
||||
Cookies: []Cookie{
|
||||
{Key: "session", Value: "abc123"},
|
||||
{Key: "auth", Value: "xyz789"},
|
||||
},
|
||||
}
|
||||
strategy := NewCookiesAuthStrategy(secret)
|
||||
|
||||
t.Run("Apply", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com", nil)
|
||||
strategy.Apply(req)
|
||||
|
||||
cookies := req.Cookies()
|
||||
if len(cookies) != 2 {
|
||||
t.Errorf("Expected 2 cookies, got %d", len(cookies))
|
||||
}
|
||||
|
||||
found := make(map[string]string)
|
||||
for _, c := range cookies {
|
||||
found[c.Name] = c.Value
|
||||
}
|
||||
if found["session"] != "abc123" {
|
||||
t.Errorf("session cookie = %v, want abc123", found["session"])
|
||||
}
|
||||
if found["auth"] != "xyz789" {
|
||||
t.Errorf("auth cookie = %v, want xyz789", found["auth"])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ApplyOnRR replaces existing cookies", func(t *testing.T) {
|
||||
req, _ := retryablehttp.NewRequest("GET", "http://example.com", nil)
|
||||
// Add existing cookie that should be replaced
|
||||
req.AddCookie(&http.Cookie{Name: "session", Value: "old_value"})
|
||||
// Add existing cookie that should be kept
|
||||
req.AddCookie(&http.Cookie{Name: "other", Value: "keep_me"})
|
||||
|
||||
strategy.ApplyOnRR(req)
|
||||
|
||||
cookies := req.Cookies()
|
||||
found := make(map[string]string)
|
||||
for _, c := range cookies {
|
||||
found[c.Name] = c.Value
|
||||
}
|
||||
|
||||
// New cookie values should override old ones
|
||||
if found["session"] != "abc123" {
|
||||
t.Errorf("session cookie = %v, want abc123", found["session"])
|
||||
}
|
||||
if found["auth"] != "xyz789" {
|
||||
t.Errorf("auth cookie = %v, want xyz789", found["auth"])
|
||||
}
|
||||
// Existing non-replaced cookie should be preserved
|
||||
if found["other"] != "keep_me" {
|
||||
t.Errorf("other cookie = %v, want keep_me", found["other"])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestQueryAuthStrategy(t *testing.T) {
|
||||
secret := &Secret{
|
||||
Params: []KV{
|
||||
{Key: "api_key", Value: "secret123"},
|
||||
{Key: "token", Value: "abc"},
|
||||
},
|
||||
}
|
||||
strategy := NewQueryAuthStrategy(secret)
|
||||
|
||||
t.Run("Apply", func(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "http://example.com/path?existing=value", nil)
|
||||
strategy.Apply(req)
|
||||
|
||||
query := req.URL.Query()
|
||||
if got := query.Get("api_key"); got != "secret123" {
|
||||
t.Errorf("api_key = %v, want secret123", got)
|
||||
}
|
||||
if got := query.Get("token"); got != "abc" {
|
||||
t.Errorf("token = %v, want abc", got)
|
||||
}
|
||||
if got := query.Get("existing"); got != "value" {
|
||||
t.Errorf("existing = %v, want value", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ApplyOnRR", func(t *testing.T) {
|
||||
req, _ := retryablehttp.NewRequest("GET", "http://example.com/path?existing=value", nil)
|
||||
strategy.ApplyOnRR(req)
|
||||
|
||||
query := req.Request.URL.Query()
|
||||
if got := query.Get("api_key"); got != "secret123" {
|
||||
t.Errorf("api_key = %v, want secret123", got)
|
||||
}
|
||||
if got := query.Get("token"); got != "abc" {
|
||||
t.Errorf("token = %v, want abc", got)
|
||||
}
|
||||
if got := query.Get("existing"); got != "value" {
|
||||
t.Errorf("existing = %v, want value", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package authprovider
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
urlutil "github.com/projectdiscovery/utils/url"
|
||||
)
|
||||
|
||||
func createTestSecretsFile(t *testing.T, content string) string {
|
||||
t.Helper()
|
||||
tmpDir := t.TempDir()
|
||||
filePath := filepath.Join(tmpDir, "secrets.yaml")
|
||||
err := os.WriteFile(filePath, []byte(content), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test secrets file: %v", err)
|
||||
}
|
||||
return filePath
|
||||
}
|
||||
|
||||
func TestFileAuthProviderLookupAddr(t *testing.T) {
|
||||
content := `id: test
|
||||
info:
|
||||
name: test
|
||||
static:
|
||||
- type: BasicAuth
|
||||
domains:
|
||||
- example.com
|
||||
- api.example.com:443
|
||||
username: user
|
||||
password: pass
|
||||
- type: BearerToken
|
||||
domains-regex:
|
||||
- ".*\\.test\\.com"
|
||||
token: regextoken
|
||||
`
|
||||
filePath := createTestSecretsFile(t, content)
|
||||
provider, err := NewFileAuthProvider(filePath)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFileAuthProvider() error = %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
addr string
|
||||
wantCount int
|
||||
}{
|
||||
{
|
||||
name: "exact match",
|
||||
addr: "example.com",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "exact match case insensitive",
|
||||
addr: "EXAMPLE.COM",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "with port 443 normalized",
|
||||
addr: "example.com:443",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "with port 80 normalized",
|
||||
addr: "example.com:80",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "subdomain exact match",
|
||||
addr: "api.example.com",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "regex match",
|
||||
addr: "foo.test.com",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "regex match subdomain",
|
||||
addr: "bar.baz.test.com",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "no match",
|
||||
addr: "unknown.com",
|
||||
wantCount: 0,
|
||||
},
|
||||
{
|
||||
name: "non-standard port not normalized",
|
||||
addr: "example.com:8080",
|
||||
wantCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
strategies := provider.LookupAddr(tt.addr)
|
||||
if len(strategies) != tt.wantCount {
|
||||
t.Errorf("LookupAddr(%q) returned %d strategies, want %d", tt.addr, len(strategies), tt.wantCount)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileAuthProviderLookupURL(t *testing.T) {
|
||||
content := `id: test
|
||||
info:
|
||||
name: test
|
||||
static:
|
||||
- type: BasicAuth
|
||||
domains:
|
||||
- example.com
|
||||
username: user
|
||||
password: pass
|
||||
`
|
||||
filePath := createTestSecretsFile(t, content)
|
||||
provider, err := NewFileAuthProvider(filePath)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFileAuthProvider() error = %v", err)
|
||||
}
|
||||
|
||||
t.Run("LookupURL", func(t *testing.T) {
|
||||
u, _ := url.Parse("https://example.com/path")
|
||||
strategies := provider.LookupURL(u)
|
||||
if len(strategies) != 1 {
|
||||
t.Errorf("LookupURL() returned %d strategies, want 1", len(strategies))
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("LookupURLX", func(t *testing.T) {
|
||||
u, _ := urlutil.Parse("https://example.com/path")
|
||||
strategies := provider.LookupURLX(u)
|
||||
if len(strategies) != 1 {
|
||||
t.Errorf("LookupURLX() returned %d strategies, want 1", len(strategies))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestMultiAuthProvider(t *testing.T) {
|
||||
content1 := `id: test1
|
||||
info:
|
||||
name: test1
|
||||
static:
|
||||
- type: BasicAuth
|
||||
domains:
|
||||
- first.com
|
||||
username: user1
|
||||
password: pass1
|
||||
`
|
||||
content2 := `id: test2
|
||||
info:
|
||||
name: test2
|
||||
static:
|
||||
- type: BearerToken
|
||||
domains:
|
||||
- second.com
|
||||
token: token2
|
||||
`
|
||||
filePath1 := createTestSecretsFile(t, content1)
|
||||
provider1, err := NewFileAuthProvider(filePath1)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFileAuthProvider() error = %v", err)
|
||||
}
|
||||
|
||||
// Create second file in different temp dir
|
||||
tmpDir2 := t.TempDir()
|
||||
filePath2 := filepath.Join(tmpDir2, "secrets2.yaml")
|
||||
err = os.WriteFile(filePath2, []byte(content2), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test secrets file: %v", err)
|
||||
}
|
||||
provider2, err := NewFileAuthProvider(filePath2)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFileAuthProvider() error = %v", err)
|
||||
}
|
||||
|
||||
multi := NewMultiAuthProvider(provider1, provider2)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
addr string
|
||||
wantCount int
|
||||
}{
|
||||
{
|
||||
name: "match first provider",
|
||||
addr: "first.com",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "match second provider",
|
||||
addr: "second.com",
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "no match",
|
||||
addr: "third.com",
|
||||
wantCount: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
strategies := multi.LookupAddr(tt.addr)
|
||||
if len(strategies) != tt.wantCount {
|
||||
t.Errorf("LookupAddr(%q) returned %d strategies, want %d", tt.addr, len(strategies), tt.wantCount)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFileAuthProviderErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
content string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty secrets",
|
||||
content: `id: test`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid secret type",
|
||||
content: `id: test
|
||||
static:
|
||||
- type: InvalidType
|
||||
domains:
|
||||
- example.com
|
||||
`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing required field",
|
||||
content: `id: test
|
||||
static:
|
||||
- type: BasicAuth
|
||||
domains:
|
||||
- example.com
|
||||
username: user
|
||||
`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
filePath := createTestSecretsFile(t, tt.content)
|
||||
_, err := NewFileAuthProvider(filePath)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("NewFileAuthProvider() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user