wasm: strip port from host when match host (#626)

This commit is contained in:
澄潭
2023-11-07 17:11:56 +08:00
committed by GitHub
parent 26654aefc0
commit 9f5b795a4d
4 changed files with 75 additions and 1 deletions

View File

@@ -387,6 +387,8 @@ class RouteRuleMatcher {
return true;
}
request_host = Wasm::Common::Http::stripPortFromHost(request_host);
for (const auto& host_match : rule.hosts) {
const auto& host = host_match.second;
switch (host_match.first) {

View File

@@ -584,6 +584,48 @@ TEST_F(BasicAuthTest, RuleWithConsumerAllow) {
FilterHeadersStatus::Continue);
}
TEST_F(BasicAuthTest, GlobalAuthRuleWithDomainPort) {
std::string configuration = R"(
{
"global_auth": true,
"consumers" : [
{"credential" : "ok:test", "name" : "consumer_ok"},
{"credential" : "admin2:admin2", "name" : "consumer2"},
{"credential" : "YWRtaW4zOmFkbWluMw==", "name" : "consumer3"},
{"credential" : "admin:admin", "name" : "consumer"}
],
"_rules_" : [
{
"_match_domain_" : ["test.com", "*.example.com"],
"allow" : [ "consumer" ]
}
]
})";
BufferBase buffer;
buffer.set({configuration.data(), configuration.size()});
EXPECT_CALL(*mock_context_, getBuffer(WasmBufferType::PluginConfiguration))
.WillOnce([&buffer](WasmBufferType) { return &buffer; });
EXPECT_TRUE(root_context_->configure(configuration.size()));
authority_ = "www.example.com:8080";
cred_ = "admin:admin";
authorization_header_ = "Basic " + Base64::encode(cred_.data(), cred_.size());
EXPECT_EQ(context_->onRequestHeaders(0, false),
FilterHeadersStatus::Continue);
cred_ = "admin2:admin2";
authorization_header_ = "Basic " + Base64::encode(cred_.data(), cred_.size());
EXPECT_EQ(context_->onRequestHeaders(0, false),
FilterHeadersStatus::StopIteration);
authority_ = "abc.com";
authorization_header_ = "Basic " + Base64::encode(cred_.data(), cred_.size());
EXPECT_EQ(context_->onRequestHeaders(0, false),
FilterHeadersStatus::Continue);
}
TEST_F(BasicAuthTest, RuleWithEncryptedConsumerAllow) {
std::string configuration = R"(
{

View File

@@ -109,7 +109,6 @@ func (m *RuleMatcher[PluginConfig]) ParseRuleConfig(config gjson.Result,
if keyCount > 0 {
err := parsePluginConfig(config, &pluginConfig)
if err != nil {
proxywasm.LogWarnf("parse global config failed, err:%v", err)
globalConfigError = err
} else {
m.globalConfig = pluginConfig
@@ -185,7 +184,25 @@ func (m RuleMatcher[PluginConfig]) parseHostMatchConfig(config gjson.Result) []H
return hostMatchers
}
func stripPortFromHost(reqHost string) string {
// Port removing code is inspired by
// https://github.com/envoyproxy/envoy/blob/v1.17.0/source/common/http/header_utility.cc#L219
portStart := strings.LastIndexByte(reqHost, ':')
if portStart != -1 {
// According to RFC3986 v6 address is always enclosed in "[]".
// section 3.2.2.
v6EndIndex := strings.LastIndexByte(reqHost, ']')
if v6EndIndex == -1 || v6EndIndex < portStart {
if portStart+1 <= len(reqHost) {
return reqHost[:portStart]
}
}
}
return reqHost
}
func (m RuleMatcher[PluginConfig]) hostMatch(rule RuleConfig[PluginConfig], reqHost string) bool {
reqHost = stripPortFromHost(reqHost)
for _, hostMatch := range rule.hosts {
switch hostMatch.matchType {
case Suffix:

View File

@@ -118,6 +118,19 @@ func TestHostMatch(t *testing.T) {
host: "example.com",
result: false,
},
{
name: "exact port",
config: RuleConfig[customConfig]{
hosts: []HostMatcher{
{
matchType: Exact,
host: "www.example.com",
},
},
},
host: "www.example.com:8080",
result: true,
},
{
name: "any",
config: RuleConfig[customConfig]{