mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-20 13:04:25 +02:00
* s3api: check the direct peer against the trusted-proxy allowlist * s3: verify X-Forwarded-Prefix only from trusted proxies * s3: note that trusted proxies must sanitize forwarded headers
152 lines
4.7 KiB
Go
152 lines
4.7 KiB
Go
package policy_engine
|
|
|
|
import (
|
|
"net/http"
|
|
"testing"
|
|
)
|
|
|
|
func newReq(remoteAddr string, xff, xRealIP string) *http.Request {
|
|
r := &http.Request{RemoteAddr: remoteAddr, Header: http.Header{}}
|
|
if xff != "" {
|
|
r.Header.Set("X-Forwarded-For", xff)
|
|
}
|
|
if xRealIP != "" {
|
|
r.Header.Set("X-Real-Ip", xRealIP)
|
|
}
|
|
return r
|
|
}
|
|
|
|
func TestTrustedProxies_IsTrusted(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.5", "192.168.0.0/16"})
|
|
if !tp.IsTrusted("10.0.0.5") {
|
|
t.Error("bare IP should be trusted")
|
|
}
|
|
if !tp.IsTrusted("192.168.1.100") {
|
|
t.Error("IP in CIDR should be trusted")
|
|
}
|
|
if tp.IsTrusted("8.8.8.8") {
|
|
t.Error("public IP should not be trusted")
|
|
}
|
|
if tp.IsTrusted("not-an-ip") {
|
|
t.Error("invalid IP should not be trusted")
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_CanonicalizesBareIPv6(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"2001:0db8::1"})
|
|
if !tp.IsTrusted("2001:db8::1") {
|
|
t.Error("canonical IPv6 should match non-canonical allowlist entry")
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_InvalidBareIPSkipped(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"not-an-ip", "10.0.0.5"})
|
|
if tp.IsTrusted("not-an-ip") {
|
|
t.Error("invalid entry should not be stored")
|
|
}
|
|
if !tp.IsTrusted("10.0.0.5") {
|
|
t.Error("valid entry after invalid one should still load")
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_IsTrustedPeer(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
if !tp.IsTrustedPeer(newReq("10.0.0.5:1234", "", "")) {
|
|
t.Error("peer in allowlist should be trusted")
|
|
}
|
|
if !tp.IsTrustedPeer(newReq("10.0.0.5:1234", "8.8.8.8", "")) {
|
|
t.Error("forwarded headers must not affect peer trust")
|
|
}
|
|
if tp.IsTrustedPeer(newReq("8.8.8.8:1234", "", "")) {
|
|
t.Error("peer outside allowlist should not be trusted")
|
|
}
|
|
if tp.IsTrustedPeer(newReq("not-an-addr", "", "")) {
|
|
t.Error("malformed RemoteAddr should not be trusted")
|
|
}
|
|
if tp.IsTrustedPeer(nil) {
|
|
t.Error("nil request should not be trusted")
|
|
}
|
|
var nilTP *TrustedProxies
|
|
if nilTP.IsTrustedPeer(newReq("10.0.0.5:1234", "", "")) {
|
|
t.Error("nil TrustedProxies should not trust any peer")
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_NilNotTrusted(t *testing.T) {
|
|
var tp *TrustedProxies
|
|
if tp.IsTrusted("127.0.0.1") {
|
|
t.Error("nil TrustedProxies should not trust any IP")
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_DirectPeerWhenUntrusted(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("203.0.113.5:1234", "8.8.8.8", "1.1.1.1")
|
|
if got := tp.ExtractSourceIP(r); got != "203.0.113.5" {
|
|
t.Errorf("untrusted peer: want 203.0.113.5, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_XForwardedFor(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("10.0.0.1:1234", "8.8.8.8, 10.0.0.2", "")
|
|
if got := tp.ExtractSourceIP(r); got != "8.8.8.8" {
|
|
t.Errorf("trusted proxy: want 8.8.8.8, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_AllTrustedReturnsLeftmost(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("10.0.0.1:1234", "10.0.0.5, 10.0.0.6", "")
|
|
if got := tp.ExtractSourceIP(r); got != "10.0.0.5" {
|
|
t.Errorf("all-trusted chain: want leftmost 10.0.0.5, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_MalformedXFFFallsBackToPeer(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("10.0.0.1:1234", "8.8.8.8, garbage", "")
|
|
if got := tp.ExtractSourceIP(r); got != "10.0.0.1" {
|
|
t.Errorf("malformed XFF: want direct peer 10.0.0.1, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_XRealIP(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("10.0.0.1:1234", "", "8.8.8.8")
|
|
if got := tp.ExtractSourceIP(r); got != "8.8.8.8" {
|
|
t.Errorf("X-Real-Ip: want 8.8.8.8, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_XForwardedForPreferredOverXRealIP(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("10.0.0.1:1234", "8.8.8.8", "1.1.1.1")
|
|
if got := tp.ExtractSourceIP(r); got != "8.8.8.8" {
|
|
t.Errorf("XFF should win over X-Real-Ip: want 8.8.8.8, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_NoTrustedProxiesUsesPeer(t *testing.T) {
|
|
tp := NewTrustedProxies(nil)
|
|
r := newReq("10.0.0.1:1234", "8.8.8.8", "1.1.1.1")
|
|
if got := tp.ExtractSourceIP(r); got != "10.0.0.1" {
|
|
t.Errorf("empty allowlist: want 10.0.0.1, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_NilRequest(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
if got := tp.ExtractSourceIP(nil); got != "" {
|
|
t.Errorf("nil request: want empty, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestTrustedProxies_ExtractSourceIP_UnixSocket(t *testing.T) {
|
|
tp := NewTrustedProxies([]string{"10.0.0.0/24"})
|
|
r := newReq("@", "", "")
|
|
if got := tp.ExtractSourceIP(r); got != "@" {
|
|
t.Errorf("unix socket: want @, got %s", got)
|
|
}
|
|
}
|