Skip to content

Commit b4fd28c

Browse files
committed
MINOR: deprecate whitelist and black list in favor of allow-list and deny-list
occurrences of whitelist and blacklist in code have been renamed to allow-list and deny-list Signed-off-by: Vincent Gramer <[email protected]>
1 parent ff82484 commit b4fd28c

File tree

5 files changed

+150
-22
lines changed

5 files changed

+150
-22
lines changed

deploy/tests/e2e/access-control/access_control_test.go

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func (suite *AccessControlSuite) Test_Whitelist() {
4141
suite.Run("Inline", func() {
4242
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
4343
{"src-ip-header", " X-Client-IP"},
44-
{"whitelist", " 192.168.2.0/24"},
44+
{"allow-list", " 192.168.2.0/24"},
4545
}
4646

4747
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
@@ -50,10 +50,62 @@ func (suite *AccessControlSuite) Test_Whitelist() {
5050
suite.eventuallyReturns("192.168.5.3", http.StatusForbidden)
5151
})
5252

53+
suite.Run("Inline deprecated annotation name", func() {
54+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
55+
{"src-ip-header", " X-Client-IP"},
56+
{"whitelist", "192.168.4.0/24"},
57+
}
58+
59+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
60+
61+
suite.eventuallyReturns("192.168.4.3", http.StatusOK)
62+
suite.eventuallyReturns("192.168.5.3", http.StatusForbidden)
63+
})
64+
65+
suite.Run("Inline: when new and deprecated annotation names are defined then only new name is considered", func() {
66+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
67+
{"src-ip-header", " X-Client-IP"},
68+
{"whitelist", "192.168.4.0/24"},
69+
{"allow-list", "192.168.5.0/24"},
70+
}
71+
72+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
73+
74+
suite.eventuallyReturns("192.168.5.3", http.StatusOK)
75+
suite.eventuallyReturns("192.168.4.3", http.StatusForbidden)
76+
})
77+
5378
suite.Run("Patternfile", func() {
5479
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
5580
{"src-ip-header", " X-Client-IP"},
56-
{"whitelist", " patterns/ips"},
81+
{"allow-list", " patterns/ips"},
82+
}
83+
84+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
85+
suite.NoError(suite.test.Apply("config/patternfile-a.yml", "", nil))
86+
87+
suite.eventuallyReturns("192.168.0.3", http.StatusOK)
88+
suite.eventuallyReturns("192.168.2.3", http.StatusForbidden)
89+
})
90+
91+
suite.Run("Patternfile deprecated annotation name", func() {
92+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
93+
{"src-ip-header", " X-Client-IP"},
94+
{"whitelist", " patterns/ips2"},
95+
}
96+
97+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
98+
suite.NoError(suite.test.Apply("config/patternfile-a.yml", "", nil))
99+
100+
suite.eventuallyReturns("192.169.0.3", http.StatusOK)
101+
suite.eventuallyReturns("192.168.2.3", http.StatusForbidden)
102+
})
103+
104+
suite.Run("Patternfile: when new and deprecated annotation names are defined then only new name is considered", func() {
105+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
106+
{"src-ip-header", " X-Client-IP"},
107+
{"whitelist", " patterns/ips2"},
108+
{"allow-list", " patterns/ips"},
57109
}
58110

59111
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
@@ -68,7 +120,7 @@ func (suite *AccessControlSuite) Test_Blacklist() {
68120
suite.Run("Inline", func() {
69121
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
70122
{"src-ip-header", " X-Client-IP"},
71-
{"blacklist", " 192.168.2.0/24"},
123+
{"deny-list", " 192.168.2.0/24"},
72124
}
73125

74126
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
@@ -77,10 +129,35 @@ func (suite *AccessControlSuite) Test_Blacklist() {
77129
suite.eventuallyReturns("192.168.5.3", http.StatusOK)
78130
})
79131

132+
suite.Run("Inline deprecated annotation name", func() {
133+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
134+
{"src-ip-header", " X-Client-IP"},
135+
{"blacklist", "192.168.4.0/24"},
136+
}
137+
138+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
139+
140+
suite.eventuallyReturns("192.168.4.3", http.StatusForbidden)
141+
suite.eventuallyReturns("192.168.5.3", http.StatusOK)
142+
})
143+
144+
suite.Run("Inline: when new and deprecated annotation names are defined then only new name is considered", func() {
145+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
146+
{"src-ip-header", " X-Client-IP"},
147+
{"blacklist", "192.168.4.0/24"},
148+
{"deny-list", "192.168.5.0/24"},
149+
}
150+
151+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
152+
153+
suite.eventuallyReturns("192.168.5.3", http.StatusForbidden)
154+
suite.eventuallyReturns("192.168.4.3", http.StatusOK)
155+
})
156+
80157
suite.Run("Patternfile", func() {
81158
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
82159
{"src-ip-header", " X-Client-IP"},
83-
{"blacklist", " patterns/ips"},
160+
{"deny-list", "patterns/ips"},
84161
}
85162

86163
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
@@ -89,4 +166,30 @@ func (suite *AccessControlSuite) Test_Blacklist() {
89166
suite.eventuallyReturns("192.168.0.3", http.StatusForbidden)
90167
suite.eventuallyReturns("192.168.2.3", http.StatusOK)
91168
})
169+
170+
suite.Run("Patternfile deprecated annotation name", func() {
171+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
172+
{"src-ip-header", " X-Client-IP"},
173+
{"blacklist", " patterns/ips2"},
174+
}
175+
176+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
177+
suite.NoError(suite.test.Apply("config/patternfile-a.yml", "", nil))
178+
179+
suite.eventuallyReturns("192.169.0.3", http.StatusForbidden)
180+
suite.eventuallyReturns("192.168.2.3", http.StatusOK)
181+
})
182+
suite.Run("Patternfile: when new and deprecated annotation names are defined then only new name is considered", func() {
183+
suite.tmplData.IngAnnotations = []struct{ Key, Value string }{
184+
{"src-ip-header", " X-Client-IP"},
185+
{"blacklist", "patterns/ips2"},
186+
{"deny-list", "patterns/ips"},
187+
}
188+
189+
suite.NoError(suite.test.Apply("config/deploy.yaml.tmpl", suite.test.GetNS(), suite.tmplData))
190+
suite.NoError(suite.test.Apply("config/patternfile-a.yml", "", nil))
191+
192+
suite.eventuallyReturns("192.168.0.3", http.StatusForbidden)
193+
suite.eventuallyReturns("192.169.2.3", http.StatusOK)
194+
})
92195
}

