pluginsdk/egress/egress_test.go
Alex Dunmow 39427c40e7 feat(egress): http.request capability + allowed_hosts manifest (ADR 0023)
Host-mediated outbound HTTP for wasm plugins: guest http.RoundTripper
over the http.request capability; the host performs the request under
policy. New egress package defines the host-pattern grammar (exact or
multi-label wildcard, public-suffix rejected), matching, resource
bounds, and the ErrDenied sentinel (ABI_ERROR_CODE_EGRESS_DENIED).
plugin.mod gains first-class AllowedHosts + MaxResponseMB; manifest
gains allowed_hosts=34, max_response_mb=35. CoreServices.OutboundHTTP
carries the transport. Golden roundtrip + denial-mapping tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 02:00:29 +08:00

68 lines
2.0 KiB
Go

package egress
import (
"errors"
"net/url"
"testing"
)
func TestParsePatternRejects(t *testing.T) {
for _, raw := range []string{
"", "*", "*.com", "*.co.uk", "*.uk",
"https://api.cal.com", "api.cal.com/path", "user@api.cal.com",
"*.*.cal.com", "api.cal.com:0", "api.cal.com:99999",
"*.", "-bad.com", "bad-.com",
} {
if _, err := ParsePattern(raw); err == nil {
t.Errorf("ParsePattern(%q) = nil error, want rejection", raw)
}
}
}
func TestParsePatternAccepts(t *testing.T) {
for _, raw := range []string{
"api.cal.com", "*.cal.com", "example.com",
"api.example.com:8443", "sub.deep.example.org",
} {
if _, err := ParsePattern(raw); err != nil {
t.Errorf("ParsePattern(%q) = %v, want accept", raw, err)
}
}
}
func TestAllowlistAllows(t *testing.T) {
al, err := ParseAllowlist([]string{"api.cal.com", "*.example.org", "api.svc.com:8443"})
if err != nil {
t.Fatalf("ParseAllowlist: %v", err)
}
tests := []struct {
url string
allow bool
}{
{"https://api.cal.com/v1/slots", true},
{"https://api.cal.com:443/v1/slots", true},
{"https://cal.com/", false}, // apex not matched by exact api.cal.com
{"http://api.cal.com/", false}, // http refused
{"https://api.cal.com:8443/", false}, // wrong port
{"https://a.example.org/", true}, // wildcard depth 1
{"https://a.b.c.example.org/", true}, // wildcard multi-label
{"https://example.org/", false}, // wildcard excludes apex
{"https://evilexample.org/", false}, // suffix must be dot-anchored
{"https://api.svc.com:8443/", true}, // explicit port
{"https://api.svc.com/", false}, // default port not authorized
}
for _, tt := range tests {
u, _ := url.Parse(tt.url)
err := al.Allows(u)
if tt.allow && err != nil {
t.Errorf("Allows(%q) = %v, want allow", tt.url, err)
}
if !tt.allow && err == nil {
t.Errorf("Allows(%q) = nil, want deny", tt.url)
}
if !tt.allow && err != nil && !errors.Is(err, ErrDenied) {
t.Errorf("Allows(%q) denial not ErrDenied: %v", tt.url, err)
}
}
}