Skip to content
This repository was archived by the owner on Apr 17, 2019. It is now read-only.

Commit 3d958cc

Browse files
committed
Add ip/cidr white list support
1 parent cfdd590 commit 3d958cc

File tree

6 files changed

+187
-0
lines changed

6 files changed

+187
-0
lines changed

ingress/controllers/nginx/controller.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"k8s.io/contrib/ingress/controllers/nginx/nginx/auth"
4545
"k8s.io/contrib/ingress/controllers/nginx/nginx/config"
4646
"k8s.io/contrib/ingress/controllers/nginx/nginx/healthcheck"
47+
"k8s.io/contrib/ingress/controllers/nginx/nginx/ipwhitelist"
4748
"k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit"
4849
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
4950
"k8s.io/contrib/ingress/controllers/nginx/nginx/secureupstream"
@@ -697,6 +698,12 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
697698
glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
698699
}
699700

701+
wl, err := ipwhitelist.ParseAnnotations(ngxCfg.WhiteList, ing)
702+
glog.V(3).Infof("nginx white list %v", wl)
703+
if err != nil {
704+
glog.V(3).Infof("error reading white list annotation in Ingress %v/%v: %v", ing.GetNamespace(), ing.GetName(), err)
705+
}
706+
700707
host := rule.Host
701708
if host == "" {
702709
host = defServerName
@@ -728,6 +735,7 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
728735
loc.RateLimit = *rl
729736
loc.Redirect = *locRew
730737
loc.SecureUpstream = secUpstream
738+
loc.Whitelist = *wl
731739

732740
addLoc = false
733741
continue
@@ -750,6 +758,7 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg config.Configuratio
750758
RateLimit: *rl,
751759
Redirect: *locRew,
752760
SecureUpstream: secUpstream,
761+
Whitelist: *wl,
753762
})
754763
}
755764
}

