Skip to content

Commit 31e2a6d

Browse files
committed
Merge remote-tracking branch 'origin/master' into feat/ingress-anno-regex
Signed-off-by: Ashing Zheng <axingfly@gmail.com>
2 parents 1f090bc + e7d192b commit 31e2a6d

File tree

10 files changed

+358
-10
lines changed

10 files changed

+358
-10
lines changed

docs/en/latest/concepts/gateway-api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ By supporting Gateway API, the APISIX Ingress controller can realize richer func
5959

6060
For configuration examples, see the Gateway API tabs in [Configuration Examples](../reference/example.md).
6161

62-
For a complete list of configuration options, refer to the [Gateway API Reference](https://gateway-api.sigs.k8s.io/reference/spec/). Be aware that some fields are not supported, or partially supported.
62+
For a complete list of configuration options, refer to the [Gateway API Reference](https://gateway-api.sigs.k8s.io/reference/1.3/spec/). Be aware that some fields are not supported, or partially supported.
6363

6464
## Unsupported / Partially Supported Fields
6565

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. 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+
package plugins
16+
17+
import (
18+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
19+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
20+
)
21+
22+
type forwardAuth struct{}
23+
24+
// NewForwardAuthHandler creates a handler to convert
25+
// annotations about forward authentication to APISIX forward-auth plugin.
26+
func NewForwardAuthHandler() PluginAnnotationsHandler {
27+
return &forwardAuth{}
28+
}
29+
30+
func (i *forwardAuth) PluginName() string {
31+
return "forward-auth"
32+
}
33+
34+
func (i *forwardAuth) Handle(e annotations.Extractor) (any, error) {
35+
uri := e.GetStringAnnotation(annotations.AnnotationsForwardAuthURI)
36+
sslVerify := e.GetStringAnnotation(annotations.AnnotationsForwardAuthSSLVerify) != annotations.FalseString
37+
if len(uri) > 0 {
38+
return &adctypes.ForwardAuthConfig{
39+
URI: uri,
40+
SSLVerify: sslVerify,
41+
RequestHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthRequestHeaders),
42+
UpstreamHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthUpstreamHeaders),
43+
ClientHeaders: e.GetStringsAnnotation(annotations.AnnotationsForwardAuthClientHeaders),
44+
}, nil
45+
}
46+
47+
return nil, nil
48+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. 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+
package plugins
17+
18+
import (
19+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
20+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
21+
)
22+
23+
type ipRestriction struct{}
24+
25+
// NewIPRestrictionHandler creates a handler to convert
26+
// annotations about client IP control to APISIX ip-restriction plugin.
27+
func NewIPRestrictionHandler() PluginAnnotationsHandler {
28+
return &ipRestriction{}
29+
}
30+
31+
func (i *ipRestriction) PluginName() string {
32+
return "ip-restriction"
33+
}
34+
35+
func (i *ipRestriction) Handle(e annotations.Extractor) (any, error) {
36+
allowlist := e.GetStringsAnnotation(annotations.AnnotationsAllowlistSourceRange)
37+
blocklist := e.GetStringsAnnotation(annotations.AnnotationsBlocklistSourceRange)
38+
39+
if allowlist == nil && blocklist == nil {
40+
return nil, nil
41+
}
42+
43+
return &adctypes.IPRestrictConfig{
44+
Allowlist: allowlist,
45+
Blocklist: blocklist,
46+
}, nil
47+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one or more
2+
// contributor license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright ownership.
4+
// The ASF licenses this file to You under the Apache License, Version 2.0
5+
// (the "License"); you may not use this file except in compliance with
6+
// the License. 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+
package plugins
17+
18+
import (
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
23+
adctypes "github.com/apache/apisix-ingress-controller/api/adc"
24+
"github.com/apache/apisix-ingress-controller/internal/adc/translator/annotations"
25+
)
26+
27+
func TestIPRestrictionHandler(t *testing.T) {
28+
// Test with allowlist only
29+
anno := map[string]string{
30+
annotations.AnnotationsAllowlistSourceRange: "10.2.2.2,192.168.0.0/16",
31+
}
32+
p := NewIPRestrictionHandler()
33+
out, err := p.Handle(annotations.NewExtractor(anno))
34+
assert.Nil(t, err, "checking given error")
35+
assert.NotNil(t, out, "checking output is not nil")
36+
config := out.(*adctypes.IPRestrictConfig)
37+
assert.Len(t, config.Allowlist, 2, "checking size of allowlist")
38+
assert.Equal(t, "10.2.2.2", config.Allowlist[0])
39+
assert.Equal(t, "192.168.0.0/16", config.Allowlist[1])
40+
assert.Nil(t, config.Blocklist, "checking blocklist is nil")
41+
assert.Equal(t, "ip-restriction", p.PluginName())
42+
43+
// Test with both allowlist and blocklist
44+
anno[annotations.AnnotationsBlocklistSourceRange] = "172.17.0.0/16,127.0.0.1"
45+
out, err = p.Handle(annotations.NewExtractor(anno))
46+
assert.Nil(t, err, "checking given error")
47+
assert.NotNil(t, out, "checking output is not nil")
48+
config = out.(*adctypes.IPRestrictConfig)
49+
assert.Len(t, config.Allowlist, 2, "checking size of allowlist")
50+
assert.Equal(t, "10.2.2.2", config.Allowlist[0])
51+
assert.Equal(t, "192.168.0.0/16", config.Allowlist[1])
52+
assert.Len(t, config.Blocklist, 2, "checking size of blocklist")
53+
assert.Equal(t, "172.17.0.0/16", config.Blocklist[0])
54+
assert.Equal(t, "127.0.0.1", config.Blocklist[1])
55+
56+
// Test with blocklist only
57+
delete(anno, annotations.AnnotationsAllowlistSourceRange)
58+
out, err = p.Handle(annotations.NewExtractor(anno))
59+
assert.Nil(t, err, "checking given error")
60+
assert.NotNil(t, out, "checking output is not nil")
61+
config = out.(*adctypes.IPRestrictConfig)
62+
assert.Nil(t, config.Allowlist, "checking allowlist is nil")
63+
assert.Len(t, config.Blocklist, 2, "checking size of blocklist")
64+
assert.Equal(t, "172.17.0.0/16", config.Blocklist[0])
65+
assert.Equal(t, "127.0.0.1", config.Blocklist[1])
66+
67+
// Test with neither allowlist nor blocklist
68+
delete(anno, annotations.AnnotationsBlocklistSourceRange)
69+
out, err = p.Handle(annotations.NewExtractor(anno))
70+
assert.Nil(t, err, "checking given error")
71+
assert.Nil(t, out, "checking the given ip-restriction plugin config is nil")
72+
}

internal/adc/translator/annotations/plugins/plugins.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ var (
4444
NewBasicAuthHandler(),
4545
NewKeyAuthHandler(),
4646
NewResponseRewriteHandler(),
47+
NewIPRestrictionHandler(),
48+
NewForwardAuthHandler(),
4749
}
4850
)
4951

internal/adc/translator/annotations/types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ const (
9191
AnnotationsSvcNamespace = AnnotationsPrefix + "svc-namespace"
9292
)
9393

94+
const (
95+
FalseString = "false"
96+
)
97+
9498
// Handler abstracts the behavior so that the apisix-ingress-controller knows
9599
type IngressAnnotationsParser interface {
96100
// Handle parses the target annotation and converts it to the type-agnostic structure.

internal/adc/translator/annotations_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,47 @@ func TestTranslateIngressAnnotations(t *testing.T) {
288288
ServiceNamespace: "custom-namespace",
289289
},
290290
},
291+
{
292+
name: "forward auth",
293+
anno: map[string]string{
294+
annotations.AnnotationsForwardAuthURI: "http://127.0.0.1:9080",
295+
annotations.AnnotationsForwardAuthRequestHeaders: "Authorization",
296+
annotations.AnnotationsForwardAuthClientHeaders: "Location",
297+
annotations.AnnotationsForwardAuthUpstreamHeaders: "X-User-ID",
298+
},
299+
expected: &IngressConfig{
300+
Plugins: adctypes.Plugins{
301+
"forward-auth": &adctypes.ForwardAuthConfig{
302+
URI: "http://127.0.0.1:9080",
303+
SSLVerify: true,
304+
RequestHeaders: []string{"Authorization"},
305+
UpstreamHeaders: []string{"X-User-ID"},
306+
ClientHeaders: []string{"Location"},
307+
},
308+
},
309+
},
310+
},
311+
{
312+
name: "forward auth with ssl-verify false",
313+
anno: map[string]string{
314+
annotations.AnnotationsForwardAuthURI: "http://127.0.0.1:9080",
315+
annotations.AnnotationsForwardAuthSSLVerify: "false",
316+
annotations.AnnotationsForwardAuthRequestHeaders: "Authorization",
317+
annotations.AnnotationsForwardAuthClientHeaders: "Location",
318+
annotations.AnnotationsForwardAuthUpstreamHeaders: "X-User-ID",
319+
},
320+
expected: &IngressConfig{
321+
Plugins: adctypes.Plugins{
322+
"forward-auth": &adctypes.ForwardAuthConfig{
323+
URI: "http://127.0.0.1:9080",
324+
SSLVerify: false,
325+
RequestHeaders: []string{"Authorization"},
326+
UpstreamHeaders: []string{"X-User-ID"},
327+
ClientHeaders: []string{"Location"},
328+
},
329+
},
330+
},
331+
},
291332
{
292333
name: "regex",
293334
anno: map[string]string{

internal/webhook/v1/ingress_webhook.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,7 @@ var ingresslog = logf.Log.WithName("ingress-resource")
3838

3939
// unsupportedAnnotations contains all the APISIX Ingress annotations that are not supported in 2.0.0
4040
// ref: https://apisix.apache.org/docs/ingress-controller/upgrade-guide/#limited-support-for-ingress-annotations
41-
var unsupportedAnnotations = []string{
42-
"k8s.apisix.apache.org/auth-uri",
43-
"k8s.apisix.apache.org/auth-ssl-verify",
44-
"k8s.apisix.apache.org/auth-request-headers",
45-
"k8s.apisix.apache.org/auth-upstream-headers",
46-
"k8s.apisix.apache.org/auth-client-headers",
47-
"k8s.apisix.apache.org/allowlist-source-range",
48-
"k8s.apisix.apache.org/blocklist-source-range",
49-
}
41+
var unsupportedAnnotations = []string{}
5042

5143
// checkUnsupportedAnnotations checks if the Ingress contains any unsupported annotations
5244
// and returns appropriate warnings

test/e2e/framework/manifests/nginx.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ data:
5151
}
5252
}
5353
54+
location /auth {
55+
content_by_lua_block {
56+
local auth = ngx.req.get_headers()["Authorization"]
57+
if auth == "123" then
58+
ngx.header["X-User-ID"] = "user-123"
59+
ngx.exit(200)
60+
else
61+
ngx.header["Location"] = "http://example.com/auth"
62+
ngx.exit(401)
63+
end
64+
}
65+
}
66+
5467
location /ws {
5568
content_by_lua_block {
5669
local server = require "resty.websocket.server"

0 commit comments

Comments
 (0)