ingress-nginx-helm/test/e2e/annotations/modsecurity/modsecurity.go

383 lines
12 KiB
Go
Raw Normal View History

/*
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 (
"net/http"
"strings"
"github.com/onsi/ginkgo"
"k8s.io/ingress-nginx/test/e2e/framework"
)
var _ = framework.DescribeAnnotation("modsecurity owasp", func() {
f := framework.NewDefaultFramework("modsecuritylocation")
ginkgo.BeforeEach(func() {
f.NewEchoDeployment()
})
ginkgo.It("should enable modsecurity", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 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;")
})
})
ginkgo.It("should enable modsecurity with transaction ID and OWASP rules", func() {
host := "modsecurity.foo.com"
nameSpace := f.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",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 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\";")
})
})
ginkgo.It("should disable modsecurity", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "false",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return !strings.Contains(server, "modsecurity on;")
})
})
ginkgo.It("should enable modsecurity with snippet", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
"nginx.ingress.kubernetes.io/modsecurity-snippet": "SecRuleEngine On",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "modsecurity on;") &&
strings.Contains(server, "SecRuleEngine On")
})
})
ginkgo.It("should enable modsecurity without using 'modsecurity on;'", func() {
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true"},
)
host := "modsecurity.foo.com"
nameSpace := f.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 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;")
})
})
ginkgo.It("should disable modsecurity using 'modsecurity off;'", func() {
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true"},
)
host := "modsecurity.foo.com"
nameSpace := f.Namespace
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "false",
}
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "modsecurity off;")
})
})
ginkgo.It("should enable modsecurity with snippet and block requests", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
}
f.UpdateNginxConfigMapData("annotation-value-word-blocklist", "load_module, lua_package, _by_lua, location, root, {, }")
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "modsecurity on;") &&
strings.Contains(server, "SecRuleEngine On")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("User-Agent", "block-ua").
Expect().
Status(http.StatusForbidden)
})
ginkgo.It("should enable modsecurity globally and with modsecurity-snippet block requests", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
}
f.UpdateNginxConfigMapData("annotation-value-word-blocklist", "load_module, lua_package, _by_lua, location, root, {, }")
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.UpdateNginxConfigMapData("enable-modsecurity", "true")
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "SecRuleEngine On")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("User-Agent", "block-ua").
Expect().
Status(http.StatusForbidden)
})
ginkgo.It("should enable modsecurity when enable-owasp-modsecurity-crs is set to true", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
}
f.UpdateNginxConfigMapData("annotation-value-word-blocklist", "load_module, lua_package, _by_lua, location, root, {, }")
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true",
"enable-owasp-modsecurity-crs": "true",
})
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "SecRuleEngine On")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("User-Agent", "block-ua").
Expect().
Status(http.StatusForbidden)
})
ginkgo.It("should enable modsecurity through the config map", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
snippet := `SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
}
f.UpdateNginxConfigMapData("annotation-value-word-blocklist", "load_module, lua_package, _by_lua, location, root, {, }")
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
expectedComment := "SecRuleEngine On"
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true",
"enable-owasp-modsecurity-crs": "true",
"modsecurity-snippet": expectedComment,
})
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "SecRequestBodyAccess On")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("User-Agent", "block-ua").
Expect().
Status(http.StatusForbidden)
})
ginkgo.It("should enable modsecurity through the config map but ignore snippet as disabled by admin", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
snippet := `SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLog /dev/stdout
SecAuditLogType Serial
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
}
f.UpdateNginxConfigMapData("annotation-value-word-blocklist", "load_module, lua_package, _by_lua, location, root, {, }")
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
expectedComment := "SecRuleEngine On"
f.SetNginxConfigMapData(map[string]string{
"enable-modsecurity": "true",
"enable-owasp-modsecurity-crs": "true",
"allow-snippet-annotations": "false",
"modsecurity-snippet": expectedComment,
})
f.WaitForNginxServer(host,
func(server string) bool {
return !strings.Contains(server, "block-ua")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("User-Agent", "block-ua").
Expect().
Status(http.StatusOK)
})
Disable default modsecurity_rules_file if modsecurity-snippet is specified (#8021) * Disabled default modsecurity_rules_file if modsecurity-snippet is specifed The default modsecurity_rules_file overwrites the ModSecurity-snippet if it is specified with custom config settings like "SecRuleEngine On". This will not let Modsecurity be in blocking mode even if "SecRuleEngine On" is specified in the ModSecurity-snippet configuration * Remove unnecessary comments Only have the default Modsecurity conf settings in case Modsecurity configuration snippet is not present and remove unnecessary comments * Fixed modsecurity default file only if Modsecurity snippet present Fixed if condition Modsecurity snippet present have modsecurity default config file * Added e2e test to disabling modsecurity conf Added e2e in case modsecurity-snippet enabled to disable settings in default modsecurity.conf * Validate writing to a different location Validate also modsecurity to write to a different location instead of the default directory * Fixed the formatting * Fixed if empty ModsecuritySnippet * Fixed ModsecuritySnippet condition * Fixed the condition also in ingress controller template * Removed the default config condition in ingress controller template * Fixed the default config condition in ingress controller template * Fixed pull-ingress-nginx-test * Revert "Fixed the default config condition in ingress controller template" This reverts commit 9d38eca40fe615a4c756500ca57b05634240edde. * Revert template_test * Adjusted the formating %v
2021-12-23 11:34:38 +00:00
ginkgo.It("should disable default modsecurity conf setting when modsecurity-snippet is specified", func() {
host := "modsecurity.foo.com"
nameSpace := f.Namespace
snippet := `SecRuleEngine On
SecRequestBodyAccess On
SecAuditEngine RelevantOnly
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Concurrent
SecAuditLog /var/tmp/modsec_audit.log
SecAuditLogStorageDir /var/tmp/
SecRule REQUEST_HEADERS:User-Agent \"block-ua\" \"log,deny,id:107,status:403,msg:\'UA blocked\'\"`
annotations := map[string]string{
"nginx.ingress.kubernetes.io/enable-modsecurity": "true",
"nginx.ingress.kubernetes.io/modsecurity-snippet": snippet,
}
f.UpdateNginxConfigMapData("annotation-value-word-blocklist", "load_module, lua_package, _by_lua, location, root, {, }")
// Sleep a while just to guarantee that the configmap is applied
framework.Sleep()
ing := framework.NewSingleIngress(host, "/", host, nameSpace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)
f.WaitForNginxServer(host,
func(server string) bool {
return !strings.Contains(server, "modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;") &&
strings.Contains(server, "SecAuditLog /var/tmp/modsec_audit.log")
})
f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
WithHeader("User-Agent", "block-ua").
Expect().
Status(http.StatusForbidden)
})
})