Add annotation to enable rewrite logs in a location
This commit is contained in:
parent
1086ec6c7e
commit
c995031ffd
7 changed files with 157 additions and 18 deletions
|
@ -46,6 +46,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|
||||||
|[nginx.ingress.kubernetes.io/proxy-request-buffering](#custom-timeouts)|string|
|
|[nginx.ingress.kubernetes.io/proxy-request-buffering](#custom-timeouts)|string|
|
||||||
|[nginx.ingress.kubernetes.io/proxy-redirect-from](#proxy-redirect)|string|
|
|[nginx.ingress.kubernetes.io/proxy-redirect-from](#proxy-redirect)|string|
|
||||||
|[nginx.ingress.kubernetes.io/proxy-redirect-to](#proxy-redirect)|string|
|
|[nginx.ingress.kubernetes.io/proxy-redirect-to](#proxy-redirect)|string|
|
||||||
|
|[nginx.ingress.kubernetes.io/rewrite-log](#enable-rewrite-log)|URI|
|
||||||
|[nginx.ingress.kubernetes.io/rewrite-target](#rewrite)|URI|
|
|[nginx.ingress.kubernetes.io/rewrite-target](#rewrite)|URI|
|
||||||
|[nginx.ingress.kubernetes.io/secure-backends](#secure-backends)|"true" or "false"|
|
|[nginx.ingress.kubernetes.io/secure-backends](#secure-backends)|"true" or "false"|
|
||||||
|[nginx.ingress.kubernetes.io/secure-verify-ca-secret](#secure-backends)|string|
|
|[nginx.ingress.kubernetes.io/secure-verify-ca-secret](#secure-backends)|string|
|
||||||
|
@ -467,6 +468,14 @@ In some scenarios could be required to disable NGINX access logs. To enable this
|
||||||
nginx.ingress.kubernetes.io/enable-access-log: "false"
|
nginx.ingress.kubernetes.io/enable-access-log: "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Enable Rewrite Log
|
||||||
|
|
||||||
|
In some scenarios it could be required to enable NGINX rewrite logs. Note that rewrite logs are sent to the error_log file at the notice level. To enable this feature use the annotation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
|
||||||
|
```
|
||||||
|
|
||||||
### Lua Resty WAF
|
### Lua Resty WAF
|
||||||
|
|
||||||
Using `lua-resty-waf-*` annotations we can enable and control [lua-resty-waf](https://github.com/p0pr0ck5/lua-resty-waf) per location.
|
Using `lua-resty-waf-*` annotations we can enable and control [lua-resty-waf](https://github.com/p0pr0ck5/lua-resty-waf) per location.
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -23,36 +23,46 @@ import (
|
||||||
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
"k8s.io/ingress-nginx/internal/ingress/resolver"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cors struct {
|
type log struct {
|
||||||
r resolver.Resolver
|
r resolver.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config contains the configuration to be used in the Ingress
|
// Config contains the configuration to be used in the Ingress
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Access bool `json:"accessLog"`
|
Access bool `json:"accessLog"`
|
||||||
|
Rewrite bool `json:"rewriteLog"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal tests for equality between two Config types
|
// Equal tests for equality between two Config types
|
||||||
func (bd1 *Config) Equal(bd2 *Config) bool {
|
func (bd1 *Config) Equal(bd2 *Config) bool {
|
||||||
if bd1.Access == bd2.Access {
|
if bd1.Access != bd2.Access {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
if bd1.Rewrite != bd2.Rewrite {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewParser creates a new access log annotation parser
|
// NewParser creates a new log annotations parser
|
||||||
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
|
||||||
return cors{r}
|
return log{r}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses the annotations contained in the ingress
|
// Parse parses the annotations contained in the ingress
|
||||||
// rule used to indicate if the location/s should enable logs
|
// rule used to indicate if the location/s should enable logs
|
||||||
func (c cors) Parse(ing *extensions.Ingress) (interface{}, error) {
|
func (l log) Parse(ing *extensions.Ingress) (interface{}, error) {
|
||||||
accessEnabled, err := parser.GetBoolAnnotation("enable-access-log", ing)
|
accessEnabled, err := parser.GetBoolAnnotation("enable-access-log", ing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
accessEnabled = true
|
accessEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Config{accessEnabled}, nil
|
rewriteEnabled, err := parser.GetBoolAnnotation("enable-rewrite-log", ing)
|
||||||
|
if err != nil {
|
||||||
|
rewriteEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Config{Access: accessEnabled, Rewrite: rewriteEnabled}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ func buildIngress() *extensions.Ingress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIngressLogConfig(t *testing.T) {
|
func TestIngressAccessLogConfig(t *testing.T) {
|
||||||
ing := buildIngress()
|
ing := buildIngress()
|
||||||
|
|
||||||
data := map[string]string{}
|
data := map[string]string{}
|
||||||
|
@ -79,3 +79,21 @@ func TestIngressLogConfig(t *testing.T) {
|
||||||
t.Errorf("expected access be disabled but is enabled")
|
t.Errorf("expected access be disabled but is enabled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIngressRewriteLogConfig(t *testing.T) {
|
||||||
|
ing := buildIngress()
|
||||||
|
|
||||||
|
data := map[string]string{}
|
||||||
|
data[parser.GetAnnotationWithPrefix("enable-rewrite-log")] = "true"
|
||||||
|
ing.SetAnnotations(data)
|
||||||
|
|
||||||
|
log, _ := NewParser(&resolver.Mock{}).Parse(ing)
|
||||||
|
nginxLogs, ok := log.(*Config)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("expected a Config type")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !nginxLogs.Rewrite {
|
||||||
|
t.Errorf("expected rewrite log to be enabled but it is disabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -264,7 +264,7 @@ type Location struct {
|
||||||
// +optional
|
// +optional
|
||||||
XForwardedPrefix bool `json:"xForwardedPrefix,omitempty"`
|
XForwardedPrefix bool `json:"xForwardedPrefix,omitempty"`
|
||||||
// Logs allows to enable or disable the nginx logs
|
// Logs allows to enable or disable the nginx logs
|
||||||
// By default this is enabled
|
// By default access logs are enabled and rewrite logs are disabled
|
||||||
Logs log.Config `json:"logs,omitempty"`
|
Logs log.Config `json:"logs,omitempty"`
|
||||||
// GRPC indicates if the kubernetes service exposes a gRPC interface
|
// GRPC indicates if the kubernetes service exposes a gRPC interface
|
||||||
// By default this is false
|
// By default this is false
|
||||||
|
|
|
@ -275,9 +275,9 @@ http {
|
||||||
|
|
||||||
# Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server.
|
# Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server.
|
||||||
# If no such header is provided, it can provide a random value.
|
# If no such header is provided, it can provide a random value.
|
||||||
map $http_x_request_id $req_id {
|
map $http_x_request_id $req_id {
|
||||||
default $http_x_request_id;
|
default $http_x_request_id;
|
||||||
"" $request_id;
|
"" $request_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
{{ if $cfg.ComputeFullForwardedFor }}
|
{{ if $cfg.ComputeFullForwardedFor }}
|
||||||
|
@ -297,8 +297,6 @@ http {
|
||||||
server_name_in_redirect off;
|
server_name_in_redirect off;
|
||||||
port_in_redirect off;
|
port_in_redirect off;
|
||||||
|
|
||||||
rewrite_log on;
|
|
||||||
|
|
||||||
ssl_protocols {{ $cfg.SSLProtocols }};
|
ssl_protocols {{ $cfg.SSLProtocols }};
|
||||||
|
|
||||||
# turn on session caching to drastically improve performance
|
# turn on session caching to drastically improve performance
|
||||||
|
@ -550,7 +548,7 @@ http {
|
||||||
allow ::1;
|
allow ::1;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
# this should be equals to configuration_data dict
|
# this should be equals to configuration_data dict
|
||||||
client_max_body_size "10m";
|
client_max_body_size "10m";
|
||||||
proxy_buffering off;
|
proxy_buffering off;
|
||||||
|
@ -895,6 +893,10 @@ stream {
|
||||||
access_log off;
|
access_log off;
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{ if $location.Logs.Rewrite }}
|
||||||
|
rewrite_log on;
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }};
|
port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }};
|
||||||
|
|
||||||
{{ if $all.Cfg.EnableVtsStatus }}{{ if $location.VtsFilterKey }} vhost_traffic_status_filter_by_set_key {{ $location.VtsFilterKey }};{{ end }}{{ end }}
|
{{ if $all.Cfg.EnableVtsStatus }}{{ if $location.VtsFilterKey }} vhost_traffic_status_filter_by_set_key {{ $location.VtsFilterKey }};{{ end }}{{ end }}
|
||||||
|
|
100
test/e2e/annotations/rewrite_log.go
Normal file
100
test/e2e/annotations/rewrite_log.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/parnurzeal/gorequest"
|
||||||
|
"k8s.io/api/extensions/v1beta1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = framework.IngressNginxDescribe("Annotations - Rewrite Log", func() {
|
||||||
|
f := framework.NewDefaultFramework("rewrite-log")
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
err := f.NewEchoDeploymentWithReplicas(2)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
})
|
||||||
|
|
||||||
|
AfterEach(func() {
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should write rewrite logs", func() {
|
||||||
|
host := "rewrite.bar.com"
|
||||||
|
|
||||||
|
ing, err := f.EnsureIngress(&v1beta1.Ingress{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: host,
|
||||||
|
Namespace: f.IngressController.Namespace,
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"nginx.ingress.kubernetes.io/rewrite-target": "/",
|
||||||
|
"nginx.ingress.kubernetes.io/enable-rewrite-log": "true",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: v1beta1.IngressSpec{
|
||||||
|
Rules: []v1beta1.IngressRule{
|
||||||
|
{
|
||||||
|
Host: host,
|
||||||
|
IngressRuleValue: v1beta1.IngressRuleValue{
|
||||||
|
HTTP: &v1beta1.HTTPIngressRuleValue{
|
||||||
|
Paths: []v1beta1.HTTPIngressPath{
|
||||||
|
{
|
||||||
|
Path: "/something",
|
||||||
|
Backend: v1beta1.IngressBackend{
|
||||||
|
ServiceName: "http-svc",
|
||||||
|
ServicePort: intstr.FromInt(80),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(ing).NotTo(BeNil())
|
||||||
|
|
||||||
|
err = f.WaitForNginxServer(host,
|
||||||
|
func(server string) bool {
|
||||||
|
return strings.Contains(server, "rewrite_log on;")
|
||||||
|
})
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
|
resp, _, errs := gorequest.New().
|
||||||
|
Get(f.IngressController.HTTPURL+"/something").
|
||||||
|
Set("Host", host).
|
||||||
|
End()
|
||||||
|
|
||||||
|
Expect(len(errs)).Should(Equal(0))
|
||||||
|
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
|
||||||
|
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
logs, err := f.NginxLogs()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(logs).To(ContainSubstring(`"/something" matches "/something", client:`))
|
||||||
|
Expect(logs).To(ContainSubstring(`rewritten data: "/", args: "",`))
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue