diff --git a/controllers/nginx/pkg/cmd/controller/nginx.go b/controllers/nginx/pkg/cmd/controller/nginx.go index 9e2bb64d23a5..1032526ba091 100644 --- a/controllers/nginx/pkg/cmd/controller/nginx.go +++ b/controllers/nginx/pkg/cmd/controller/nginx.go @@ -101,6 +101,8 @@ type NGINXController struct { configmap *api.ConfigMap + storeLister ingress.StoreLister + binary string } @@ -281,6 +283,10 @@ func (n *NGINXController) SetConfig(cmap *api.ConfigMap) { n.configmap = cmap } +func (n *NGINXController) SetListers(lister ingress.StoreLister) { + n.storeLister = lister +} + // OnUpdate is called by syncQueue in https://github.com/aledbf/ingress-controller/blob/master/pkg/ingress/controller/controller.go#L82 // periodically to keep the configuration in sync. // @@ -324,7 +330,20 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) ([]byte, er // and we leave some room to avoid consuming all the FDs available maxOpenFiles := (sysctlFSFileMax() / cfg.WorkerProcesses) - 1024 + setHeaders := map[string]string{} + if cfg.ProxySetHeaders != "" { + cmap, exists, err := n.storeLister.ConfigMap.Get(cfg.ProxySetHeaders) + if err != nil { + glog.Warningf("unexpected error reading configmap %v: %v", cfg.ProxySetHeaders, err) + } + + if exists { + setHeaders = cmap.(*api.ConfigMap).Data + } + } + return n.t.Write(config.TemplateConfig{ + ProxySetHeaders: setHeaders, MaxOpenFiles: maxOpenFiles, BacklogSize: sysctlSomaxconn(), Backends: ingressCfg.Backends, diff --git a/controllers/nginx/pkg/config/config.go b/controllers/nginx/pkg/config/config.go index c3dc11331c70..86971edcf765 100644 --- a/controllers/nginx/pkg/config/config.go +++ b/controllers/nginx/pkg/config/config.go @@ -152,6 +152,9 @@ type Configuration struct { // of your external load balancer ProxyRealIPCIDR string `json:"proxy-real-ip-cidr,omitempty"` + // Sets the name of the configmap that contains the headers to pass to the backend + ProxySetHeaders string `json:"proxy-set-headers,omitempty"` + // Maximum size of the server names hash tables used in server names, map directive’s values, // MIME types, names of request header strings, etcd. // http://nginx.org/en/docs/hash.html @@ -283,6 +286,7 @@ func NewDefault() Configuration { // TemplateConfig contains the nginx configuration to render the file nginx.conf type TemplateConfig struct { + ProxySetHeaders map[string]string MaxOpenFiles int BacklogSize int Backends []*ingress.Backend diff --git a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl index c4f4c497f6f4..f55a5de75a08 100644 --- a/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl +++ b/controllers/nginx/rootfs/etc/nginx/template/nginx.tmpl @@ -1,4 +1,4 @@ -{{ $cfg := .Cfg }}{{ $healthzURI := .HealthzURI }}{{ $backends := .Backends }} +{{ $cfg := .Cfg }}{{ $healthzURI := .HealthzURI }}{{ $backends := .Backends }}{{ $proxyHeaders := .ProxySetHeaders }} daemon off; worker_processes {{ $cfg.WorkerProcesses }}; @@ -307,6 +307,11 @@ http { # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ proxy_set_header Proxy ""; + # Custom headers + {{ range $k, $v := $proxyHeaders }} + proxy_set_header {{ $k }} "{{ $v }}"; + {{ end }} + proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index 0fecef961de4..d12639aed054 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -304,6 +304,14 @@ func newIngressController(config *Configuration) *GenericController { ic.annotations = newAnnotationExtractor(ic) + ic.cfg.Backend.SetListers(ingress.StoreLister{ + Ingress: ic.ingLister, + Service: ic.svcLister, + Endpoint: ic.endpLister, + Secret: ic.secrLister, + ConfigMap: ic.mapLister, + }) + return &ic } diff --git a/core/pkg/ingress/types.go b/core/pkg/ingress/types.go index 4891995e7e2b..3b7413831b15 100644 --- a/core/pkg/ingress/types.go +++ b/core/pkg/ingress/types.go @@ -18,8 +18,10 @@ package ingress import ( "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/client/cache" "k8s.io/kubernetes/pkg/healthz" + cache_store "k8s.io/ingress/core/pkg/cache" "k8s.io/ingress/core/pkg/ingress/annotations/auth" "k8s.io/ingress/core/pkg/ingress/annotations/authreq" "k8s.io/ingress/core/pkg/ingress/annotations/ipwhitelist" @@ -81,6 +83,9 @@ type Controller interface { OnUpdate(Configuration) ([]byte, error) // ConfigMap content of --configmap SetConfig(*api.ConfigMap) + // SetListers allows the access of store listers present in the generic controller + // This avoid the use of the kubernetes client. + SetListers(StoreLister) // BackendDefaults returns the minimum settings required to configure the // communication to endpoints BackendDefaults() defaults.Backend @@ -88,6 +93,16 @@ type Controller interface { Info() *BackendInfo } +// StoreLister returns the configured stores for ingresses, services, +// endpoints, secrets and configmaps. +type StoreLister struct { + Ingress cache_store.StoreToIngressLister + Service cache.StoreToServiceLister + Endpoint cache.StoreToEndpointsLister + Secret cache_store.StoreToSecretsLister + ConfigMap cache_store.StoreToConfigmapLister +} + // BackendInfo returns information about the backend. // This fields contains information that helps to track issues or to // map the running ingress controller to source code