mirror of
https://github.com/alibaba/higress.git
synced 2026-06-26 02:35:02 +08:00
fix(oidc): fail closed when verifier is unavailable (#4013)
Signed-off-by: EndlessSeeker <1766508902@qq.com> Co-authored-by: Jingze <52855280+Jing-ze@users.noreply.github.com>
This commit is contained in:
@@ -6,12 +6,19 @@ toolchain go1.24.4
|
||||
|
||||
require (
|
||||
github.com/higress-group/oauth2-proxy v1.0.1-0.20260605094027-396b01ca2ca4
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250822030947-8345453fddd0
|
||||
github.com/higress-group/wasm-go v1.0.2-0.20250911113549-cbf1cfcce774
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
)
|
||||
|
||||
require github.com/tidwall/sjson v1.2.5 // indirect
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
github.com/tetratelabs/wazero v1.7.2 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||
|
||||
@@ -16,8 +16,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/higress-group/oauth2-proxy v1.0.1-0.20260605094027-396b01ca2ca4 h1:P7p5oh95mvgi38QhIN+nHJJCJPGjWqv3UHAmKzo25ko=
|
||||
github.com/higress-group/oauth2-proxy v1.0.1-0.20260605094027-396b01ca2ca4/go.mod h1:sDlsoo4dx+Cx56vI5kegeXZAoQ4nnd7xWL7Oc4/4hLI=
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80 h1:xqmtTZI0JQ2O+Lg9/CE6c+Tw9KD6FnvWw8EpLVuuvfg=
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250611100342-5654e89a7a80/go.mod h1:tRI2LfMudSkKHhyv1uex3BWzcice2s/l8Ah8axporfA=
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250822030947-8345453fddd0 h1:YGdj8KBzVjabU3STUfwMZghB+VlX6YLfJtLbrsWaOD0=
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20250822030947-8345453fddd0/go.mod h1:tRI2LfMudSkKHhyv1uex3BWzcice2s/l8Ah8axporfA=
|
||||
github.com/higress-group/wasm-go v1.0.2-0.20250911113549-cbf1cfcce774 h1:3nzDlUZ8+Nc0c2f8y0wUiw6mnyu1+ZYT0mK7x9Oitro=
|
||||
github.com/higress-group/wasm-go v1.0.2-0.20250911113549-cbf1cfcce774/go.mod h1:882/J8ccU4i+LeyFKmeicbHWAYLj8y7YZr60zk0OOCI=
|
||||
github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
|
||||
@@ -36,6 +36,8 @@ github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
|
||||
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tetratelabs/wazero v1.7.2 h1:1+z5nXJNwMLPAWaTePFi49SSTL0IMx/i3Fg8Yc25GDc=
|
||||
github.com/tetratelabs/wazero v1.7.2/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@@ -54,5 +56,7 @@ golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -71,7 +71,14 @@ func onHttpRequestHeaders(ctx wrapper.HttpContext, config PluginConfig, log log.
|
||||
// TODO: remove this verifier after envoy support send request during parseConfig
|
||||
if err := config.oidcHandler.ValidateVerifier(); err != nil {
|
||||
log.Critical(err.Error())
|
||||
return types.ActionContinue
|
||||
_ = proxywasm.SendHttpResponseWithDetail(
|
||||
http.StatusServiceUnavailable,
|
||||
"oidc.verifier_unavailable",
|
||||
nil,
|
||||
[]byte("OIDC verifier is unavailable"),
|
||||
-1,
|
||||
)
|
||||
return types.ActionPause
|
||||
}
|
||||
|
||||
config.oidcHandler.ServeHTTP(rw, req)
|
||||
|
||||
93
plugins/wasm-go/extensions/oidc/main_test.go
Normal file
93
plugins/wasm-go/extensions/oidc/main_test.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
|
||||
"github.com/higress-group/wasm-go/pkg/test"
|
||||
)
|
||||
|
||||
func oidcTestConfig(matchList []map[string]interface{}) json.RawMessage {
|
||||
data, _ := json.Marshal(map[string]interface{}{
|
||||
"redirect_url": "http://foo.bar.com/oauth2/callback",
|
||||
"oidc_issuer_url": "http://127.0.0.1:65535/realms/poc",
|
||||
"client_id": "poc",
|
||||
"client_secret": "poc",
|
||||
"cookie_secret": "nqavJrGvRmQxWwGNptLdyUVKcBNZ2b18Guc1n_8DCfY=",
|
||||
"service_name": "keycloak.static",
|
||||
"service_port": 80,
|
||||
"service_host": "127.0.0.1:65535",
|
||||
"match_type": "whitelist",
|
||||
"match_list": matchList,
|
||||
"verifier_interval": "2s",
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
func TestOnHttpRequestHeadersVerifierUnavailable(t *testing.T) {
|
||||
test.RunTest(t, func(t *testing.T) {
|
||||
host, status := test.NewTestHost(oidcTestConfig(nil))
|
||||
defer host.Reset()
|
||||
if status != types.OnPluginStartStatusOK {
|
||||
t.Fatalf("plugin start status = %v, want %v", status, types.OnPluginStartStatusOK)
|
||||
}
|
||||
|
||||
action := host.CallOnHttpRequestHeaders([][2]string{
|
||||
{":scheme", "http"},
|
||||
{":authority", "foo.bar.com"},
|
||||
{":path", "/protected"},
|
||||
{":method", "GET"},
|
||||
})
|
||||
|
||||
if action != types.ActionPause {
|
||||
t.Fatalf("request action = %v, want %v", action, types.ActionPause)
|
||||
}
|
||||
if streamAction := host.GetHttpStreamAction(); streamAction != types.ActionPause {
|
||||
t.Fatalf("stream action = %v, want %v", streamAction, types.ActionPause)
|
||||
}
|
||||
localResponse := host.GetLocalResponse()
|
||||
if localResponse == nil {
|
||||
t.Fatal("local response is nil")
|
||||
}
|
||||
if localResponse.StatusCode != 503 {
|
||||
t.Fatalf("local response status = %d, want 503", localResponse.StatusCode)
|
||||
}
|
||||
if body := string(localResponse.Data); body != "OIDC verifier is unavailable" {
|
||||
t.Fatalf("local response body = %q, want %q", body, "OIDC verifier is unavailable")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestOnHttpRequestHeadersAllowlistBypassesVerifierCheck(t *testing.T) {
|
||||
test.RunTest(t, func(t *testing.T) {
|
||||
host, status := test.NewTestHost(oidcTestConfig([]map[string]interface{}{
|
||||
{
|
||||
"match_rule_domain": "foo.bar.com",
|
||||
"match_rule_path": "/public",
|
||||
"match_rule_type": "prefix",
|
||||
},
|
||||
}))
|
||||
defer host.Reset()
|
||||
if status != types.OnPluginStartStatusOK {
|
||||
t.Fatalf("plugin start status = %v, want %v", status, types.OnPluginStartStatusOK)
|
||||
}
|
||||
|
||||
action := host.CallOnHttpRequestHeaders([][2]string{
|
||||
{":scheme", "http"},
|
||||
{":authority", "foo.bar.com"},
|
||||
{":path", "/public/info"},
|
||||
{":method", "GET"},
|
||||
})
|
||||
|
||||
if action != types.ActionContinue {
|
||||
t.Fatalf("request action = %v, want %v", action, types.ActionContinue)
|
||||
}
|
||||
if streamAction := host.GetHttpStreamAction(); streamAction != types.ActionContinue {
|
||||
t.Fatalf("stream action = %v, want %v", streamAction, types.ActionContinue)
|
||||
}
|
||||
if localResponse := host.GetLocalResponse(); localResponse != nil {
|
||||
t.Fatalf("local response = %+v, want nil", localResponse)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user