diff --git a/docs/user-guide/nginx-configuration/configmap.md b/docs/user-guide/nginx-configuration/configmap.md index d893782bdb..b736550b3b 100755 --- a/docs/user-guide/nginx-configuration/configmap.md +++ b/docs/user-guide/nginx-configuration/configmap.md @@ -74,6 +74,7 @@ The following table shows a configuration option's name, type, and the default v |[server-name-hash-bucket-size](#server-name-hash-bucket-size)|int|`` |[proxy-headers-hash-max-size](#proxy-headers-hash-max-size)|int|512| |[proxy-headers-hash-bucket-size](#proxy-headers-hash-bucket-size)|int|64| +|[plugins](#plugins)|[]string| | |[reuse-port](#reuse-port)|bool|"true"| |[server-tokens](#server-tokens)|bool|"true"| |[ssl-ciphers](#ssl-ciphers)|string|"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"| @@ -465,6 +466,11 @@ _References:_ - [http://nginx.org/en/docs/hash.html](http://nginx.org/en/docs/hash.html) - [https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_headers_hash_bucket_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_headers_hash_bucket_size) +## plugins + +Configures plugins to use placed in the directory /etc/nginx/lua/plugins. Every plugin has to have main.lua in the root. +Every plugin has to bundle all of its dependencies. The execution order follows the definition. + ## server-tokens Send NGINX Server header in responses and display NGINX version in error pages. _**default:**_ is enabled diff --git a/internal/ingress/controller/config/config.go b/internal/ingress/controller/config/config.go index b9aa93a476..02a0fca3ae 100644 --- a/internal/ingress/controller/config/config.go +++ b/internal/ingress/controller/config/config.go @@ -268,6 +268,11 @@ type Configuration struct { NginxStatusIpv4Whitelist []string `json:"nginx-status-ipv4-whitelist,omitempty"` NginxStatusIpv6Whitelist []string `json:"nginx-status-ipv6-whitelist,omitempty"` + // Plugins configures plugins to use placed in the directory /etc/nginx/lua/plugins. + // Every plugin has to have main.lua in the root. Every plugin has to bundle all of its dependencies. + // The execution order follows the definition. + Plugins []string `json:"plugins,omitempty"` + // If UseProxyProtocol is enabled ProxyRealIPCIDR defines the default the IP/network address // of your external load balancer ProxyRealIPCIDR []string `json:"proxy-real-ip-cidr,omitempty"` diff --git a/internal/ingress/controller/template/configmap.go b/internal/ingress/controller/template/configmap.go index 25a0f75d70..a51af34450 100644 --- a/internal/ingress/controller/template/configmap.go +++ b/internal/ingress/controller/template/configmap.go @@ -61,6 +61,7 @@ const ( globalAuthCacheKey = "global-auth-cache-key" globalAuthCacheDuration = "global-auth-cache-duration" luaSharedDictsKey = "lua-shared-dicts" + plugins = "plugins" ) var ( @@ -341,6 +342,15 @@ func ReadConfig(src map[string]string) config.Configuration { delete(conf, workerProcesses) } + if val, ok := conf[plugins]; ok { + to.Plugins = strings.Split(val, ",") + for i := range to.Plugins { + to.Plugins[i] = strings.TrimSpace(to.Plugins[i]) + } + + delete(conf, plugins) + } + to.CustomHTTPErrors = filterErrors(errors) to.SkipAccessLogURLs = skipUrls to.WhitelistSourceRange = whiteList diff --git a/rootfs/etc/nginx/template/nginx.tmpl b/rootfs/etc/nginx/template/nginx.tmpl index cef735766f..7982b90417 100755 --- a/rootfs/etc/nginx/template/nginx.tmpl +++ b/rootfs/etc/nginx/template/nginx.tmpl @@ -103,7 +103,7 @@ http { plugins = res end -- load all plugins that'll be used here - plugins.init({}) + plugins.init({ {{ range $idx, $plugin := $cfg.Plugins }}{{ if $idx }},{{ end }}{{ $plugin | quote }}{{ end }} }) } init_worker_by_lua_block { diff --git a/test/e2e/settings/plugins.go b/test/e2e/settings/plugins.go new file mode 100644 index 0000000000..038b226179 --- /dev/null +++ b/test/e2e/settings/plugins.go @@ -0,0 +1,54 @@ +/* +Copyright 2020 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 settings + +import ( + "fmt" + "net/http" + "strings" + + "github.com/onsi/ginkgo" + "k8s.io/ingress-nginx/test/e2e/framework" +) + +var _ = framework.IngressNginxDescribe("plugins", func() { + f := framework.NewDefaultFramework("plugins") + + ginkgo.BeforeEach(func() { + f.NewEchoDeployment() + }) + + ginkgo.It("should exist a x-hello-world header", func() { + f.UpdateNginxConfigMapData("plugins", "hello_world, invalid") + + host := "example.com" + f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)) + + f.WaitForNginxConfiguration( + func(server string) bool { + return strings.Contains(server, fmt.Sprintf("server_name %v", host)) && + strings.Contains(server, `plugins.init({ "hello_world","invalid" })`) + }) + + f.HTTPTestClient(). + GET("/"). + WithHeader("Host", host). + Expect(). + Status(http.StatusOK). + Body().Contains("x-hello-world=1") + }) +})