diff --git a/plugins/wasm-go/extensions/oidc/go.mod b/plugins/wasm-go/extensions/oidc/go.mod index 663965d09..98bda0391 100644 --- a/plugins/wasm-go/extensions/oidc/go.mod +++ b/plugins/wasm-go/extensions/oidc/go.mod @@ -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 diff --git a/plugins/wasm-go/extensions/oidc/go.sum b/plugins/wasm-go/extensions/oidc/go.sum index 78b25580c..8fa2964e2 100644 --- a/plugins/wasm-go/extensions/oidc/go.sum +++ b/plugins/wasm-go/extensions/oidc/go.sum @@ -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= diff --git a/plugins/wasm-go/extensions/oidc/main.go b/plugins/wasm-go/extensions/oidc/main.go index 1e7cf656c..b5e97ec94 100644 --- a/plugins/wasm-go/extensions/oidc/main.go +++ b/plugins/wasm-go/extensions/oidc/main.go @@ -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) diff --git a/plugins/wasm-go/extensions/oidc/main_test.go b/plugins/wasm-go/extensions/oidc/main_test.go new file mode 100644 index 000000000..23811686a --- /dev/null +++ b/plugins/wasm-go/extensions/oidc/main_test.go @@ -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) + } + }) +}