From 61d902db14bd5eb80f35763db845faccd3c63946 Mon Sep 17 00:00:00 2001 From: Manuel Alejandro de Brito Fontes Date: Mon, 4 Nov 2019 15:41:26 -0300 Subject: [PATCH] Remove Lua resty waf feature --- internal/ingress/annotations/annotations.go | 3 - .../ingress/annotations/luarestywaf/main.go | 126 ---------- .../annotations/luarestywaf/main_test.go | 86 ------- internal/ingress/controller/config/config.go | 4 - internal/ingress/controller/controller.go | 1 - .../ingress/controller/template/template.go | 36 +-- .../controller/template/template_test.go | 20 +- internal/ingress/types.go | 3 - internal/ingress/types_equals.go | 3 - rootfs/etc/nginx/template/nginx.tmpl | 71 +----- test/e2e/annotations/luarestywaf.go | 224 ------------------ 11 files changed, 12 insertions(+), 565 deletions(-) delete mode 100644 internal/ingress/annotations/luarestywaf/main.go delete mode 100644 internal/ingress/annotations/luarestywaf/main_test.go delete mode 100644 test/e2e/annotations/luarestywaf.go diff --git a/internal/ingress/annotations/annotations.go b/internal/ingress/annotations/annotations.go index 45c8b9c5ae..973ada6901 100644 --- a/internal/ingress/annotations/annotations.go +++ b/internal/ingress/annotations/annotations.go @@ -45,7 +45,6 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist" "k8s.io/ingress-nginx/internal/ingress/annotations/loadbalancing" "k8s.io/ingress-nginx/internal/ingress/annotations/log" - "k8s.io/ingress-nginx/internal/ingress/annotations/luarestywaf" "k8s.io/ingress-nginx/internal/ingress/annotations/mirror" "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/ingress/annotations/portinredirect" @@ -109,7 +108,6 @@ type Ingress struct { XForwardedPrefix string SSLCiphers string Logs log.Config - LuaRestyWAF luarestywaf.Config InfluxDB influxdb.Config ModSecurity modsecurity.Config Mirror mirror.Config @@ -157,7 +155,6 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor { "XForwardedPrefix": xforwardedprefix.NewParser(cfg), "SSLCiphers": sslcipher.NewParser(cfg), "Logs": log.NewParser(cfg), - "LuaRestyWAF": luarestywaf.NewParser(cfg), "InfluxDB": influxdb.NewParser(cfg), "BackendProtocol": backendprotocol.NewParser(cfg), "ModSecurity": modsecurity.NewParser(cfg), diff --git a/internal/ingress/annotations/luarestywaf/main.go b/internal/ingress/annotations/luarestywaf/main.go deleted file mode 100644 index 76b59ef8ee..0000000000 --- a/internal/ingress/annotations/luarestywaf/main.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package luarestywaf - -import ( - "strings" - - networking "k8s.io/api/networking/v1beta1" - - "k8s.io/ingress-nginx/internal/ingress/annotations/parser" - "k8s.io/ingress-nginx/internal/ingress/errors" - "k8s.io/ingress-nginx/internal/ingress/resolver" - "k8s.io/ingress-nginx/internal/sets" -) - -var luaRestyWAFModes = map[string]bool{"ACTIVE": true, "INACTIVE": true, "SIMULATE": true} - -// Config returns lua-resty-waf configuration for an Ingress rule -type Config struct { - Mode string `json:"mode"` - Debug bool `json:"debug"` - IgnoredRuleSets []string `json:"ignored-rulesets"` - ExtraRulesetString string `json:"extra-ruleset-string"` - ScoreThreshold int `json:"score-threshold"` - AllowUnknownContentTypes bool `json:"allow-unknown-content-types"` - ProcessMultipartBody bool `json:"process-multipart-body"` -} - -// Equal tests for equality between two Config types -func (e1 *Config) Equal(e2 *Config) bool { - if e1 == e2 { - return true - } - if e1 == nil || e2 == nil { - return false - } - if e1.Mode != e2.Mode { - return false - } - if e1.Debug != e2.Debug { - return false - } - - match := sets.StringElementsMatch(e1.IgnoredRuleSets, e2.IgnoredRuleSets) - if !match { - return false - } - - if e1.ExtraRulesetString != e2.ExtraRulesetString { - return false - } - if e1.ScoreThreshold != e2.ScoreThreshold { - return false - } - if e1.AllowUnknownContentTypes != e2.AllowUnknownContentTypes { - return false - } - if e1.ProcessMultipartBody != e2.ProcessMultipartBody { - return false - } - - return true -} - -type luarestywaf struct { - r resolver.Resolver -} - -// NewParser creates a new CORS annotation parser -func NewParser(r resolver.Resolver) parser.IngressAnnotation { - return luarestywaf{r} -} - -// Parse parses the annotations contained in the ingress rule -// used to indicate if the location/s contains a fragment of -// configuration to be included inside the paths of the rules -func (a luarestywaf) Parse(ing *networking.Ingress) (interface{}, error) { - var err error - config := &Config{} - - mode, err := parser.GetStringAnnotation("lua-resty-waf", ing) - if err != nil { - return &Config{}, err - } - - config.Mode = strings.ToUpper(mode) - if _, ok := luaRestyWAFModes[config.Mode]; !ok { - return &Config{}, errors.NewInvalidAnnotationContent("lua-resty-waf", mode) - } - - config.Debug, _ = parser.GetBoolAnnotation("lua-resty-waf-debug", ing) - - ignoredRuleSetsStr, _ := parser.GetStringAnnotation("lua-resty-waf-ignore-rulesets", ing) - config.IgnoredRuleSets = strings.FieldsFunc(ignoredRuleSetsStr, func(c rune) bool { - strC := string(c) - return strC == "," || strC == " " - }) - - // TODO(elvinefendi) maybe validate the ruleset string here - config.ExtraRulesetString, _ = parser.GetStringAnnotation("lua-resty-waf-extra-rules", ing) - - config.ScoreThreshold, _ = parser.GetIntAnnotation("lua-resty-waf-score-threshold", ing) - - config.AllowUnknownContentTypes, _ = parser.GetBoolAnnotation("lua-resty-waf-allow-unknown-content-types", ing) - - config.ProcessMultipartBody, err = parser.GetBoolAnnotation("lua-resty-waf-process-multipart-body", ing) - if err != nil { - config.ProcessMultipartBody = true - } - - return config, nil -} diff --git a/internal/ingress/annotations/luarestywaf/main_test.go b/internal/ingress/annotations/luarestywaf/main_test.go deleted file mode 100644 index cdad6a1c3f..0000000000 --- a/internal/ingress/annotations/luarestywaf/main_test.go +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package luarestywaf - -import ( - "testing" - - api "k8s.io/api/core/v1" - networking "k8s.io/api/networking/v1beta1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/ingress-nginx/internal/ingress/annotations/parser" - "k8s.io/ingress-nginx/internal/ingress/resolver" -) - -func TestParse(t *testing.T) { - luaRestyWAFAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf") - luaRestyWAFDebugAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-debug") - luaRestyWAFIgnoredRuleSetsAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-ignore-rulesets") - luaRestyWAFScoreThresholdAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-score-threshold") - luaRestyWAFAllowUnknownContentTypesAnnotation := parser.GetAnnotationWithPrefix("lua-resty-waf-allow-unknown-content-types") - luaRestyWAFProcessMultipartBody := parser.GetAnnotationWithPrefix("lua-resty-waf-process-multipart-body") - - ap := NewParser(&resolver.Mock{}) - if ap == nil { - t.Fatalf("expected a parser.IngressAnnotation but returned nil") - } - - testCases := []struct { - annotations map[string]string - expected *Config - }{ - {nil, &Config{}}, - {map[string]string{}, &Config{}}, - - {map[string]string{luaRestyWAFAnnotation: "active"}, &Config{Mode: "ACTIVE", Debug: false, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}}, - {map[string]string{luaRestyWAFDebugAnnotation: "true"}, &Config{Debug: false}}, - - {map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "ACTIVE", Debug: true, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}}, - {map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFDebugAnnotation: "false"}, &Config{Mode: "ACTIVE", Debug: false, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}}, - {map[string]string{luaRestyWAFAnnotation: "inactive", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "INACTIVE", Debug: true, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}}, - - {map[string]string{ - luaRestyWAFAnnotation: "active", - luaRestyWAFDebugAnnotation: "true", - luaRestyWAFIgnoredRuleSetsAnnotation: "ruleset1, ruleset2 ruleset3, another.ruleset", - luaRestyWAFScoreThresholdAnnotation: "10", - luaRestyWAFAllowUnknownContentTypesAnnotation: "true"}, - &Config{Mode: "ACTIVE", Debug: true, IgnoredRuleSets: []string{"ruleset1", "ruleset2", "ruleset3", "another.ruleset"}, ScoreThreshold: 10, AllowUnknownContentTypes: true, ProcessMultipartBody: true}}, - - {map[string]string{luaRestyWAFAnnotation: "siMulate", luaRestyWAFDebugAnnotation: "true"}, &Config{Mode: "SIMULATE", Debug: true, IgnoredRuleSets: []string{}, ProcessMultipartBody: true}}, - {map[string]string{luaRestyWAFAnnotation: "siMulateX", luaRestyWAFDebugAnnotation: "true"}, &Config{Debug: false}}, - - {map[string]string{luaRestyWAFAnnotation: "active", luaRestyWAFProcessMultipartBody: "false"}, &Config{Mode: "ACTIVE", ProcessMultipartBody: false, IgnoredRuleSets: []string{}}}, - } - - ing := &networking.Ingress{ - ObjectMeta: meta_v1.ObjectMeta{ - Name: "foo", - Namespace: api.NamespaceDefault, - }, - Spec: networking.IngressSpec{}, - } - - for _, testCase := range testCases { - ing.SetAnnotations(testCase.annotations) - result, _ := ap.Parse(ing) - config := result.(*Config) - if !config.Equal(testCase.expected) { - t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations) - } - } -} diff --git a/internal/ingress/controller/config/config.go b/internal/ingress/controller/config/config.go index fa456f8285..22e319ff12 100644 --- a/internal/ingress/controller/config/config.go +++ b/internal/ingress/controller/config/config.go @@ -610,10 +610,6 @@ type Configuration struct { // +optional GlobalExternalAuth GlobalExternalAuth `json:"global-external-auth"` - // DisableLuaRestyWAF disables lua-resty-waf globally regardless - // of whether there's an ingress that has enabled the WAF using annotation - DisableLuaRestyWAF bool `json:"disable-lua-resty-waf"` - // EnableInfluxDB enables the nginx InfluxDB extension // http://github.com/influxdata/nginx-influxdb-module/ // By default this is disabled diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index a40103d73f..39e2424bd4 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -1177,7 +1177,6 @@ func locationApplyAnnotations(loc *ingress.Location, anns *annotations.Ingress) loc.UsePortInRedirects = anns.UsePortInRedirects loc.Connection = anns.Connection loc.Logs = anns.Logs - loc.LuaRestyWAF = anns.LuaRestyWAF loc.InfluxDB = anns.InfluxDB loc.DefaultBackend = anns.DefaultBackend loc.BackendProtocol = anns.BackendProtocol diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index a45e4cc6a8..2d671250a6 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -93,11 +93,6 @@ func (t *Template) Write(conf config.TemplateConfig) ([]byte, error) { outCmdBuf := t.bp.Get() defer t.bp.Put(outCmdBuf) - // TODO: remove once we found a fix for coredump running luarocks install lrexlib - if runtime.GOARCH == "arm" { - conf.Cfg.DisableLuaRestyWAF = true - } - if klog.V(3) { b, err := json.Marshal(conf) if err != nil { @@ -134,7 +129,6 @@ var ( return true }, "escapeLiteralDollar": escapeLiteralDollar, - "shouldConfigureLuaRestyWAF": shouldConfigureLuaRestyWAF, "buildLuaSharedDictionaries": buildLuaSharedDictionaries, "luaConfigurationRequestBodySize": luaConfigurationRequestBodySize, "buildLocation": buildLocation, @@ -225,15 +219,7 @@ func quote(input interface{}) string { return fmt.Sprintf("%q", inputStr) } -func shouldConfigureLuaRestyWAF(disableLuaRestyWAF bool, mode string) bool { - if !disableLuaRestyWAF && len(mode) > 0 { - return true - } - - return false -} - -func buildLuaSharedDictionaries(c interface{}, s interface{}, disableLuaRestyWAF bool) string { +func buildLuaSharedDictionaries(c interface{}, s interface{}) string { var out []string cfg, ok := c.(config.Configuration) @@ -241,7 +227,8 @@ func buildLuaSharedDictionaries(c interface{}, s interface{}, disableLuaRestyWAF klog.Errorf("expected a 'config.Configuration' type but %T was returned", c) return "" } - servers, ok := s.([]*ingress.Server) + + _, ok = s.([]*ingress.Server) if !ok { klog.Errorf("expected an '[]*ingress.Server' type but %T was returned", s) return "" @@ -251,23 +238,6 @@ func buildLuaSharedDictionaries(c interface{}, s interface{}, disableLuaRestyWAF out = append(out, fmt.Sprintf("lua_shared_dict %s %dM", name, size)) } - // TODO: there must be a better place for this - if _, ok := cfg.LuaSharedDicts["waf_storage"]; !ok && !disableLuaRestyWAF { - luaRestyWAFEnabled := func() bool { - for _, server := range servers { - for _, location := range server.Locations { - if len(location.LuaRestyWAF.Mode) > 0 { - return true - } - } - } - return false - }() - if luaRestyWAFEnabled { - out = append(out, "lua_shared_dict waf_storage 64M") - } - } - sort.Strings(out) return strings.Join(out, ";\n") + ";\n" diff --git a/internal/ingress/controller/template/template_test.go b/internal/ingress/controller/template/template_test.go index e1661901a0..c24e355d63 100644 --- a/internal/ingress/controller/template/template_test.go +++ b/internal/ingress/controller/template/template_test.go @@ -38,7 +38,6 @@ import ( "k8s.io/ingress-nginx/internal/ingress" "k8s.io/ingress-nginx/internal/ingress/annotations/authreq" "k8s.io/ingress-nginx/internal/ingress/annotations/influxdb" - "k8s.io/ingress-nginx/internal/ingress/annotations/luarestywaf" "k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity" "k8s.io/ingress-nginx/internal/ingress/annotations/ratelimit" "k8s.io/ingress-nginx/internal/ingress/annotations/rewrite" @@ -189,7 +188,7 @@ func TestBuildLuaSharedDictionaries(t *testing.T) { "configuration_data": 10, "certificate_data": 20, }, } - actual := buildLuaSharedDictionaries(cfg, invalidType, true) + actual := buildLuaSharedDictionaries(cfg, invalidType) if !reflect.DeepEqual(expected, actual) { t.Errorf("Expected '%v' but returned '%v'", expected, actual) @@ -198,32 +197,23 @@ func TestBuildLuaSharedDictionaries(t *testing.T) { servers := []*ingress.Server{ { Hostname: "foo.bar", - Locations: []*ingress.Location{{Path: "/", LuaRestyWAF: luarestywaf.Config{}}}, + Locations: []*ingress.Location{{Path: "/"}}, }, { Hostname: "another.host", - Locations: []*ingress.Location{{Path: "/", LuaRestyWAF: luarestywaf.Config{}}}, + Locations: []*ingress.Location{{Path: "/"}}, }, } // returns value from config - configuration := buildLuaSharedDictionaries(cfg, servers, false) + configuration := buildLuaSharedDictionaries(cfg, servers) if !strings.Contains(configuration, "lua_shared_dict configuration_data 10M;\n") { t.Errorf("expected to include 'configuration_data' but got %s", configuration) } if !strings.Contains(configuration, "lua_shared_dict certificate_data 20M;\n") { t.Errorf("expected to include 'certificate_data' but got %s", configuration) } - if strings.Contains(configuration, "waf_storage") { - t.Errorf("expected to not include 'waf_storage' but got %s", configuration) - } - - servers[1].Locations[0].LuaRestyWAF = luarestywaf.Config{Mode: "ACTIVE"} - configuration = buildLuaSharedDictionaries(cfg, servers, false) - if !strings.Contains(configuration, "lua_shared_dict waf_storage") { - t.Errorf("expected to configure 'waf_storage', but got %s", configuration) - } // test invalid config - configuration = buildLuaSharedDictionaries(invalidType, servers, false) + configuration = buildLuaSharedDictionaries(invalidType, servers) if configuration != "" { t.Errorf("expected an empty string, but got %s", configuration) } diff --git a/internal/ingress/types.go b/internal/ingress/types.go index 263c137f48..953ae121fc 100644 --- a/internal/ingress/types.go +++ b/internal/ingress/types.go @@ -31,7 +31,6 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/influxdb" "k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist" "k8s.io/ingress-nginx/internal/ingress/annotations/log" - "k8s.io/ingress-nginx/internal/ingress/annotations/luarestywaf" "k8s.io/ingress-nginx/internal/ingress/annotations/mirror" "k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity" "k8s.io/ingress-nginx/internal/ingress/annotations/proxy" @@ -307,8 +306,6 @@ type Location struct { // Logs allows to enable or disable the nginx logs // By default access logs are enabled and rewrite logs are disabled Logs log.Config `json:"logs,omitempty"` - // LuaRestyWAF contains parameters to configure lua-resty-waf - LuaRestyWAF luarestywaf.Config `json:"luaRestyWAF"` // InfluxDB allows to monitor the incoming request by sending them to an influxdb database // +optional InfluxDB influxdb.Config `json:"influxDB,omitempty"` diff --git a/internal/ingress/types_equals.go b/internal/ingress/types_equals.go index 8108ed95ab..34d3475d2e 100644 --- a/internal/ingress/types_equals.go +++ b/internal/ingress/types_equals.go @@ -404,9 +404,6 @@ func (l1 *Location) Equal(l2 *Location) bool { if !(&l1.Logs).Equal(&l2.Logs) { return false } - if !(&l1.LuaRestyWAF).Equal(&l2.LuaRestyWAF) { - return false - } if !(&l1.InfluxDB).Equal(&l2.InfluxDB) { return false diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl index f54d7931a4..9f1574aca8 100755 --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -50,16 +50,11 @@ events { http { lua_package_path "/etc/nginx/lua/?.lua;;"; - {{ buildLuaSharedDictionaries $cfg $servers $all.Cfg.DisableLuaRestyWAF }} + {{ buildLuaSharedDictionaries $cfg $servers }} init_by_lua_block { collectgarbage("collect") - {{ if not $all.Cfg.DisableLuaRestyWAF }} - local lua_resty_waf = require("resty.waf") - lua_resty_waf.init() - {{ end }} - -- init modules local ok, res @@ -980,78 +975,20 @@ stream { plugins.run() } - {{ if shouldConfigureLuaRestyWAF $all.Cfg.DisableLuaRestyWAF $location.LuaRestyWAF.Mode }} # be careful with `access_by_lua_block` and `satisfy any` directives as satisfy any # will always succeed when there's `access_by_lua_block` that does not have any lua code doing `ngx.exit(ngx.DECLINED)` - # that means currently `satisfy any` and lua-resty-waf together will potentiall render any # other authentication method such as basic auth or external auth useless - all requests will be allowed. - access_by_lua_block { - local lua_resty_waf = require("resty.waf") - local waf = lua_resty_waf:new() - - waf:set_option("mode", {{ $location.LuaRestyWAF.Mode | quote }}) - waf:set_option("storage_zone", "waf_storage") - - {{ if $location.LuaRestyWAF.AllowUnknownContentTypes }} - waf:set_option("allow_unknown_content_types", true) - {{ else }} - waf:set_option("allowed_content_types", { "text/html", "text/json", "application/json" }) - {{ end }} - - waf:set_option("event_log_level", ngx.WARN) - - {{ if gt $location.LuaRestyWAF.ScoreThreshold 0 }} - waf:set_option("score_threshold", {{ $location.LuaRestyWAF.ScoreThreshold }}) - {{ end }} - - {{ if not $location.LuaRestyWAF.ProcessMultipartBody }} - waf:set_option("process_multipart_body", false) - {{ end }} - - {{ if $location.LuaRestyWAF.Debug }} - waf:set_option("debug", true) - waf:set_option("event_log_request_arguments", true) - waf:set_option("event_log_request_body", true) - waf:set_option("event_log_request_headers", true) - waf:set_option("req_tid_header", true) - waf:set_option("res_tid_header", true) - {{ end }} - - {{ range $ruleset := $location.LuaRestyWAF.IgnoredRuleSets }} - waf:set_option("ignore_ruleset", {{ $ruleset | quote }}) - {{ end }} - - {{ if gt (len $location.LuaRestyWAF.ExtraRulesetString) 0 }} - waf:set_option("add_ruleset_string", "10000_extra_rules", {{ $location.LuaRestyWAF.ExtraRulesetString }}) - {{ end }} - - waf:exec() - } - {{ end }} + #access_by_lua_block { + #} header_filter_by_lua_block { - {{ if shouldConfigureLuaRestyWAF $all.Cfg.DisableLuaRestyWAF $location.LuaRestyWAF.Mode }} - local lua_resty_waf = require "resty.waf" - local waf = lua_resty_waf:new() - waf:exec() - {{ end }} - plugins.run() } + body_filter_by_lua_block { - {{ if shouldConfigureLuaRestyWAF $all.Cfg.DisableLuaRestyWAF $location.LuaRestyWAF.Mode }} - local lua_resty_waf = require "resty.waf" - local waf = lua_resty_waf:new() - waf:exec() - {{ end }} } log_by_lua_block { - {{ if shouldConfigureLuaRestyWAF $all.Cfg.DisableLuaRestyWAF $location.LuaRestyWAF.Mode }} - local lua_resty_waf = require "resty.waf" - local waf = lua_resty_waf:new() - waf:exec() - {{ end }} balancer.log() {{ if $all.EnableMetrics }} monitor.call() diff --git a/test/e2e/annotations/luarestywaf.go b/test/e2e/annotations/luarestywaf.go deleted file mode 100644 index b9ff6be020..0000000000 --- a/test/e2e/annotations/luarestywaf.go +++ /dev/null @@ -1,224 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package annotations - -import ( - "fmt" - "net/http" - "time" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/parnurzeal/gorequest" - - "k8s.io/ingress-nginx/test/e2e/framework" -) - -var _ = framework.IngressNginxDescribe("Annotations - lua-resty-waf", func() { - f := framework.NewDefaultFramework("luarestywaf") - - BeforeEach(func() { - f.NewEchoDeployment() - }) - - Context("when lua-resty-waf is enabled", func() { - It("should return 403 for a malicious request that matches a default WAF rule and 200 for other requests", func() { - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{"nginx.ingress.kubernetes.io/lua-resty-waf": "active"}) - - url := fmt.Sprintf("%s?msg=XSS", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusForbidden)) - }) - It("should not apply ignored rulesets", func() { - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{ - "nginx.ingress.kubernetes.io/lua-resty-waf": "active", - "nginx.ingress.kubernetes.io/lua-resty-waf-ignore-rulesets": "41000_sqli, 42000_xss"}) - - url := fmt.Sprintf("%s?msg=XSS", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - }) - It("should apply the score threshold", func() { - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{ - "nginx.ingress.kubernetes.io/lua-resty-waf": "active", - "nginx.ingress.kubernetes.io/lua-resty-waf-score-threshold": "20"}) - - url := fmt.Sprintf("%s?msg=XSS", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - }) - It("should not reject request with an unknown content type", func() { - host := "foo" - contenttype := "application/octet-stream" - createIngress(f, host, framework.EchoService, 80, map[string]string{ - "nginx.ingress.kubernetes.io/lua-resty-waf-allow-unknown-content-types": "true", - "nginx.ingress.kubernetes.io/lua-resty-waf": "active"}) - - url := fmt.Sprintf("%s?msg=my-message", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - Set("Content-Type", contenttype). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - }) - It("should not fail a request with multipart content type when multipart body processing disabled", func() { - contenttype := "multipart/form-data; boundary=alamofire.boundary.3fc2e849279e18fc" - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{ - "nginx.ingress.kubernetes.io/lua-resty-waf-process-multipart-body": "false", - "nginx.ingress.kubernetes.io/lua-resty-waf": "active"}) - - url := fmt.Sprintf("%s?msg=my-message", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - Set("Content-Type", contenttype). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - }) - It("should fail a request with multipart content type when multipart body processing enabled by default", func() { - contenttype := "multipart/form-data; boundary=alamofire.boundary.3fc2e849279e18fc" - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{ - "nginx.ingress.kubernetes.io/lua-resty-waf": "active"}) - - url := fmt.Sprintf("%s?msg=my-message", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - Set("Content-Type", contenttype). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusBadRequest)) - }) - It("should apply configured extra rules", func() { - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{ - "nginx.ingress.kubernetes.io/lua-resty-waf": "active", - "nginx.ingress.kubernetes.io/lua-resty-waf-extra-rules": `[=[ - { "access": [ - { "actions": { "disrupt" : "DENY" }, - "id": 10001, - "msg": "my custom rule", - "operator": "STR_CONTAINS", - "pattern": "foo", - "vars": [ { "parse": [ "values", 1 ], "type": "REQUEST_ARGS" } ] } - ], - "body_filter": [], - "header_filter":[] - } - ]=]`, - }) - - url := fmt.Sprintf("%s?msg=my-message", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - - url = fmt.Sprintf("%s?msg=my-foo-message", f.GetURL(framework.HTTP)) - resp, _, errs = gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusForbidden)) - }) - }) - Context("when lua-resty-waf is not enabled", func() { - It("should return 200 even for a malicious request", func() { - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{}) - - url := fmt.Sprintf("%s?msg=XSS", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - }) - It("should run in simulate mode", func() { - host := "foo" - createIngress(f, host, framework.EchoService, 80, map[string]string{"nginx.ingress.kubernetes.io/lua-resty-waf": "simulate"}) - - url := fmt.Sprintf("%s?msg=XSS", f.GetURL(framework.HTTP)) - resp, _, errs := gorequest.New(). - Get(url). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - - time.Sleep(5 * time.Second) - log, err := f.NginxLogs() - Expect(err).ToNot(HaveOccurred()) - Expect(log).To(ContainSubstring("Request score greater than score threshold")) - }) - }) -}) - -func createIngress(f *framework.Framework, host, service string, port int, annotations map[string]string) { - ing := framework.NewSingleIngress(host, "/", host, f.Namespace, service, port, &annotations) - f.EnsureIngress(ing) - - f.WaitForNginxServer(host, - func(server string) bool { - return Expect(server).Should(ContainSubstring(fmt.Sprintf("server_name %v", host))) - }) - - time.Sleep(1 * time.Second) - - resp, body, errs := gorequest.New(). - Get(f.GetURL(framework.HTTP)). - Set("Host", host). - End() - - Expect(len(errs)).Should(Equal(0)) - Expect(resp.StatusCode).Should(Equal(http.StatusOK)) - Expect(body).Should(ContainSubstring(fmt.Sprintf("host=%v", host))) -}