forked from TrueCloudLab/frostfs-s3-gw
386 lines
11 KiB
Go
386 lines
11 KiB
Go
|
package middleware
|
||
|
|
||
|
import (
|
||
|
"net/http"
|
||
|
"net/http/httptest"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/stretchr/testify/require"
|
||
|
"go.uber.org/zap/zaptest"
|
||
|
)
|
||
|
|
||
|
type VHSSettingsMock struct {
|
||
|
domains []string
|
||
|
}
|
||
|
|
||
|
func (v *VHSSettingsMock) Domains() []string {
|
||
|
return v.domains
|
||
|
}
|
||
|
|
||
|
func (v *VHSSettingsMock) GlobalVHS() bool {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (v *VHSSettingsMock) VHSNamespacesEnabled() map[string]bool {
|
||
|
return make(map[string]bool)
|
||
|
}
|
||
|
|
||
|
func TestIsVHSAddress(t *testing.T) {
|
||
|
for _, tc := range []struct {
|
||
|
name string
|
||
|
vhsEnabledFlag bool
|
||
|
vhsNamespaced map[string]bool
|
||
|
namespace string
|
||
|
expected bool
|
||
|
}{
|
||
|
{
|
||
|
name: "vhs disabled",
|
||
|
expected: false,
|
||
|
},
|
||
|
{
|
||
|
name: "vhs disabled for namespace",
|
||
|
vhsEnabledFlag: true,
|
||
|
vhsNamespaced: map[string]bool{
|
||
|
"kapusta": false,
|
||
|
},
|
||
|
namespace: "kapusta",
|
||
|
expected: false,
|
||
|
},
|
||
|
{
|
||
|
name: "vhs enabled (global vhs flag)",
|
||
|
vhsEnabledFlag: true,
|
||
|
expected: true,
|
||
|
},
|
||
|
{
|
||
|
name: "vhs enabled for namespace",
|
||
|
vhsNamespaced: map[string]bool{
|
||
|
"kapusta": true,
|
||
|
},
|
||
|
namespace: "kapusta",
|
||
|
expected: true,
|
||
|
},
|
||
|
} {
|
||
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
actual := isVHSAddress(tc.vhsEnabledFlag, tc.vhsNamespaced, tc.namespace)
|
||
|
require.Equal(t, tc.expected, actual)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPreparePathStyleAddress(t *testing.T) {
|
||
|
bkt, obj := "test-bucket", "test-object"
|
||
|
|
||
|
for _, tc := range []struct {
|
||
|
name string
|
||
|
urlParams string
|
||
|
expectedReqType ReqType
|
||
|
expectedBktName string
|
||
|
expectedObjName string
|
||
|
}{
|
||
|
{
|
||
|
name: "bucket request",
|
||
|
urlParams: "/" + bkt,
|
||
|
expectedReqType: bucketType,
|
||
|
expectedBktName: bkt,
|
||
|
},
|
||
|
{
|
||
|
name: "bucket request with slash",
|
||
|
urlParams: "/" + bkt + "/",
|
||
|
expectedReqType: bucketType,
|
||
|
expectedBktName: bkt,
|
||
|
},
|
||
|
{
|
||
|
name: "object request",
|
||
|
urlParams: "/" + bkt + "/" + obj,
|
||
|
expectedReqType: objectType,
|
||
|
expectedBktName: bkt,
|
||
|
expectedObjName: obj,
|
||
|
},
|
||
|
{
|
||
|
name: "object request with slash",
|
||
|
urlParams: "/" + bkt + "/" + obj + "/",
|
||
|
expectedReqType: objectType,
|
||
|
expectedBktName: bkt,
|
||
|
expectedObjName: obj + "/",
|
||
|
},
|
||
|
{
|
||
|
name: "none type request",
|
||
|
urlParams: "/",
|
||
|
expectedReqType: noneType,
|
||
|
},
|
||
|
} {
|
||
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
reqInfo := &ReqInfo{}
|
||
|
r := httptest.NewRequest(http.MethodGet, tc.urlParams, nil)
|
||
|
|
||
|
preparePathStyleAddress(reqInfo, r, reqLogOrDefault(r.Context(), zaptest.NewLogger(t)))
|
||
|
require.Equal(t, tc.expectedReqType, reqInfo.RequestType)
|
||
|
require.Equal(t, tc.expectedBktName, reqInfo.BucketName)
|
||
|
require.Equal(t, tc.expectedObjName, reqInfo.ObjectName)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestPrepareVHSAddress(t *testing.T) {
|
||
|
bkt, obj, domain := "test-bucket", "test-object", "domain.com"
|
||
|
|
||
|
for _, tc := range []struct {
|
||
|
name string
|
||
|
domains []string
|
||
|
host string
|
||
|
urlParams string
|
||
|
expectedReqType ReqType
|
||
|
expectedBktName string
|
||
|
expectedObjName string
|
||
|
}{
|
||
|
{
|
||
|
name: "bucket request, the domain matched",
|
||
|
domains: []string{domain},
|
||
|
host: bkt + "." + domain,
|
||
|
urlParams: "/",
|
||
|
expectedReqType: bucketType,
|
||
|
expectedBktName: bkt,
|
||
|
},
|
||
|
{
|
||
|
name: "object request, the domain matched",
|
||
|
domains: []string{domain},
|
||
|
host: bkt + "." + domain,
|
||
|
urlParams: "/" + obj,
|
||
|
expectedReqType: objectType,
|
||
|
expectedBktName: bkt,
|
||
|
expectedObjName: obj,
|
||
|
},
|
||
|
{
|
||
|
name: "object request with slash, the domain matched",
|
||
|
domains: []string{domain},
|
||
|
host: bkt + "." + domain,
|
||
|
urlParams: "/" + obj + "/",
|
||
|
expectedReqType: objectType,
|
||
|
expectedBktName: bkt,
|
||
|
expectedObjName: obj + "/",
|
||
|
},
|
||
|
{
|
||
|
name: "list-buckets request, the domain matched",
|
||
|
domains: []string{domain},
|
||
|
host: domain,
|
||
|
urlParams: "/",
|
||
|
expectedReqType: noneType,
|
||
|
},
|
||
|
{
|
||
|
name: "bucket request, the domain don't match",
|
||
|
host: bkt + "." + domain,
|
||
|
urlParams: "/",
|
||
|
expectedReqType: bucketType,
|
||
|
expectedBktName: bkt,
|
||
|
},
|
||
|
{
|
||
|
name: "object request, the domain don't match",
|
||
|
host: bkt + "." + domain,
|
||
|
urlParams: "/" + obj,
|
||
|
expectedReqType: objectType,
|
||
|
expectedBktName: bkt,
|
||
|
expectedObjName: obj,
|
||
|
},
|
||
|
{
|
||
|
name: "object request with slash, the domain don't match",
|
||
|
host: bkt + "." + domain,
|
||
|
urlParams: "/" + obj + "/",
|
||
|
expectedReqType: objectType,
|
||
|
expectedBktName: bkt,
|
||
|
expectedObjName: obj + "/",
|
||
|
},
|
||
|
{
|
||
|
name: "list-buckets request, the domain don't match (list-buckets isn't supported if the domains don't match)",
|
||
|
host: domain,
|
||
|
urlParams: "/",
|
||
|
expectedReqType: bucketType,
|
||
|
expectedBktName: strings.Split(domain, ".")[0],
|
||
|
},
|
||
|
} {
|
||
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
reqInfo := &ReqInfo{}
|
||
|
vhsSettings := &VHSSettingsMock{domains: tc.domains}
|
||
|
r := httptest.NewRequest(http.MethodGet, tc.urlParams, nil)
|
||
|
r.Host = tc.host
|
||
|
|
||
|
prepareVHSAddress(reqInfo, r, vhsSettings)
|
||
|
require.Equal(t, tc.expectedReqType, reqInfo.RequestType)
|
||
|
require.Equal(t, tc.expectedBktName, reqInfo.BucketName)
|
||
|
require.Equal(t, tc.expectedObjName, reqInfo.ObjectName)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestCheckDomains(t *testing.T) {
|
||
|
for _, tc := range []struct {
|
||
|
name string
|
||
|
domains []string
|
||
|
requestURL string
|
||
|
expectedBktName string
|
||
|
expectedMatch bool
|
||
|
}{
|
||
|
{
|
||
|
name: "valid url with bktName and namespace (wildcard after protocol infix)",
|
||
|
domains: []string{"s3.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.s3.kapusta.domain.com",
|
||
|
expectedBktName: "bktA",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url without bktName and namespace (wildcard after protocol infix)",
|
||
|
domains: []string{"s3.<wildcard>.domain.com"},
|
||
|
requestURL: "s3.kapusta.domain.com",
|
||
|
expectedBktName: "",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with invalid bktName (wildcard after protocol infix)",
|
||
|
domains: []string{"s3.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.bktB.s3.kapusta.domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url without namespace (wildcard after protocol infix)",
|
||
|
domains: []string{"s3.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.s3.domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with invalid infix (wildcard after protocol infix)",
|
||
|
domains: []string{"s3.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.s4.kapusta.domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with invalid postfix (wildcard after protocol infix)",
|
||
|
domains: []string{"s3.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.s3.kapusta.dom.su",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url with bktName and namespace (wildcard at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.kapusta.domain.com",
|
||
|
expectedBktName: "bktA",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url without bktName and namespace (wildcard at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.domain.com"},
|
||
|
requestURL: "kapusta.domain.com",
|
||
|
expectedBktName: "",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with invalid bktName (wildcard at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.bktB.kapusta.domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "collision test - true, because we cannot clearly distinguish a namespace from a bucket (wildcard at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.domain.com",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url (fewer hosts)",
|
||
|
domains: []string{"<wildcard>.domain.com"},
|
||
|
requestURL: "domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with invalid postfix (wildcard at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.kapusta.dom.su",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url with bktName and without wildcard (root namaspace)",
|
||
|
domains: []string{"domain.com"},
|
||
|
requestURL: "bktA.domain.com",
|
||
|
expectedBktName: "bktA",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url without bktName and without wildcard (root namaspace)",
|
||
|
domains: []string{"domain.com"},
|
||
|
requestURL: "domain.com",
|
||
|
expectedBktName: "",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with bktName without wildcard (root namaspace)",
|
||
|
domains: []string{"domain.com"},
|
||
|
requestURL: "bktA.dom.su",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url without wildcard (root namaspace)",
|
||
|
domains: []string{"domain.com"},
|
||
|
requestURL: "dom.su",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url, with a sorted list of domains",
|
||
|
domains: []string{"s3.<wildcard>.domain.com", "<wildcard>.domain.com", "domain.com"},
|
||
|
requestURL: "s3.kapusta.domain.com",
|
||
|
expectedBktName: "",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url with bktName, multiple wildcards (wildcards at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.s3.kapusta.domain.com",
|
||
|
expectedBktName: "bktA",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url without bktName, multiple wildcards (wildcards at the beginning of the domain)",
|
||
|
domains: []string{"<wildcard>.<wildcard>.domain.com"},
|
||
|
requestURL: "s3.kapusta.domain.com",
|
||
|
expectedBktName: "",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url with bktName, multiply wildcards",
|
||
|
domains: []string{"s3.<wildcard>.subdomain.<wildcard>.com"},
|
||
|
requestURL: "bktA.s3.kapusta.subdomain.domain.com",
|
||
|
expectedBktName: "bktA",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "valid url without bktName, multiply wildcards",
|
||
|
domains: []string{"s3.<wildcard>.subdomain.<wildcard>.com"},
|
||
|
requestURL: "s3.kapusta.subdomain.domain.com",
|
||
|
expectedBktName: "",
|
||
|
expectedMatch: true,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url without one wildcard",
|
||
|
domains: []string{"<wildcard>.<wildcard>.domain.com"},
|
||
|
requestURL: "kapusta.domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url, multiply wildcards",
|
||
|
domains: []string{"<wildcard>.<wildcard>.domain.com"},
|
||
|
requestURL: "s3.kapusta.dom.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
{
|
||
|
name: "invalid url with invalid bktName, multiply wildcards",
|
||
|
domains: []string{"<wildcard>.<wildcard>.domain.com"},
|
||
|
requestURL: "bktA.bktB.s3.kapusta.domain.com",
|
||
|
expectedMatch: false,
|
||
|
},
|
||
|
} {
|
||
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
bktName, match := checkDomain(tc.requestURL, tc.domains)
|
||
|
require.Equal(t, tc.expectedBktName, bktName)
|
||
|
require.Equal(t, tc.expectedMatch, match)
|
||
|
})
|
||
|
}
|
||
|
}
|