feat: ext-auth plugin: Blacklist and whitelist modes support HTTP request method matching (#1798)

This commit is contained in:
韩贤涛
2025-02-26 20:54:52 +08:00
committed by GitHub
parent 2d8a8f26da
commit 90ca903d2e
8 changed files with 311 additions and 132 deletions

View File

@@ -260,19 +260,28 @@ func parseMatchRules(json gjson.Result, config *ExtAuthConfig) error {
var err error
matchListConfig.ForEach(func(key, value gjson.Result) bool {
pathMatcher, buildErr := expr.BuildStringMatcher(
value.Get("match_rule_type").Str,
value.Get("match_rule_path").Str, false)
if buildErr != nil {
err = fmt.Errorf("failed to build string matcher for rule with domain %q, path %q, type %q: %w",
value.Get("match_rule_domain").Str,
value.Get("match_rule_path").Str,
value.Get("match_rule_type").Str,
buildErr)
return false // stop iterating
domain := value.Get("match_rule_domain").Str
methodArray := value.Get("match_rule_method").Array()
matchRuleType := value.Get("match_rule_type").Str
matchRulePath := value.Get("match_rule_path").Str
var pathMatcher expr.Matcher
var buildErr error
if matchRuleType == "" && matchRulePath == "" {
pathMatcher = nil
} else {
pathMatcher, buildErr = expr.BuildStringMatcher(matchRuleType, matchRulePath, false)
if buildErr != nil {
err = fmt.Errorf("failed to build string matcher for rule with domain %q, method %v, path %q, type %q: %w",
domain, methodArray, matchRulePath, matchRuleType, buildErr)
return false // stop iterating
}
}
ruleList = append(ruleList, expr.Rule{
Domain: value.Get("match_rule_domain").Str,
Domain: domain,
Method: convertToStringList(methodArray),
Path: pathMatcher,
})
return true // keep iterating
@@ -297,3 +306,11 @@ func convertToStringMap(result gjson.Result) map[string]string {
})
return m
}
func convertToStringList(results []gjson.Result) []string {
interfaces := make([]string, len(results))
for i, result := range results {
interfaces[i] = result.String()
}
return interfaces
}

View File

@@ -218,6 +218,7 @@ func TestParseConfig(t *testing.T) {
RuleList: []expr.Rule{
{
Domain: "*.bar.com",
Method: []string{},
Path: func() expr.Matcher {
pathMatcher, err := expr.BuildStringMatcher(expr.MatchPatternPrefix, "/headers", false)
if err != nil {
@@ -248,6 +249,7 @@ func TestParseConfig(t *testing.T) {
"match_list": [
{
"match_rule_domain": "*.foo.com",
"match_rule_method": ["GET"],
"match_rule_path": "/api",
"match_rule_type": "exact"
}
@@ -269,6 +271,7 @@ func TestParseConfig(t *testing.T) {
RuleList: []expr.Rule{
{
Domain: "*.foo.com",
Method: []string{"GET"},
Path: func() expr.Matcher {
pathMatcher, err := expr.BuildStringMatcher(expr.MatchPatternExact, "/api", false)
if err != nil {
@@ -284,6 +287,50 @@ func TestParseConfig(t *testing.T) {
StatusOnError: 403,
},
},
{
name: "Valid Match Rules with Whitelist - Only Method",
json: `{
"http_service": {
"endpoint_mode": "envoy",
"endpoint": {
"service_name": "example.com",
"service_port": 80,
"path_prefix": "/auth"
}
},
"match_type": "whitelist",
"match_list": [
{
"match_rule_method": ["GET"]
}
]
}`,
expected: ExtAuthConfig{
HttpService: HttpService{
EndpointMode: "envoy",
Client: wrapper.NewClusterClient(wrapper.FQDNCluster{
FQDN: "example.com",
Port: 80,
Host: "",
}),
PathPrefix: "/auth",
Timeout: 1000,
},
MatchRules: expr.MatchRules{
Mode: "whitelist",
RuleList: []expr.Rule{
{
Domain: "",
Method: []string{"GET"},
Path: nil,
},
},
},
FailureModeAllow: false,
FailureModeAllowHeaderAdd: false,
StatusOnError: 403,
},
},
{
name: "Missing Match Type",
json: `{
@@ -342,12 +389,13 @@ func TestParseConfig(t *testing.T) {
"match_list": [
{
"match_rule_domain": "*.bar.com",
"match_rule_method": ["POST","PUT","DELETE"],
"match_rule_path": "/headers",
"match_rule_type": "invalid_type"
}
]
}`,
expectedErr: `failed to build string matcher for rule with domain "*.bar.com", path "/headers", type "invalid_type": unknown string matcher type`,
expectedErr: `failed to build string matcher for rule with domain "*.bar.com", method [POST PUT DELETE], path "/headers", type "invalid_type": unknown string matcher type`,
},
}