deploy/tests/e2e/access-control/config/patternfile-a.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ data:
77
ips: |
88
192.168.0.0/24
99
192.168.1.0/24
10+
ips2: |
11+
192.169.0.0/24
12+
192.169.1.0/24

pkg/annotations/annotations.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ func (a annImpl) Frontend(i *store.Ingress, r *rules.List, m maps.Maps) []Annota
9898
resSetCORS := ingress.NewResSetCORS(r)
9999
return []Annotation{
100100
// Simple annoations
101-
ingress.NewBlackList("blacklist", r, m),
102-
ingress.NewWhiteList("whitelist", r, m),
101+
ingress.NewDenyList("deny-list", r, m),
102+
ingress.NewAllowList("allow-list", r, m),
103103
ingress.NewSrcIPHdr("src-ip-header", r),
104104
ingress.NewReqSetHost("set-host", r),
105105
ingress.NewReqPathRewrite("path-rewrite", r),

pkg/annotations/ingress/accessControl.go

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,53 @@ import (
1212
"github.com/haproxytech/kubernetes-ingress/pkg/utils"
1313
)
1414

15+
var logger = utils.GetLogger()
16+
1517
type AccessControl struct {
16-
maps maps.Maps
17-
rules *rules.List
18-
name string
19-
whitelist bool
18+
maps maps.Maps
19+
rules *rules.List
20+
21+
// name of the annotation managing the access control (either allow-list or deny-list)
22+
name string
23+
24+
// deprecatedName is the deprecated annotation's name managing the access control (either whitelist or blacklist).
25+
// It will be removed in a future version in favor name.
26+
deprecatedName string
27+
allowList bool
2028
}
2129

22-
func NewBlackList(n string, r *rules.List, m maps.Maps) *AccessControl {
23-
return &AccessControl{name: n, rules: r, maps: m}
30+
func NewDenyList(n string, r *rules.List, m maps.Maps) *AccessControl {
31+
return &AccessControl{name: n, deprecatedName: "blacklist", rules: r, maps: m}
2432
}
2533

26-
func NewWhiteList(n string, r *rules.List, m maps.Maps) *AccessControl {
27-
return &AccessControl{name: n, rules: r, maps: m, whitelist: true}
34+
func NewAllowList(n string, r *rules.List, m maps.Maps) *AccessControl {
35+
return &AccessControl{name: n, deprecatedName: "whitelist", rules: r, maps: m, allowList: true}
2836
}
2937

3038
func (a *AccessControl) GetName() string {
3139
return a.name
3240
}
3341

3442
func (a *AccessControl) Process(k store.K8s, annotations ...map[string]string) (err error) {
35-
input := common.GetValue(a.GetName(), annotations...)
43+
input := a.GetAnnotationValue(annotations...)
3644
if input == "" {
3745
return
3846
}
3947

4048
if strings.HasPrefix(input, "patterns/") {
4149
a.rules.Add(&rules.ReqDeny{
4250
SrcIPsMap: maps.Path(input),
43-
Whitelist: a.whitelist,
51+
AllowList: a.allowList,
4452
})
4553

4654
return
4755
}
4856

4957
var mapName maps.Name
50-
if a.whitelist {
51-
mapName = maps.Name("whitelist-" + utils.Hash([]byte(input)))
58+
if a.allowList {
59+
mapName = maps.Name("allowlist-" + utils.Hash([]byte(input)))
5260
} else {
53-
mapName = maps.Name("blacklist-" + utils.Hash([]byte(input)))
61+
mapName = maps.Name("denylist-" + utils.Hash([]byte(input)))
5462
}
5563

5664
if !a.maps.MapExists(mapName) {
@@ -66,7 +74,21 @@ func (a *AccessControl) Process(k store.K8s, annotations ...map[string]string) (
6674
}
6775
a.rules.Add(&rules.ReqDeny{
6876
SrcIPsMap: maps.GetPath(mapName),
69-
Whitelist: a.whitelist,
77+
AllowList: a.allowList,
7078
})
7179
return
7280
}
81+
82+
// GetAnnotationValue returns the annotation value of the AccessControl. If the annotation is not defined, it returns an empty string.
83+
// If the "new" annotation's name is not defined, it falls back to the deprecated name and logs a warning.
84+
// Deprecated: remove this function when the deprecated annotation name will not be supported anymore.
85+
func (a *AccessControl) GetAnnotationValue(annotations ...map[string]string) string {
86+
value := common.GetValue(a.name, annotations...)
87+
if value == "" { // fallback to deprecated annotation name
88+
value = common.GetValue(a.deprecatedName, annotations...)
89+
if value != "" {
90+
logger.Warningf("annotation %q is deprecated and will be removed in a future version. Please use %q instead.", a.deprecatedName, a.name)
91+
}
92+
}
93+
return value
94+
}

pkg/haproxy/rules/reqDeny.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
type ReqDeny struct {
1414
SrcIPsMap maps.Path
15-
Whitelist bool
15+
AllowList bool
1616
}
1717

1818
func (r ReqDeny) GetType() Type {
@@ -21,7 +21,7 @@ func (r ReqDeny) GetType() Type {
2121

2222
func (r ReqDeny) Create(client api.HAProxyClient, frontend *models.Frontend, ingressACL string) error {
2323
not := ""
24-
if r.Whitelist {
24+
if r.AllowList {
2525
not = "!"
2626
}
2727
if frontend.Mode == "tcp" {

0 commit comments

Comments
 (0)