ingress/controllers/nginx/nginx.tmpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ http {
180180
{{- range $location := $server.Locations }}
181181
{{ $path := buildLocation $location }}
182182
location {{ $path }} {
183+
{{ if gt (len $location.Whitelist.CIDR) 0 }}
184+
{{- range $ip := $location.Whitelist.CIDR }}
185+
allow {{ $ip }};{{ end }}
186+
deny all;
187+
{{ end -}}
188+
183189
{{ if (and $server.SSL $location.Redirect.SSLRedirect) -}}
184190
# enforce ssl on server side
185191
if ($scheme = http) {

ingress/controllers/nginx/nginx/config/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ type Configuration struct {
233233
// Responses with the “text/html” type are always compressed if UseGzip is enabled
234234
GzipTypes string `structs:"gzip-types,omitempty"`
235235

236+
// WhiteList allows limiting access to certain client addresses.
237+
// http://nginx.org/en/docs/http/ngx_http_access_module.html
238+
WhiteList []string `structs:"whitelist,omitempty"`
239+
236240
// Defines the number of worker processes. By default auto means number of available CPU cores
237241
// http://nginx.org/en/docs/ngx_core_module.html#worker_processes
238242
WorkerProcesses string `structs:"worker-processes,omitempty"`
@@ -270,6 +274,7 @@ func NewDefault() Configuration {
270274
VtsStatusZoneSize: "10m",
271275
UseHTTP2: true,
272276
CustomHTTPErrors: make([]int, 0),
277+
WhiteList: make([]string, 0),
273278
}
274279

275280
if glog.V(5) {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright 2016 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package ipwhitelist
18+
19+
import (
20+
"errors"
21+
22+
"k8s.io/kubernetes/pkg/apis/extensions"
23+
"k8s.io/kubernetes/pkg/util/net/sets"
24+
)
25+
26+
const (
27+
whitelist = "ingress.kubernetes.io/whitelist"
28+
)
29+
30+
var (
31+
// ErrMissingWhitelist returned error when the ingress does not contains the
32+
// whitelist annotation
33+
ErrMissingWhitelist = errors.New("whitelist annotation is missing")
34+
35+
// ErrInvalidCIDR returned error when the whitelist annotation does not
36+
// contains a valid IP or network address
37+
ErrInvalidCIDR = errors.New("the annotation does not contains a valid IP address or network")
38+
)
39+
40+
// Whitelist returns the CIDR
41+
type Whitelist struct {
42+
CIDR []string
43+
}
44+
45+
type ingAnnotations map[string]string
46+
47+
func (a ingAnnotations) whitelist() ([]string, error) {
48+
val, ok := a[whitelist]
49+
if !ok {
50+
return nil, ErrMissingWhitelist
51+
}
52+
53+
ipnet, err := sets.ParseIPNets(val)
54+
if err != nil {
55+
return nil, ErrInvalidCIDR
56+
}
57+
58+
nets := make([]string, 0)
59+
for k := range ipnet {
60+
nets = append(nets, k)
61+
}
62+
63+
return nets, nil
64+
}
65+
66+
// ParseAnnotations parses the annotations contained in the ingress
67+
// rule used to configure upstream check parameters
68+
func ParseAnnotations(whiteList []string, ing *extensions.Ingress) (*Whitelist, error) {
69+
if ing.GetAnnotations() == nil {
70+
return &Whitelist{whiteList}, ErrMissingWhitelist
71+
}
72+
73+
wl, err := ingAnnotations(ing.GetAnnotations()).whitelist()
74+
if err != nil {
75+
wl = whiteList
76+
}
77+
78+
return &Whitelist{wl}, err
79+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright 2016 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package ipwhitelist
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
"k8s.io/kubernetes/pkg/api"
24+
"k8s.io/kubernetes/pkg/apis/extensions"
25+
"k8s.io/kubernetes/pkg/util/intstr"
26+
)
27+
28+
func buildIngress() *extensions.Ingress {
29+
defaultBackend := extensions.IngressBackend{
30+
ServiceName: "default-backend",
31+
ServicePort: intstr.FromInt(80),
32+
}
33+
34+
return &extensions.Ingress{
35+
ObjectMeta: api.ObjectMeta{
36+
Name: "foo",
37+
Namespace: api.NamespaceDefault,
38+
},
39+
Spec: extensions.IngressSpec{
40+
Backend: &extensions.IngressBackend{
41+
ServiceName: "default-backend",
42+
ServicePort: intstr.FromInt(80),
43+
},
44+
Rules: []extensions.IngressRule{
45+
{
46+
Host: "foo.bar.com",
47+
IngressRuleValue: extensions.IngressRuleValue{
48+
HTTP: &extensions.HTTPIngressRuleValue{
49+
Paths: []extensions.HTTPIngressPath{
50+
{
51+
Path: "/foo",
52+
Backend: defaultBackend,
53+
},
54+
},
55+
},
56+
},
57+
},
58+
},
59+
},
60+
}
61+
}
62+
63+
func TestAnnotations(t *testing.T) {
64+
ing := buildIngress()
65+
66+
_, err := ingAnnotations(ing.GetAnnotations()).whitelist()
67+
if err == nil {
68+
t.Error("Expected a validation error")
69+
}
70+
71+
testNet := "10.0.0.0/24"
72+
enet := []string{testNet}
73+
74+
data := map[string]string{}
75+
data[whitelist] = testNet
76+
ing.SetAnnotations(data)
77+
78+
wl, err := ingAnnotations(ing.GetAnnotations()).whitelist()
79+
if err != nil {
80+
t.Errorf("Unexpected error: %v", err)
81+
}
82+
83+
if !reflect.DeepEqual(wl, enet) {
84+
t.Errorf("Expected %v but returned %s", enet, wl)
85+
}
86+
}

ingress/controllers/nginx/nginx/nginx.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package nginx
1818

1919
import (
2020
"k8s.io/contrib/ingress/controllers/nginx/nginx/auth"
21+
"k8s.io/contrib/ingress/controllers/nginx/nginx/ipwhitelist"
2122
"k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit"
2223
"k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite"
2324
)
@@ -99,6 +100,7 @@ type Location struct {
99100
RateLimit ratelimit.RateLimit
100101
Redirect rewrite.Redirect
101102
SecureUpstream bool
103+
Whitelist ipwhitelist.Whitelist
102104
}
103105

104106
// LocationByPath sorts location by path

0 commit comments

Comments
 (0)