Merge pull request #3309 from diazjf/modsecurity-location
Customize ModSecurity to be used in Locations
This commit is contained in:
commit
d97999c07d
9 changed files with 307 additions and 7 deletions
|
@ -95,6 +95,10 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|
||||||
|[nginx.ingress.kubernetes.io/influxdb-host](#influxdb)|string|
|
|[nginx.ingress.kubernetes.io/influxdb-host](#influxdb)|string|
|
||||||
|[nginx.ingress.kubernetes.io/influxdb-server-name](#influxdb)|string|
|
|[nginx.ingress.kubernetes.io/influxdb-server-name](#influxdb)|string|
|
||||||
|[nginx.ingress.kubernetes.io/use-regex](#use-regex)|bool|
|
|[nginx.ingress.kubernetes.io/use-regex](#use-regex)|bool|
|
||||||
|
|[nginx.ingress.kubernetes.io/enable-modsecurity](#modsecurity)|bool|
|
||||||
|
|[nginx.ingress.kubernetes.io/enable-owasp-core-rules](#modsecurity)|bool|
|
||||||
|
|[nginx.ingress.kubernetes.io/modsecurity-transaction-id](#modsecurity)|string|
|
||||||
|
|
||||||
|
|
||||||
### Canary
|
### Canary
|
||||||
|
|
||||||
|
@ -634,6 +638,29 @@ For details on how to write WAF rules, please refer to [https://github.com/p0pr0
|
||||||
|
|
||||||
[configmap]: ./configmap.md
|
[configmap]: ./configmap.md
|
||||||
|
|
||||||
|
### ModSecurity
|
||||||
|
|
||||||
|
[ModSecurity](http://modsecurity.org/) is an OpenSource Web Application firewall. It can be enabled for a particular set
|
||||||
|
of ingress locations. The ModSecurity module must first be enabled by by enabling ModSecurity in the
|
||||||
|
[ConfigMap](configmap.md#enable-modsecurity). Note this will enable ModSecurity for all paths, and each path
|
||||||
|
must be disabled manually.
|
||||||
|
|
||||||
|
It can be enabled using the following annotation:
|
||||||
|
```yaml
|
||||||
|
nginx.ingress.kubernetes.io/enable-modsecurity: "true"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can enable the [OWASP Core Rule Set](https://www.modsecurity.org/CRS/Documentation/) by
|
||||||
|
setting the following annotation:
|
||||||
|
```yaml
|
||||||
|
nginx.ingress.kubernetes.io/enable-owasp-core-rules: "true"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can pass transactionIDs from nginx by setting up the following:
|
||||||
|
```yaml
|
||||||
|
nginx.ingress.kubernetes.io/modsecurity-transaction-id: "$request_id"
|
||||||
|
```
|
||||||
|
|
||||||
### InfluxDB
|
### InfluxDB
|
||||||
|
|
||||||
Using `influxdb-*` annotations we can monitor requests passing through a Location by sending them to an InfluxDB backend exposing the UDP socket
|
Using `influxdb-*` annotations we can monitor requests passing through a Location by sending them to an InfluxDB backend exposing the UDP socket
|
||||||
|
@ -689,5 +716,3 @@ When this annotation is set to `true`, the case insensitive regular expression [
|
||||||
Additionally, if the [`rewrite-target` annotation](#rewrite) is used on any Ingress for a given host, then the case insensitive regular expression [location modifier](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) will be enforced on ALL paths for a given host regardless of what Ingress they are defined on.
|
Additionally, if the [`rewrite-target` annotation](#rewrite) is used on any Ingress for a given host, then the case insensitive regular expression [location modifier](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) will be enforced on ALL paths for a given host regardless of what Ingress they are defined on.
|
||||||
|
|
||||||
Please read about [ingress path matching](../ingress-path-matching.md) before using this modifier.
|
Please read about [ingress path matching](../ingress-path-matching.md) before using this modifier.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/imdario/mergo"
|
"github.com/imdario/mergo"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/canary"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/canary"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/sslcipher"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/sslcipher"
|
||||||
|
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
|
@ -98,6 +99,7 @@ type Ingress struct {
|
||||||
Logs log.Config
|
Logs log.Config
|
||||||
LuaRestyWAF luarestywaf.Config
|
LuaRestyWAF luarestywaf.Config
|
||||||
InfluxDB influxdb.Config
|
InfluxDB influxdb.Config
|
||||||
|
ModSecurity modsecurity.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor defines the annotation parsers to be used in the extraction of annotations
|
// Extractor defines the annotation parsers to be used in the extraction of annotations
|
||||||
|
@ -140,6 +142,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
|
||||||
"LuaRestyWAF": luarestywaf.NewParser(cfg),
|
"LuaRestyWAF": luarestywaf.NewParser(cfg),
|
||||||
"InfluxDB": influxdb.NewParser(cfg),
|
"InfluxDB": influxdb.NewParser(cfg),
|
||||||
"BackendProtocol": backendprotocol.NewParser(cfg),
|
"BackendProtocol": backendprotocol.NewParser(cfg),
|
||||||
|
"ModSecurity": modsecurity.NewParser(cfg),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
88
internal/ingress/annotations/modsecurity/main.go
Normal file
88
internal/ingress/annotations/modsecurity/main.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 modsecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
|
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config contains the AuthSSLCert used for mutual authentication
|
||||||
|
// and the configured ValidationDepth
|
||||||
|
type Config struct {
|
||||||
|
Enable bool `json:"enable-modsecurity"`
|
||||||
|
OWASPRules bool `json:"enable-owasp-core-rules"`
|
||||||
|
TransactionID string `json:"modsecurity-transaction-id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal tests for equality between two Config types
|
||||||
|
func (modsec1 *Config) Equal(modsec2 *Config) bool {
|
||||||
|
if modsec1 == modsec2 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if modsec1 == nil || modsec2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if modsec1.Enable != modsec2.Enable {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if modsec1.OWASPRules != modsec2.OWASPRules {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if modsec1.TransactionID != modsec2.TransactionID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewParser creates a new ModSecurity annotation parser
|
||||||
|
func NewParser(resolver resolver.Resolver) parser.IngressAnnotation {
|
||||||
|
return modSecurity{resolver}
|
||||||
|
}
|
||||||
|
|
||||||
|
type modSecurity struct {
|
||||||
|
r resolver.Resolver
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses the annotations contained in the ingress
|
||||||
|
// rule used to enable ModSecurity in a particular location
|
||||||
|
func (a modSecurity) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
|
|
||||||
|
enableModSecurity, err := parser.GetBoolAnnotation("enable-modsecurity", ing)
|
||||||
|
if err != nil {
|
||||||
|
enableModSecurity = false
|
||||||
|
}
|
||||||
|
|
||||||
|
owaspRules, err := parser.GetBoolAnnotation("enable-owasp-core-rules", ing)
|
||||||
|
if err != nil {
|
||||||
|
owaspRules = false
|
||||||
|
}
|
||||||
|
|
||||||
|
transactionID, err := parser.GetStringAnnotation("modsecurity-transaction-id", ing)
|
||||||
|
if err != nil {
|
||||||
|
transactionID = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return Config{
|
||||||
|
Enable: enableModSecurity,
|
||||||
|
OWASPRules: owaspRules,
|
||||||
|
TransactionID: transactionID,
|
||||||
|
}, nil
|
||||||
|
}
|
73
internal/ingress/annotations/modsecurity/main_test.go
Normal file
73
internal/ingress/annotations/modsecurity/main_test.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 modsecurity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
api "k8s.io/api/core/v1"
|
||||||
|
extensions "k8s.io/api/extensions/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) {
|
||||||
|
enable := parser.GetAnnotationWithPrefix("enable-modsecurity")
|
||||||
|
owasp := parser.GetAnnotationWithPrefix("enable-owasp-core-rules")
|
||||||
|
transID := parser.GetAnnotationWithPrefix("modsecurity-transaction-id")
|
||||||
|
|
||||||
|
ap := NewParser(&resolver.Mock{})
|
||||||
|
if ap == nil {
|
||||||
|
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
annotations map[string]string
|
||||||
|
expected Config
|
||||||
|
}{
|
||||||
|
{map[string]string{enable: "true"}, Config{true, false, ""}},
|
||||||
|
{map[string]string{enable: "false"}, Config{false, false, ""}},
|
||||||
|
{map[string]string{enable: ""}, Config{false, false, ""}},
|
||||||
|
|
||||||
|
{map[string]string{owasp: "true"}, Config{false, true, ""}},
|
||||||
|
{map[string]string{owasp: "false"}, Config{false, false, ""}},
|
||||||
|
{map[string]string{owasp: ""}, Config{false, false, ""}},
|
||||||
|
|
||||||
|
{map[string]string{transID: "ok"}, Config{false, false, "ok"}},
|
||||||
|
{map[string]string{transID: ""}, Config{false, false, ""}},
|
||||||
|
|
||||||
|
{map[string]string{}, Config{false, false, ""}},
|
||||||
|
{nil, Config{false, false, ""}},
|
||||||
|
}
|
||||||
|
|
||||||
|
ing := &extensions.Ingress{
|
||||||
|
ObjectMeta: meta_v1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: api.NamespaceDefault,
|
||||||
|
},
|
||||||
|
Spec: extensions.IngressSpec{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
ing.SetAnnotations(testCase.annotations)
|
||||||
|
result, _ := ap.Parse(ing)
|
||||||
|
if result != testCase.expected {
|
||||||
|
t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -355,6 +355,7 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
loc.DefaultBackend = anns.DefaultBackend
|
loc.DefaultBackend = anns.DefaultBackend
|
||||||
loc.BackendProtocol = anns.BackendProtocol
|
loc.BackendProtocol = anns.BackendProtocol
|
||||||
loc.CustomHTTPErrors = anns.CustomHTTPErrors
|
loc.CustomHTTPErrors = anns.CustomHTTPErrors
|
||||||
|
loc.ModSecurity = anns.ModSecurity
|
||||||
|
|
||||||
if loc.Redirect.FromToWWW {
|
if loc.Redirect.FromToWWW {
|
||||||
server.RedirectFromToWWW = true
|
server.RedirectFromToWWW = true
|
||||||
|
@ -396,6 +397,7 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([]
|
||||||
DefaultBackend: anns.DefaultBackend,
|
DefaultBackend: anns.DefaultBackend,
|
||||||
BackendProtocol: anns.BackendProtocol,
|
BackendProtocol: anns.BackendProtocol,
|
||||||
CustomHTTPErrors: anns.CustomHTTPErrors,
|
CustomHTTPErrors: anns.CustomHTTPErrors,
|
||||||
|
ModSecurity: anns.ModSecurity,
|
||||||
}
|
}
|
||||||
|
|
||||||
if loc.Redirect.FromToWWW {
|
if loc.Redirect.FromToWWW {
|
||||||
|
@ -848,6 +850,7 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
|
||||||
defLoc.LuaRestyWAF = anns.LuaRestyWAF
|
defLoc.LuaRestyWAF = anns.LuaRestyWAF
|
||||||
defLoc.InfluxDB = anns.InfluxDB
|
defLoc.InfluxDB = anns.InfluxDB
|
||||||
defLoc.BackendProtocol = anns.BackendProtocol
|
defLoc.BackendProtocol = anns.BackendProtocol
|
||||||
|
defLoc.ModSecurity = anns.ModSecurity
|
||||||
} else {
|
} else {
|
||||||
glog.V(3).Infof("Ingress %q defines both a backend and rules. Using its backend as default upstream for all its rules.",
|
glog.V(3).Infof("Ingress %q defines both a backend and rules. Using its backend as default upstream for all its rules.",
|
||||||
ingKey)
|
ingKey)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
extensions "k8s.io/api/extensions/v1beta1"
|
extensions "k8s.io/api/extensions/v1beta1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
"k8s.io/ingress-nginx/internal/ingress/annotations/modsecurity"
|
||||||
|
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/auth"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/auth"
|
||||||
"k8s.io/ingress-nginx/internal/ingress/annotations/authreq"
|
"k8s.io/ingress-nginx/internal/ingress/annotations/authreq"
|
||||||
|
@ -280,6 +281,9 @@ type Location struct {
|
||||||
// CustomHTTPErrors specifies the error codes that should be intercepted.
|
// CustomHTTPErrors specifies the error codes that should be intercepted.
|
||||||
// +optional
|
// +optional
|
||||||
CustomHTTPErrors []int `json:"custom-http-errors"`
|
CustomHTTPErrors []int `json:"custom-http-errors"`
|
||||||
|
// ModSecurity allows to enable and configure modsecurity
|
||||||
|
// +optional
|
||||||
|
ModSecurity modsecurity.Config `json:"modsecurity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SSLPassthroughBackend describes a SSL upstream server configured
|
// SSLPassthroughBackend describes a SSL upstream server configured
|
||||||
|
|
|
@ -380,6 +380,10 @@ func (l1 *Location) Equal(l2 *Location) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !(&l1.ModSecurity).Equal(&l2.ModSecurity) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,7 @@ pid /tmp/nginx.pid;
|
||||||
load_module /etc/nginx/modules/ngx_http_geoip2_module.so;
|
load_module /etc/nginx/modules/ngx_http_geoip2_module.so;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if $cfg.EnableModsecurity }}
|
|
||||||
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
|
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so;
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ if $cfg.EnableOpentracing }}
|
{{ if $cfg.EnableOpentracing }}
|
||||||
load_module /etc/nginx/modules/ngx_http_opentracing_module.so;
|
load_module /etc/nginx/modules/ngx_http_opentracing_module.so;
|
||||||
|
@ -1020,13 +1018,17 @@ stream {
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if $all.Cfg.EnableModsecurity }}
|
{{ if (or $location.ModSecurity.Enable $all.Cfg.EnableModsecurity) }}
|
||||||
modsecurity on;
|
modsecurity on;
|
||||||
|
|
||||||
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
|
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
|
||||||
{{ if $all.Cfg.EnableOWASPCoreRules }}
|
{{ if (or $location.ModSecurity.OWASPRules $all.Cfg.EnableOWASPCoreRules) }}
|
||||||
modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;
|
modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if (not (empty $location.ModSecurity.TransactionID)) }}
|
||||||
|
modsecurity_transaction_id "{{ $location.ModSecurity.TransactionID }}";
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if isLocationAllowed $location }}
|
{{ if isLocationAllowed $location }}
|
||||||
|
|
98
test/e2e/annotations/modsecurity.go
Normal file
98
test/e2e/annotations/modsecurity.go
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 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 (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = framework.IngressNginxDescribe("Annotations - ModSecurityLocation", func() {
|
||||||
|
f := framework.NewDefaultFramework("modsecuritylocation")
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
f.NewEchoDeployment()
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
f.UpdateNginxConfigMapData("enable-modsecurity", "false")
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should enable modsecurity", func() {
|
||||||
|
host := "modsecurity.foo.com"
|
||||||
|
nameSpace := f.IngressController.Namespace
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
|
||||||
|
}
|
||||||
|
|
||||||
|
f.UpdateNginxConfigMapData("enable-modsecurity", "true")
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/", host, nameSpace, "http-svc", 80, &annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "modsecurity on;") &&
|
||||||
|
strings.Contains(server, "modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should enable modsecurity with transaction ID and OWASP rules", func() {
|
||||||
|
host := "modsecurity.foo.com"
|
||||||
|
nameSpace := f.IngressController.Namespace
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
|
||||||
|
"nginx.ingress.kubernetes.io/enable-owasp-core-rules": "true",
|
||||||
|
"nginx.ingress.kubernetes.io/modsecurity-transaction-id": "modsecurity-$request_id",
|
||||||
|
}
|
||||||
|
|
||||||
|
f.UpdateNginxConfigMapData("enable-modsecurity", "true")
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/", host, nameSpace, "http-svc", 80, &annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "modsecurity on;") &&
|
||||||
|
strings.Contains(server, "modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf;") &&
|
||||||
|
strings.Contains(server, "modsecurity_transaction_id \"modsecurity-$request_id\";")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should disable modsecurity", func() {
|
||||||
|
host := "modsecurity.foo.com"
|
||||||
|
nameSpace := f.IngressController.Namespace
|
||||||
|
|
||||||
|
annotations := map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/enable-modsecurity": "false",
|
||||||
|
}
|
||||||
|
|
||||||
|
f.UpdateNginxConfigMapData("enable-modsecurity", "false")
|
||||||
|
|
||||||
|
ing := framework.NewSingleIngress(host, "/", host, nameSpace, "http-svc", 80, &annotations)
|
||||||
|
f.EnsureIngress(ing)
|
||||||
|
|
||||||
|
f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return !strings.Contains(server, "modsecurity on;")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue