diff --git a/example/kong/.gitignore b/example/kong/.gitignore new file mode 100644 index 0000000..a83e93d --- /dev/null +++ b/example/kong/.gitignore @@ -0,0 +1,2 @@ +coraza-proxy-wasm-kong.* +kong.env \ No newline at end of file diff --git a/example/kong/Makefile b/example/kong/Makefile new file mode 100644 index 0000000..8a98608 --- /dev/null +++ b/example/kong/Makefile @@ -0,0 +1,30 @@ +#!/bin/bash + +APP_NAME=coraza-proxy-wasm-kong +DOCKER_NETWORK=$(APP_NAME)-net +UPSTREAM_CONTAINER_NAME=$(APP_NAME)-upstream +UPSTREAM_HOST=upstream + +run: launch-kong register-upstream + +launch-kong: + mkdir -p ./build + cp $$(dirname $$(dirname $$(pwd)))/build/main.wasm ./build/coraza-proxy-wasm.wasm + curl -Ls https://get.konghq.com/quickstart | bash -s -- -a $(APP_NAME) -i incubator -t gateway-wasmer-3.0.0.0 \ + -e "KONG_LOG_LEVEL=debug" -e "KONG_WASM=on" -e "KONG_WASM_MODULES=/wasm/coraza-proxy-wasm.wasm" -v $$(pwd)/build:/wasm + +register-upstream: + @docker rm -f $(UPSTREAM_CONTAINER_NAME) || true + docker run --name=$(UPSTREAM_CONTAINER_NAME) --network=$(DOCKER_NETWORK) --network-alias=$(UPSTREAM_HOST) -p "10080:10080" -d jcchavezs/httpmole -response-status=201 + http POST :8001/services/ name="upstream" host="$(UPSTREAM_HOST)" path="/" port:=10080 protocol="http" + http POST :8001/services/upstream/routes name="upstream" "paths[]=/" "paths[]=/admin" + http POST :8001/services/upstream/plugins name="proxy-wasm" \ + "config[filters][0][name]=coraza-proxy-wasm" \ + "config[filters][0][config]={\"rules\":[\"Include @demo-conf\",\"Include @crs-setup-demo-conf\",\"SecDebugLogLevel 3\",\"Include @owasp_crs/*.conf\",\"SecRule REQUEST_URI \\\"@streq /admin\\\" \\\"id:101,phase:1,t:lowercase,deny\\\" \\\nSecRule REQUEST_BODY \\\"@rx maliciouspayload\\\" \\\"id:102,phase:2,t:lowercase,deny\\\" \\\nSecRule RESPONSE_HEADERS::status \\\"@rx 406\\\" \\\"id:103,phase:3,t:lowercase,deny\\\" \\\nSecRule RESPONSE_BODY \\\"@contains responsebodycode\\\" \\\"id:104,phase:4,t:lowercase,deny\\\"\"]}" + +logs: + docker logs -f coraza-proxy-wasm-kong-gateway + +clean: + @docker rm -f $(UPSTREAM_CONTAINER_NAME) || true + curl -Ls https://get.konghq.com/quickstart | bash -s -- -a $(APP_NAME) -d diff --git a/magefiles/magefile.go b/magefiles/magefile.go index 7fbc2e4..a6f91ff 100644 --- a/magefiles/magefile.go +++ b/magefiles/magefile.go @@ -172,6 +172,9 @@ func Build() error { if os.Getenv("MEMSTATS") == "true" { buildTags = append(buildTags, "memstats") } + if os.Getenv("METRICS") == "false" { + buildTags = append(buildTags, "disable_metrics") + } buildTagArg := fmt.Sprintf("-tags='%s'", strings.Join(buildTags, " ")) diff --git a/wasmplugin/metrics.go b/wasmplugin/metrics.go index 21c1379..f56fb5a 100644 --- a/wasmplugin/metrics.go +++ b/wasmplugin/metrics.go @@ -1,6 +1,8 @@ // Copyright The OWASP Coraza contributors // SPDX-License-Identifier: Apache-2.0 +//go:build !disable_metrics + package wasmplugin import ( diff --git a/wasmplugin/metrics_off.go b/wasmplugin/metrics_off.go new file mode 100644 index 0000000..b7ddf1e --- /dev/null +++ b/wasmplugin/metrics_off.go @@ -0,0 +1,16 @@ +// Copyright The OWASP Coraza contributors +// SPDX-License-Identifier: Apache-2.0 + +//go:build disable_metrics + +package wasmplugin + +type wafMetrics struct{} + +func NewWAFMetrics() *wafMetrics { + return &wafMetrics{} +} + +func (*wafMetrics) CountTX() {} + +func (*wafMetrics) CountTXInterruption(_ string, _ int) {} diff --git a/wasmplugin/plugin.go b/wasmplugin/plugin.go index a72681a..44a41fb 100644 --- a/wasmplugin/plugin.go +++ b/wasmplugin/plugin.go @@ -65,6 +65,10 @@ func (ctx *corazaPlugin) OnPluginStart(pluginConfigurationSize int) types.OnPlug // buffering request body to files anyways. WithRootFS(root) + for _, r := range config.rules { + proxywasm.LogInfof("- %s", r) + } + waf, err := coraza.NewWAF(conf.WithDirectives(strings.Join(config.rules, "\n"))) if err != nil { proxywasm.LogCriticalf("failed to parse rules: %v", err) @@ -143,6 +147,7 @@ func (ctx *httpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) t ctx.httpProtocol = string(protocol) + proxywasm.LogCriticalf(uri, method, ctx.httpProtocol) tx.ProcessURI(uri, method, ctx.httpProtocol) hs, err := proxywasm.GetHttpRequestHeaders() @@ -487,18 +492,18 @@ func retrieveAddressInfo(target string) (string, int) { } } srcPortRaw, err := proxywasm.GetProperty([]string{target, "port"}) - if err != nil { + if err == nil { + targetPort, err = parsePort(srcPortRaw) + if err != nil { + proxywasm.LogWarnf("failed to parse %s port: %v", target, err) + } + } else if targetPortStr != "" { // If GetProperty fails we rely on the port inside the Address property // Mostly useful for proxies other than Envoy targetPort, err = strconv.Atoi(targetPortStr) if err != nil { proxywasm.LogInfof("failed to get %s port: %v", target, err) } - } else { - targetPort, err = parsePort(srcPortRaw) - if err != nil { - proxywasm.LogWarnf("failed to parse %s port: %v", target, err) - } } return targetIP, targetPort }