diff --git a/docs/user-guide/annotations.md b/docs/user-guide/annotations.md index 6f8973ba41..12f6f48191 100644 --- a/docs/user-guide/annotations.md +++ b/docs/user-guide/annotations.md @@ -62,6 +62,7 @@ The following annotations are supported: |[nginx.ingress.kubernetes.io/proxy-buffering](#proxy-buffering)|string| |[nginx.ingress.kubernetes.io/ssl-ciphers](#ssl-ciphers)|string| |[nginx.ingress.kubernetes.io/connection-proxy-header](#connection-proxy-header)|string| +|[nginx.ingress.kubernetes.io/enable-access-log](#enable-access-log)|"true" or "false"| **Note:** all the values must be a string. In case of booleans or number it must be quoted. @@ -442,3 +443,11 @@ Using this annotation will override the default connection header set by nginx. ```yaml nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive" ``` + +### Enable Access Log + +In some scenarios could be required to disable NGINX access logs. To enable this feature use the annotation: + +```yaml +nginx.ingress.kubernetes.io/enable-access-log: "false" +``` diff --git a/internal/ingress/annotations/annotations.go b/internal/ingress/annotations/annotations.go index d5321641d6..e04e8fe597 100644 --- a/internal/ingress/annotations/annotations.go +++ b/internal/ingress/annotations/annotations.go @@ -34,6 +34,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend" "k8s.io/ingress-nginx/internal/ingress/annotations/healthcheck" "k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist" + "k8s.io/ingress-nginx/internal/ingress/annotations/log" "k8s.io/ingress-nginx/internal/ingress/annotations/parser" "k8s.io/ingress-nginx/internal/ingress/annotations/portinredirect" "k8s.io/ingress-nginx/internal/ingress/annotations/proxy" @@ -87,6 +88,7 @@ type Ingress struct { Whitelist ipwhitelist.SourceRange XForwardedPrefix bool SSLCiphers string + Logs log.Config } // Extractor defines the annotation parsers to be used in the extraction of annotations @@ -124,6 +126,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor { "Whitelist": ipwhitelist.NewParser(cfg), "XForwardedPrefix": xforwardedprefix.NewParser(cfg), "SSLCiphers": sslcipher.NewParser(cfg), + "Logs": log.NewParser(cfg), }, } } diff --git a/internal/ingress/annotations/log/main.go b/internal/ingress/annotations/log/main.go new file mode 100644 index 0000000000..f7a344f363 --- /dev/null +++ b/internal/ingress/annotations/log/main.go @@ -0,0 +1,58 @@ +/* +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 log + +import ( + extensions "k8s.io/api/extensions/v1beta1" + + "k8s.io/ingress-nginx/internal/ingress/annotations/parser" + "k8s.io/ingress-nginx/internal/ingress/resolver" +) + +type cors struct { + r resolver.Resolver +} + +// Config contains the configuration to be used in the Ingress +type Config struct { + Access bool `json:"accessLog"` +} + +// Equal tests for equality between two Config types +func (bd1 *Config) Equal(bd2 *Config) bool { + if bd1.Access == bd2.Access { + return true + } + + return false +} + +// NewParser creates a new access log annotation parser +func NewParser(r resolver.Resolver) parser.IngressAnnotation { + return cors{r} +} + +// Parse parses the annotations contained in the ingress +// rule used to indicate if the location/s should enable logs +func (c cors) Parse(ing *extensions.Ingress) (interface{}, error) { + accessEnabled, err := parser.GetBoolAnnotation("enable-access-log", ing) + if err != nil { + accessEnabled = true + } + + return &Config{accessEnabled}, nil +} diff --git a/internal/ingress/annotations/log/main_test.go b/internal/ingress/annotations/log/main_test.go new file mode 100644 index 0000000000..34430a9ef7 --- /dev/null +++ b/internal/ingress/annotations/log/main_test.go @@ -0,0 +1,81 @@ +/* +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 log + +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/apimachinery/pkg/util/intstr" + "k8s.io/ingress-nginx/internal/ingress/annotations/parser" + "k8s.io/ingress-nginx/internal/ingress/resolver" +) + +func buildIngress() *extensions.Ingress { + defaultBackend := extensions.IngressBackend{ + ServiceName: "default-backend", + ServicePort: intstr.FromInt(80), + } + + return &extensions.Ingress{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "foo", + Namespace: api.NamespaceDefault, + }, + Spec: extensions.IngressSpec{ + Backend: &extensions.IngressBackend{ + ServiceName: "default-backend", + ServicePort: intstr.FromInt(80), + }, + Rules: []extensions.IngressRule{ + { + Host: "foo.bar.com", + IngressRuleValue: extensions.IngressRuleValue{ + HTTP: &extensions.HTTPIngressRuleValue{ + Paths: []extensions.HTTPIngressPath{ + { + Path: "/foo", + Backend: defaultBackend, + }, + }, + }, + }, + }, + }, + }, + } +} + +func TestIngressLogConfig(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + data[parser.GetAnnotationWithPrefix("enable-access-log")] = "false" + ing.SetAnnotations(data) + + log, _ := NewParser(&resolver.Mock{}).Parse(ing) + nginxLogs, ok := log.(*Config) + if !ok { + t.Errorf("expected a Config type") + } + + if nginxLogs.Access { + t.Errorf("expected access be disabled but is enabled") + } +} diff --git a/internal/ingress/controller/controller.go b/internal/ingress/controller/controller.go index a7647cf7ba..3c677d7ae1 100644 --- a/internal/ingress/controller/controller.go +++ b/internal/ingress/controller/controller.go @@ -427,6 +427,7 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([] loc.XForwardedPrefix = anns.XForwardedPrefix loc.UsePortInRedirects = anns.UsePortInRedirects loc.Connection = anns.Connection + loc.Logs = anns.Logs if loc.Redirect.FromToWWW { server.RedirectFromToWWW = true @@ -460,6 +461,7 @@ func (n *NGINXController) getBackendServers(ingresses []*extensions.Ingress) ([] XForwardedPrefix: anns.XForwardedPrefix, UsePortInRedirects: anns.UsePortInRedirects, Connection: anns.Connection, + Logs: anns.Logs, } if loc.Redirect.FromToWWW { diff --git a/internal/ingress/types.go b/internal/ingress/types.go index 8a618b3acd..bf42057814 100644 --- a/internal/ingress/types.go +++ b/internal/ingress/types.go @@ -29,6 +29,7 @@ import ( "k8s.io/ingress-nginx/internal/ingress/annotations/connection" "k8s.io/ingress-nginx/internal/ingress/annotations/cors" "k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist" + "k8s.io/ingress-nginx/internal/ingress/annotations/log" "k8s.io/ingress-nginx/internal/ingress/annotations/proxy" "k8s.io/ingress-nginx/internal/ingress/annotations/ratelimit" "k8s.io/ingress-nginx/internal/ingress/annotations/redirect" @@ -257,6 +258,9 @@ type Location struct { // original location. // +optional XForwardedPrefix bool `json:"xForwardedPrefix,omitempty"` + // Logs allows to enable or disable the nginx logs + // By default this is enabled + Logs log.Config `json:"logs,omitempty"` } // SSLPassthroughBackend describes a SSL upstream server configured diff --git a/internal/ingress/types_equals.go b/internal/ingress/types_equals.go index c4ad554ea9..b03f3a2663 100644 --- a/internal/ingress/types_equals.go +++ b/internal/ingress/types_equals.go @@ -376,6 +376,9 @@ func (l1 *Location) Equal(l2 *Location) bool { if !(&l1.Connection).Equal(&l2.Connection) { return false } + if !(&l1.Logs).Equal(&l2.Logs) { + return false + } return true } diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl index df57c2d19e..b724b4aa6b 100644 --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -686,6 +686,11 @@ stream { } {{ end }} + + {{ if not $location.Logs.Access }} + access_log 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 }}