Add ip/cidr white list support

This commit is contained in:
Manuel de Brito Fontes 2016-06-06 14:31:40 -04:00
parent b395b714be
commit e792e940b2
6 changed files with 187 additions and 0 deletions

View file

@ -44,6 +44,7 @@ import (
"k8s.io/contrib/ingress/controllers/nginx/nginx/auth" "k8s.io/contrib/ingress/controllers/nginx/nginx/auth"
"k8s.io/contrib/ingress/controllers/nginx/nginx/config" "k8s.io/contrib/ingress/controllers/nginx/nginx/config"
"k8s.io/contrib/ingress/controllers/nginx/nginx/healthcheck" "k8s.io/contrib/ingress/controllers/nginx/nginx/healthcheck"
"k8s.io/contrib/ingress/controllers/nginx/nginx/ipwhitelist"
"k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit" "k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit"
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite" "k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
"k8s.io/contrib/ingress/controllers/nginx/nginx/secureupstream" "k8s.io/contrib/ingress/controllers/nginx/nginx/secureupstream"
@ -697,6 +698,12 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err) glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
} }
wl, err := ipwhitelist.ParseAnnotations(ngxCfg.WhiteList, ing)
glog.V(3).Infof("nginx white list %v", wl)
if err != nil {
glog.V(3).Infof("error reading white list annotation in Ingress %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
}
host := rule.Host host := rule.Host
if host == "" { if host == "" {
host = defServerName host = defServerName
@ -728,6 +735,7 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
loc.RateLimit = *rl loc.RateLimit = *rl
loc.Redirect = *locRew loc.Redirect = *locRew
loc.SecureUpstream = secUpstream loc.SecureUpstream = secUpstream
loc.Whitelist = *wl
addLoc = false addLoc = false
continue continue
@ -750,6 +758,7 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
RateLimit: *rl, RateLimit: *rl,
Redirect: *locRew, Redirect: *locRew,
SecureUpstream: secUpstream, SecureUpstream: secUpstream,
Whitelist: *wl,
}) })
} }
} }

View file

@ -180,6 +180,12 @@ http {
{{- range $location := $server.Locations }} {{- range $location := $server.Locations }}
{{ $path := buildLocation $location }} {{ $path := buildLocation $location }}
location {{ $path }} { location {{ $path }} {
{{ if gt (len $location.Whitelist.CIDR) 0 }}
{{- range $ip := $location.Whitelist.CIDR }}
allow {{ $ip }};{{ end }}
deny all;
{{ end -}}
{{ if (and $server.SSL $location.Redirect.SSLRedirect) -}} {{ if (and $server.SSL $location.Redirect.SSLRedirect) -}}
# enforce ssl on server side # enforce ssl on server side
if ($scheme = http) { if ($scheme = http) {

View file

@ -233,6 +233,10 @@ type Configuration struct {
// Responses with the “text/html” type are always compressed if UseGzip is enabled // Responses with the “text/html” type are always compressed if UseGzip is enabled
GzipTypes string `structs:"gzip-types,omitempty"` GzipTypes string `structs:"gzip-types,omitempty"`
// WhiteList allows limiting access to certain client addresses.
// http://nginx.org/en/docs/http/ngx_http_access_module.html
WhiteList []string `structs:"whitelist,omitempty"`
// Defines the number of worker processes. By default auto means number of available CPU cores // Defines the number of worker processes. By default auto means number of available CPU cores
// http://nginx.org/en/docs/ngx_core_module.html#worker_processes // http://nginx.org/en/docs/ngx_core_module.html#worker_processes
WorkerProcesses string `structs:"worker-processes,omitempty"` WorkerProcesses string `structs:"worker-processes,omitempty"`
@ -270,6 +274,7 @@ func NewDefault() Configuration {
VtsStatusZoneSize: "10m", VtsStatusZoneSize: "10m",
UseHTTP2: true, UseHTTP2: true,
CustomHTTPErrors: make([]int, 0), CustomHTTPErrors: make([]int, 0),
WhiteList: make([]string, 0),
} }
if glog.V(5) { if glog.V(5) {

View file

@ -0,0 +1,79 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 ipwhitelist
import (
"errors"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/util/net/sets"
)
const (
whitelist = "ingress.kubernetes.io/whitelist"
)
var (
// ErrMissingWhitelist returned error when the ingress does not contains the
// whitelist annotation
ErrMissingWhitelist = errors.New("whitelist annotation is missing")
// ErrInvalidCIDR returned error when the whitelist annotation does not
// contains a valid IP or network address
ErrInvalidCIDR = errors.New("the annotation does not contains a valid IP address or network")
)
// Whitelist returns the CIDR
type Whitelist struct {
CIDR []string
}
type ingAnnotations map[string]string
func (a ingAnnotations) whitelist() ([]string, error) {
val, ok := a[whitelist]
if !ok {
return nil, ErrMissingWhitelist
}
ipnet, err := sets.ParseIPNets(val)
if err != nil {
return nil, ErrInvalidCIDR
}
nets := make([]string, 0)
for k := range ipnet {
nets = append(nets, k)
}
return nets, nil
}
// ParseAnnotations parses the annotations contained in the ingress
// rule used to configure upstream check parameters
func ParseAnnotations(whiteList []string, ing *extensions.Ingress) (*Whitelist, error) {
if ing.GetAnnotations() == nil {
return &Whitelist{whiteList}, ErrMissingWhitelist
}
wl, err := ingAnnotations(ing.GetAnnotations()).whitelist()
if err != nil {
wl = whiteList
}
return &Whitelist{wl}, err
}

View file

@ -0,0 +1,86 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 ipwhitelist
import (
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/util/intstr"
)
func buildIngress() *extensions.Ingress {
defaultBackend := extensions.IngressBackend{
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
}
return &extensions.Ingress{
ObjectMeta: api.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 TestAnnotations(t *testing.T) {
ing := buildIngress()
_, err := ingAnnotations(ing.GetAnnotations()).whitelist()
if err == nil {
t.Error("Expected a validation error")
}
testNet := "10.0.0.0/24"
enet := []string{testNet}
data := map[string]string{}
data[whitelist] = testNet
ing.SetAnnotations(data)
wl, err := ingAnnotations(ing.GetAnnotations()).whitelist()
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if !reflect.DeepEqual(wl, enet) {
t.Errorf("Expected %v but returned %s", enet, wl)
}
}

View file

@ -18,6 +18,7 @@ package nginx
import ( import (
"k8s.io/contrib/ingress/controllers/nginx/nginx/auth" "k8s.io/contrib/ingress/controllers/nginx/nginx/auth"
"k8s.io/contrib/ingress/controllers/nginx/nginx/ipwhitelist"
"k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit" "k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit"
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite" "k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
) )
@ -99,6 +100,7 @@ type Location struct {
RateLimit ratelimit.RateLimit RateLimit ratelimit.RateLimit
Redirect rewrite.Redirect Redirect rewrite.Redirect
SecureUpstream bool SecureUpstream bool
Whitelist ipwhitelist.Whitelist
} }
// LocationByPath sorts location by path // LocationByPath sorts location by path