Managing a whitelist for _/nginx_status (#2187)
Signed-off-by: Sylvain Rabot <s.rabot@lectra.com>
This commit is contained in:
parent
6bc4dad38a
commit
385368990c
8 changed files with 79 additions and 32 deletions
|
@ -63,6 +63,8 @@ The following table shows a configuration option's name, type, and the default v
|
||||||
|[log-format-stream](#log-format-stream)|string|`[$time_local] $protocol $status $bytes_sent $bytes_received $session_time`|
|
|[log-format-stream](#log-format-stream)|string|`[$time_local] $protocol $status $bytes_sent $bytes_received $session_time`|
|
||||||
|[max-worker-connections](#max-worker-connections)|int|16384|
|
|[max-worker-connections](#max-worker-connections)|int|16384|
|
||||||
|[map-hash-bucket-size](#max-worker-connections)|int|64|
|
|[map-hash-bucket-size](#max-worker-connections)|int|64|
|
||||||
|
|[nginx-status-ipv4-whitelist](#nginx-status-ipv4-whitelist)|[]string|"127.0.0.1"|
|
||||||
|
|[nginx-status-ipv6-whitelist](#nginx-status-ipv6-whitelist)|[]string|"::1"|
|
||||||
|[proxy-real-ip-cidr](#proxy-real-ip-cidr)|[]string|"0.0.0.0/0"|
|
|[proxy-real-ip-cidr](#proxy-real-ip-cidr)|[]string|"0.0.0.0/0"|
|
||||||
|[proxy-set-headers](#proxy-set-headers)|string|""|
|
|[proxy-set-headers](#proxy-set-headers)|string|""|
|
||||||
|[server-name-hash-max-size](#server-name-hash-max-size)|int|1024|
|
|[server-name-hash-max-size](#server-name-hash-max-size)|int|1024|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -250,6 +250,11 @@ type Configuration struct {
|
||||||
// http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_bucket_size
|
// http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_bucket_size
|
||||||
MapHashBucketSize int `json:"map-hash-bucket-size,omitempty"`
|
MapHashBucketSize int `json:"map-hash-bucket-size,omitempty"`
|
||||||
|
|
||||||
|
// NginxStatusIpv4Whitelist has the list of cidr that are allowed to access
|
||||||
|
// the /nginx_status endpoint of the "_" server
|
||||||
|
NginxStatusIpv4Whitelist []string `json:"nginx-status-ipv4-whitelist,omitempty"`
|
||||||
|
NginxStatusIpv6Whitelist []string `json:"nginx-status-ipv6-whitelist,omitempty"`
|
||||||
|
|
||||||
// If UseProxyProtocol is enabled ProxyRealIPCIDR defines the default the IP/network address
|
// If UseProxyProtocol is enabled ProxyRealIPCIDR defines the default the IP/network address
|
||||||
// of your external load balancer
|
// of your external load balancer
|
||||||
ProxyRealIPCIDR []string `json:"proxy-real-ip-cidr,omitempty"`
|
ProxyRealIPCIDR []string `json:"proxy-real-ip-cidr,omitempty"`
|
||||||
|
@ -499,8 +504,14 @@ type Configuration struct {
|
||||||
// NewDefault returns the default nginx configuration
|
// NewDefault returns the default nginx configuration
|
||||||
func NewDefault() Configuration {
|
func NewDefault() Configuration {
|
||||||
defIPCIDR := make([]string, 0)
|
defIPCIDR := make([]string, 0)
|
||||||
defIPCIDR = append(defIPCIDR, "0.0.0.0/0")
|
|
||||||
defBindAddress := make([]string, 0)
|
defBindAddress := make([]string, 0)
|
||||||
|
defNginxStatusIpv4Whitelist := make([]string, 0)
|
||||||
|
defNginxStatusIpv6Whitelist := make([]string, 0)
|
||||||
|
|
||||||
|
defIPCIDR = append(defIPCIDR, "0.0.0.0/0")
|
||||||
|
defNginxStatusIpv4Whitelist = append(defNginxStatusIpv4Whitelist, "127.0.0.1")
|
||||||
|
defNginxStatusIpv6Whitelist = append(defNginxStatusIpv6Whitelist, "::1")
|
||||||
|
|
||||||
cfg := Configuration{
|
cfg := Configuration{
|
||||||
AllowBackendServerHeader: false,
|
AllowBackendServerHeader: false,
|
||||||
AccessLogPath: "/var/log/nginx/access.log",
|
AccessLogPath: "/var/log/nginx/access.log",
|
||||||
|
@ -534,6 +545,8 @@ func NewDefault() Configuration {
|
||||||
LogFormatUpstream: logFormatUpstream,
|
LogFormatUpstream: logFormatUpstream,
|
||||||
MaxWorkerConnections: 16384,
|
MaxWorkerConnections: 16384,
|
||||||
MapHashBucketSize: 64,
|
MapHashBucketSize: 64,
|
||||||
|
NginxStatusIpv4Whitelist: defNginxStatusIpv4Whitelist,
|
||||||
|
NginxStatusIpv6Whitelist: defNginxStatusIpv6Whitelist,
|
||||||
ProxyRealIPCIDR: defIPCIDR,
|
ProxyRealIPCIDR: defIPCIDR,
|
||||||
ServerNameHashMaxSize: 1024,
|
ServerNameHashMaxSize: 1024,
|
||||||
ProxyHeadersHashMaxSize: 512,
|
ProxyHeadersHashMaxSize: 512,
|
||||||
|
@ -629,6 +642,8 @@ type TemplateConfig struct {
|
||||||
Cfg Configuration
|
Cfg Configuration
|
||||||
IsIPV6Enabled bool
|
IsIPV6Enabled bool
|
||||||
IsSSLPassthroughEnabled bool
|
IsSSLPassthroughEnabled bool
|
||||||
|
NginxStatusIpv4Whitelist []string
|
||||||
|
NginxStatusIpv6Whitelist []string
|
||||||
RedirectServers map[string]string
|
RedirectServers map[string]string
|
||||||
ListenPorts *ListenPorts
|
ListenPorts *ListenPorts
|
||||||
PublishService *apiv1.Service
|
PublishService *apiv1.Service
|
||||||
|
|
|
@ -621,6 +621,8 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
|
||||||
CustomErrors: len(cfg.CustomHTTPErrors) > 0,
|
CustomErrors: len(cfg.CustomHTTPErrors) > 0,
|
||||||
Cfg: cfg,
|
Cfg: cfg,
|
||||||
IsIPV6Enabled: n.isIPV6Enabled && !cfg.DisableIpv6,
|
IsIPV6Enabled: n.isIPV6Enabled && !cfg.DisableIpv6,
|
||||||
|
NginxStatusIpv4Whitelist: cfg.NginxStatusIpv4Whitelist,
|
||||||
|
NginxStatusIpv6Whitelist: cfg.NginxStatusIpv6Whitelist,
|
||||||
RedirectServers: redirectServers,
|
RedirectServers: redirectServers,
|
||||||
IsSSLPassthroughEnabled: n.cfg.EnableSSLPassthrough,
|
IsSSLPassthroughEnabled: n.cfg.EnableSSLPassthrough,
|
||||||
ListenPorts: n.cfg.ListenPorts,
|
ListenPorts: n.cfg.ListenPorts,
|
||||||
|
|
|
@ -32,14 +32,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
customHTTPErrors = "custom-http-errors"
|
customHTTPErrors = "custom-http-errors"
|
||||||
skipAccessLogUrls = "skip-access-log-urls"
|
skipAccessLogUrls = "skip-access-log-urls"
|
||||||
whitelistSourceRange = "whitelist-source-range"
|
whitelistSourceRange = "whitelist-source-range"
|
||||||
proxyRealIPCIDR = "proxy-real-ip-cidr"
|
proxyRealIPCIDR = "proxy-real-ip-cidr"
|
||||||
bindAddress = "bind-address"
|
bindAddress = "bind-address"
|
||||||
httpRedirectCode = "http-redirect-code"
|
httpRedirectCode = "http-redirect-code"
|
||||||
proxyStreamResponses = "proxy-stream-responses"
|
proxyStreamResponses = "proxy-stream-responses"
|
||||||
hideHeaders = "hide-headers"
|
hideHeaders = "hide-headers"
|
||||||
|
nginxStatusIpv4Whitelist = "nginx-status-ipv4-whitelist"
|
||||||
|
nginxStatusIpv6Whitelist = "nginx-status-ipv6-whitelist"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -54,6 +56,7 @@ func ReadConfig(src map[string]string) config.Configuration {
|
||||||
conf[k] = v
|
conf[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to := config.NewDefault()
|
||||||
errors := make([]int, 0)
|
errors := make([]int, 0)
|
||||||
skipUrls := make([]string, 0)
|
skipUrls := make([]string, 0)
|
||||||
whiteList := make([]string, 0)
|
whiteList := make([]string, 0)
|
||||||
|
@ -62,7 +65,6 @@ func ReadConfig(src map[string]string) config.Configuration {
|
||||||
|
|
||||||
bindAddressIpv4List := make([]string, 0)
|
bindAddressIpv4List := make([]string, 0)
|
||||||
bindAddressIpv6List := make([]string, 0)
|
bindAddressIpv6List := make([]string, 0)
|
||||||
redirectCode := 308
|
|
||||||
|
|
||||||
if val, ok := conf[customHTTPErrors]; ok {
|
if val, ok := conf[customHTTPErrors]; ok {
|
||||||
delete(conf, customHTTPErrors)
|
delete(conf, customHTTPErrors)
|
||||||
|
@ -116,7 +118,7 @@ func ReadConfig(src map[string]string) config.Configuration {
|
||||||
glog.Warningf("%v is not a valid HTTP code: %v", val, err)
|
glog.Warningf("%v is not a valid HTTP code: %v", val, err)
|
||||||
} else {
|
} else {
|
||||||
if validRedirectCodes.Has(j) {
|
if validRedirectCodes.Has(j) {
|
||||||
redirectCode = j
|
to.HTTPRedirectCode = j
|
||||||
} else {
|
} else {
|
||||||
glog.Warningf("The code %v is not a valid as HTTP redirect code. Using the default.", val)
|
glog.Warningf("The code %v is not a valid as HTTP redirect code. Using the default.", val)
|
||||||
}
|
}
|
||||||
|
@ -134,7 +136,22 @@ func ReadConfig(src map[string]string) config.Configuration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
to := config.NewDefault()
|
// Nginx Status whitlelist
|
||||||
|
if val, ok := conf[nginxStatusIpv4Whitelist]; ok {
|
||||||
|
whitelist := make([]string, 0)
|
||||||
|
whitelist = append(whitelist, strings.Split(val, ",")...)
|
||||||
|
to.NginxStatusIpv4Whitelist = whitelist
|
||||||
|
|
||||||
|
delete(conf, nginxStatusIpv4Whitelist)
|
||||||
|
}
|
||||||
|
if val, ok := conf[nginxStatusIpv6Whitelist]; ok {
|
||||||
|
whitelist := make([]string, 0)
|
||||||
|
whitelist = append(whitelist, strings.Split(val, ",")...)
|
||||||
|
to.NginxStatusIpv6Whitelist = whitelist
|
||||||
|
|
||||||
|
delete(conf, nginxStatusIpv6Whitelist)
|
||||||
|
}
|
||||||
|
|
||||||
to.CustomHTTPErrors = filterErrors(errors)
|
to.CustomHTTPErrors = filterErrors(errors)
|
||||||
to.SkipAccessLogURLs = skipUrls
|
to.SkipAccessLogURLs = skipUrls
|
||||||
to.WhitelistSourceRange = whiteList
|
to.WhitelistSourceRange = whiteList
|
||||||
|
@ -142,7 +159,6 @@ func ReadConfig(src map[string]string) config.Configuration {
|
||||||
to.BindAddressIpv4 = bindAddressIpv4List
|
to.BindAddressIpv4 = bindAddressIpv4List
|
||||||
to.BindAddressIpv6 = bindAddressIpv6List
|
to.BindAddressIpv6 = bindAddressIpv6List
|
||||||
to.HideHeaders = hideHeadersList
|
to.HideHeaders = hideHeadersList
|
||||||
to.HTTPRedirectCode = redirectCode
|
|
||||||
to.ProxyStreamResponses = streamResponses
|
to.ProxyStreamResponses = streamResponses
|
||||||
to.DisableIpv6DNS = !ing_net.IsIPv6Enabled()
|
to.DisableIpv6DNS = !ing_net.IsIPv6Enabled()
|
||||||
|
|
||||||
|
|
|
@ -33,20 +33,22 @@ func TestFilterErrors(t *testing.T) {
|
||||||
|
|
||||||
func TestMergeConfigMapToStruct(t *testing.T) {
|
func TestMergeConfigMapToStruct(t *testing.T) {
|
||||||
conf := map[string]string{
|
conf := map[string]string{
|
||||||
"custom-http-errors": "300,400,demo",
|
"custom-http-errors": "300,400,demo",
|
||||||
"proxy-read-timeout": "1",
|
"proxy-read-timeout": "1",
|
||||||
"proxy-send-timeout": "2",
|
"proxy-send-timeout": "2",
|
||||||
"skip-access-log-urls": "/log,/demo,/test",
|
"skip-access-log-urls": "/log,/demo,/test",
|
||||||
"use-proxy-protocol": "true",
|
"use-proxy-protocol": "true",
|
||||||
"disable-access-log": "true",
|
"disable-access-log": "true",
|
||||||
"access-log-path": "/var/log/test/access.log",
|
"access-log-path": "/var/log/test/access.log",
|
||||||
"error-log-path": "/var/log/test/error.log",
|
"error-log-path": "/var/log/test/error.log",
|
||||||
"use-gzip": "true",
|
"use-gzip": "true",
|
||||||
"enable-dynamic-tls-records": "false",
|
"enable-dynamic-tls-records": "false",
|
||||||
"gzip-types": "text/html",
|
"gzip-types": "text/html",
|
||||||
"proxy-real-ip-cidr": "1.1.1.1/8,2.2.2.2/24",
|
"proxy-real-ip-cidr": "1.1.1.1/8,2.2.2.2/24",
|
||||||
"bind-address": "1.1.1.1,2.2.2.2,3.3.3,2001:db8:a0b:12f0::1,3731:54:65fe:2::a7,33:33:33::33::33",
|
"bind-address": "1.1.1.1,2.2.2.2,3.3.3,2001:db8:a0b:12f0::1,3731:54:65fe:2::a7,33:33:33::33::33",
|
||||||
"worker-shutdown-timeout": "99s",
|
"worker-shutdown-timeout": "99s",
|
||||||
|
"nginx-status-ipv4-whitelist": "127.0.0.1,10.0.0.0/24",
|
||||||
|
"nginx-status-ipv6-whitelist": "::1,2001::/16",
|
||||||
}
|
}
|
||||||
def := config.NewDefault()
|
def := config.NewDefault()
|
||||||
def.CustomHTTPErrors = []int{300, 400}
|
def.CustomHTTPErrors = []int{300, 400}
|
||||||
|
@ -63,6 +65,8 @@ func TestMergeConfigMapToStruct(t *testing.T) {
|
||||||
def.BindAddressIpv4 = []string{"1.1.1.1", "2.2.2.2"}
|
def.BindAddressIpv4 = []string{"1.1.1.1", "2.2.2.2"}
|
||||||
def.BindAddressIpv6 = []string{"[2001:db8:a0b:12f0::1]", "[3731:54:65fe:2::a7]"}
|
def.BindAddressIpv6 = []string{"[2001:db8:a0b:12f0::1]", "[3731:54:65fe:2::a7]"}
|
||||||
def.WorkerShutdownTimeout = "99s"
|
def.WorkerShutdownTimeout = "99s"
|
||||||
|
def.NginxStatusIpv4Whitelist = []string{"127.0.0.1", "10.0.0.0/24"}
|
||||||
|
def.NginxStatusIpv6Whitelist = []string{"::1", "2001::/16"}
|
||||||
|
|
||||||
to := ReadConfig(conf)
|
to := ReadConfig(conf)
|
||||||
if diff := pretty.Compare(to, def); diff != "" {
|
if diff := pretty.Compare(to, def); diff != "" {
|
||||||
|
|
|
@ -1011,8 +1011,14 @@ stream {
|
||||||
# this is required to avoid error if nginx is being monitored
|
# this is required to avoid error if nginx is being monitored
|
||||||
# with an external software (like sysdig)
|
# with an external software (like sysdig)
|
||||||
location /nginx_status {
|
location /nginx_status {
|
||||||
allow 127.0.0.1;
|
{{ range $v := $all.NginxStatusIpv4Whitelist }}
|
||||||
{{ if $all.IsIPV6Enabled }}allow ::1;{{ end }}
|
allow {{ $v }};
|
||||||
|
{{ end }}
|
||||||
|
{{ if $all.IsIPV6Enabled -}}
|
||||||
|
{{ range $v := $all.NginxStatusIpv6Whitelist }}
|
||||||
|
allow {{ $v }};
|
||||||
|
{{ end }}
|
||||||
|
{{ end -}}
|
||||||
deny all;
|
deny all;
|
||||||
|
|
||||||
access_log off;
|
access_log off;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
"keepAlive": 75,
|
"keepAlive": 75,
|
||||||
"mapHashBucketSize": 64,
|
"mapHashBucketSize": 64,
|
||||||
"maxWorkerConnections": 16384,
|
"maxWorkerConnections": 16384,
|
||||||
|
"nginxStatusIpv4Whitelist": "127.0.0.1",
|
||||||
|
"nginxStatusIpv6Whitelist": "::1",
|
||||||
"proxyRealIpCidr": "0.0.0.0/0",
|
"proxyRealIpCidr": "0.0.0.0/0",
|
||||||
"retryNonIdempotent": false,
|
"retryNonIdempotent": false,
|
||||||
"serverNameHashBucketSize": 64,
|
"serverNameHashBucketSize": 64,
|
||||||
|
@ -113,7 +115,7 @@
|
||||||
"pemSha": ""
|
"pemSha": ""
|
||||||
},
|
},
|
||||||
"vtsDefaultFilterKey": "$uri $server_name"
|
"vtsDefaultFilterKey": "$uri $server_name"
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"isDefBackend": true,
|
"isDefBackend": true,
|
||||||
|
@ -57210,4 +57212,4 @@
|
||||||
"failTimeout": 0
|
"failTimeout": 0
|
||||||
}]
|
}]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue