mirror of
https://github.com/alibaba/higress.git
synced 2026-03-06 17:40:51 +08:00
feat: add ip-restriction wasm-go plugin (#759)
This commit is contained in:
31
plugins/wasm-go/extensions/ip-restriction/README.md
Normal file
31
plugins/wasm-go/extensions/ip-restriction/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# 功能说明
|
||||
|
||||
`ip-restriction `插件可以通过将 IP 地址列入白名单或黑名单来限制对服务或路由的访问.支持对单个 IP 地址、多个 IP 地址和类似
|
||||
10.10.10.0/24 的 CIDR范围的限制.
|
||||
|
||||
# 配置说明
|
||||
|
||||
| 配置项 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|----------------|--------|----|-----------------------------|------------------------------------------|
|
||||
| ip_source_type | string | 否 | origin-source | 可选值:1. 对端socket ip:`origin-source`; 2. 通过header获取:`header` |
|
||||
| ip_header_name | string | 否 | x-forwarded-for | 当`ip_source_type`为`header`时,指定自定义IP来源头 |
|
||||
| allow | array | 否 | [] | 白名单列表 |
|
||||
| deny | array | 否 | [] | 黑名单列表 |
|
||||
| status | int | 否 | 403 | 拒绝访问时的 HTTP 状态码 |
|
||||
| message | string | 否 | Your IP address is blocked. | 拒绝访问时的返回信息 |
|
||||
|
||||
|
||||
```yaml
|
||||
ip_source_type: origin-source
|
||||
allow:
|
||||
- 10.0.0.1
|
||||
- 192.168.0.0/16
|
||||
```
|
||||
|
||||
```yaml
|
||||
ip_source_type: header
|
||||
ip_header_name: x-real-iP
|
||||
deny:
|
||||
- 10.0.0.1
|
||||
- 192.169.0.0/16
|
||||
```
|
||||
1
plugins/wasm-go/extensions/ip-restriction/VERSION
Normal file
1
plugins/wasm-go/extensions/ip-restriction/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
1.0.0
|
||||
22
plugins/wasm-go/extensions/ip-restriction/go.mod
Normal file
22
plugins/wasm-go/extensions/ip-restriction/go.mod
Normal file
@@ -0,0 +1,22 @@
|
||||
module github.com/alibaba/higress/plugins/wasm-go/extensions/ip-restriction
|
||||
|
||||
go 1.19
|
||||
|
||||
replace github.com/alibaba/higress/plugins/wasm-go => ../..
|
||||
|
||||
require (
|
||||
github.com/alibaba/higress/plugins/wasm-go v0.0.0
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20240226064518-b3dc4646a35a
|
||||
github.com/tidwall/gjson v1.14.3
|
||||
github.com/zmap/go-iptree v0.0.0-20210731043055-d4e632617837
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/asergeyev/nradix v0.0.0-20170505151046-3872ab85bb56 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/higress-group/nottinygc v0.0.0-20231101025119-e93c4c2f8520 // indirect
|
||||
github.com/magefile/mage v1.14.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tidwall/resp v0.1.1 // indirect
|
||||
)
|
||||
24
plugins/wasm-go/extensions/ip-restriction/go.sum
Normal file
24
plugins/wasm-go/extensions/ip-restriction/go.sum
Normal file
@@ -0,0 +1,24 @@
|
||||
github.com/asergeyev/nradix v0.0.0-20170505151046-3872ab85bb56 h1:Wi5Tgn8K+jDcBYL+dIMS1+qXYH2r7tpRAyBgqrWfQtw=
|
||||
github.com/asergeyev/nradix v0.0.0-20170505151046-3872ab85bb56/go.mod h1:8BhOLuqtSuT5NZtZMwfvEibi09RO3u79uqfHZzfDTR4=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/higress-group/nottinygc v0.0.0-20231101025119-e93c4c2f8520 h1:IHDghbGQ2DTIXHBHxWfqCYQW1fKjyJ/I7W1pMyUDeEA=
|
||||
github.com/higress-group/nottinygc v0.0.0-20231101025119-e93c4c2f8520/go.mod h1:Nz8ORLaFiLWotg6GeKlJMhv8cci8mM43uEnLA5t8iew=
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20240226064518-b3dc4646a35a h1:luYRvxLTE1xYxrXYj7nmjd1U0HHh8pUPiKfdZ0MhCGE=
|
||||
github.com/higress-group/proxy-wasm-go-sdk v0.0.0-20240226064518-b3dc4646a35a/go.mod h1:hNFjhrLUIq+kJ9bOcs8QtiplSQ61GZXtd2xHKx4BYRo=
|
||||
github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo=
|
||||
github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
|
||||
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/resp v0.1.1 h1:Ly20wkhqKTmDUPlyM1S7pWo5kk0tDu8OoC/vFArXmwE=
|
||||
github.com/tidwall/resp v0.1.1/go.mod h1:3/FrruOBAxPTPtundW0VXgmsQ4ZBA0Aw714lVYgwFa0=
|
||||
github.com/zmap/go-iptree v0.0.0-20210731043055-d4e632617837 h1:DjHnADS2r2zynZ3WkCFAQ+PNYngMSNceRROi0pO6c3M=
|
||||
github.com/zmap/go-iptree v0.0.0-20210731043055-d4e632617837/go.mod h1:9vp0bxqozzQwcjBwenEXfKVq8+mYbwHkQ1NF9Ap0DMw=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
157
plugins/wasm-go/extensions/ip-restriction/main.go
Normal file
157
plugins/wasm-go/extensions/ip-restriction/main.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
|
||||
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
|
||||
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/zmap/go-iptree/iptree"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultRealIpHeader string = "X-Forwarded-For"
|
||||
DefaultDenyStatus uint32 = 403
|
||||
DefaultDenyMessage string = "Your IP address is blocked."
|
||||
)
|
||||
const (
|
||||
OriginSourceType = "origin-source"
|
||||
HeaderSourceType = "header"
|
||||
)
|
||||
|
||||
type RestrictionConfig struct {
|
||||
IPSourceType string `json:"ip_source_type"` //IP来源类型
|
||||
IPHeaderName string `json:"ip_header_name"` //真实IP头
|
||||
Allow *iptree.IPTree `json:"allow"` //允许的IP
|
||||
Deny *iptree.IPTree `json:"deny"` //拒绝的IP
|
||||
Status uint32 `json:"status"` //被拒绝时返回的状态码
|
||||
Message string `json:"message"` //被拒绝时返回的消息
|
||||
}
|
||||
|
||||
func main() {
|
||||
wrapper.SetCtx(
|
||||
"ip-restriction",
|
||||
wrapper.ParseConfigBy(parseConfig),
|
||||
wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders))
|
||||
}
|
||||
|
||||
func parseConfig(json gjson.Result, config *RestrictionConfig, log wrapper.Log) error {
|
||||
sourceType := json.Get("ip_source_type")
|
||||
if sourceType.Exists() && sourceType.String() != "" {
|
||||
switch sourceType.String() {
|
||||
case HeaderSourceType:
|
||||
config.IPSourceType = HeaderSourceType
|
||||
case OriginSourceType:
|
||||
default:
|
||||
config.IPSourceType = OriginSourceType
|
||||
}
|
||||
} else {
|
||||
config.IPSourceType = OriginSourceType
|
||||
}
|
||||
|
||||
header := json.Get("ip_header_name")
|
||||
if header.Exists() && header.String() != "" {
|
||||
config.IPHeaderName = header.String()
|
||||
} else {
|
||||
config.IPHeaderName = DefaultRealIpHeader
|
||||
}
|
||||
status := json.Get("status")
|
||||
if status.Exists() && status.Uint() > 1 {
|
||||
config.Status = uint32(header.Uint())
|
||||
} else {
|
||||
config.Status = DefaultDenyStatus
|
||||
}
|
||||
message := json.Get("message")
|
||||
if message.Exists() && message.String() != "" {
|
||||
config.Message = message.String()
|
||||
} else {
|
||||
config.Message = DefaultDenyMessage
|
||||
}
|
||||
allowNets, err := parseIPNets(json.Get("allow").Array())
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
denyNets, err := parseIPNets(json.Get("deny").Array())
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
return err
|
||||
}
|
||||
if allowNets != nil && denyNets != nil {
|
||||
log.Warn("allow and deny cannot be set at the same time")
|
||||
return fmt.Errorf("allow and deny cannot be set at the same time")
|
||||
}
|
||||
if allowNets == nil && denyNets == nil {
|
||||
log.Warn("allow and deny cannot be empty at the same time")
|
||||
return fmt.Errorf("allow and deny cannot be empty at the same time")
|
||||
}
|
||||
config.Allow = allowNets
|
||||
config.Deny = denyNets
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDownStreamIp(config RestrictionConfig) (net.IP, error) {
|
||||
var (
|
||||
s string
|
||||
err error
|
||||
)
|
||||
|
||||
if config.IPSourceType == HeaderSourceType {
|
||||
s, err = proxywasm.GetHttpRequestHeader(config.IPHeaderName)
|
||||
if err == nil {
|
||||
s = strings.Split(strings.Trim(s, " "), ",")[0]
|
||||
}
|
||||
} else {
|
||||
var bs []byte
|
||||
bs, err = proxywasm.GetProperty([]string{"source", "address"})
|
||||
s = string(bs)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip := parseIP(s)
|
||||
realIP := net.ParseIP(ip)
|
||||
if realIP == nil {
|
||||
return nil, fmt.Errorf("invalid ip[%s]", ip)
|
||||
}
|
||||
return realIP, nil
|
||||
}
|
||||
|
||||
func onHttpRequestHeaders(context wrapper.HttpContext, config RestrictionConfig, log wrapper.Log) types.Action {
|
||||
realIp, err := getDownStreamIp(config)
|
||||
if err != nil {
|
||||
return deniedUnauthorized(config)
|
||||
}
|
||||
allow := config.Allow
|
||||
deny := config.Deny
|
||||
if allow != nil {
|
||||
if realIp == nil {
|
||||
log.Error("realIp is nil, blocked")
|
||||
return deniedUnauthorized(config)
|
||||
}
|
||||
if _, found, _ := allow.Get(realIp); !found {
|
||||
return deniedUnauthorized(config)
|
||||
}
|
||||
}
|
||||
if deny != nil {
|
||||
if realIp == nil {
|
||||
log.Error("realIp is nil, continue")
|
||||
return types.ActionContinue
|
||||
}
|
||||
if _, found, _ := deny.Get(realIp); found {
|
||||
return deniedUnauthorized(config)
|
||||
}
|
||||
}
|
||||
return types.ActionContinue
|
||||
}
|
||||
|
||||
func deniedUnauthorized(config RestrictionConfig) types.Action {
|
||||
body, _ := json.Marshal(map[string]string{
|
||||
"message": config.Message,
|
||||
})
|
||||
_ = proxywasm.SendHttpResponse(config.Status, nil, body, -1)
|
||||
return types.ActionContinue
|
||||
}
|
||||
37
plugins/wasm-go/extensions/ip-restriction/utils.go
Normal file
37
plugins/wasm-go/extensions/ip-restriction/utils.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/zmap/go-iptree/iptree"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// parseIPNets 解析Ip段配置
|
||||
func parseIPNets(array []gjson.Result) (*iptree.IPTree, error) {
|
||||
if len(array) == 0 {
|
||||
return nil, nil
|
||||
} else {
|
||||
tree := iptree.New()
|
||||
for _, result := range array {
|
||||
err := tree.AddByString(result.String(), 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid IP[%s]", result.String())
|
||||
}
|
||||
}
|
||||
return tree, nil
|
||||
}
|
||||
}
|
||||
|
||||
// parseIP 解析IP
|
||||
func parseIP(source string) string {
|
||||
if strings.Contains(source, ".") {
|
||||
// parse ipv4
|
||||
return strings.Split(source, ":")[0]
|
||||
}
|
||||
//parse ipv6
|
||||
if strings.Contains(source, "]") {
|
||||
return strings.Split(source, "]")[0][1:]
|
||||
}
|
||||
return source
|
||||
}
|
||||
106
plugins/wasm-go/extensions/ip-restriction/utils_test.go
Normal file
106
plugins/wasm-go/extensions/ip-restriction/utils_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/tidwall/gjson"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parseIPNets(t *testing.T) {
|
||||
type args struct {
|
||||
array []gjson.Result
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantVal bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "",
|
||||
args: args{
|
||||
array: gjson.Parse(`["127.0.0.1/30","10.0.0.1"]`).Array(),
|
||||
},
|
||||
wantVal: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "",
|
||||
args: args{
|
||||
array: gjson.Parse(``).Array(),
|
||||
},
|
||||
wantVal: false,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parseIPNets(tt.args.array)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parseIPNets() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !tt.wantVal && got == nil {
|
||||
return
|
||||
}
|
||||
if _, found, _ := got.GetByString("10.0.0.1"); found != tt.wantVal {
|
||||
t.Errorf("parseIPNets() got = %v, want %v", found, tt.wantVal)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseIP(t *testing.T) {
|
||||
type args struct {
|
||||
source string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
{
|
||||
name: "case 1",
|
||||
args: args{
|
||||
"127.0.0.1",
|
||||
},
|
||||
want: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
name: "case 2",
|
||||
args: args{
|
||||
"127.0.0.1:12",
|
||||
},
|
||||
want: "127.0.0.1",
|
||||
},
|
||||
{
|
||||
name: "case 3",
|
||||
args: args{
|
||||
"fe80::14d5:8aff:fed9:2114",
|
||||
},
|
||||
want: "fe80::14d5:8aff:fed9:2114",
|
||||
},
|
||||
{
|
||||
name: "case 4",
|
||||
args: args{
|
||||
"[fe80::14d5:8aff:fed9:2114]:123",
|
||||
},
|
||||
want: "fe80::14d5:8aff:fed9:2114",
|
||||
},
|
||||
{
|
||||
name: "case 5",
|
||||
args: args{
|
||||
"127.0.0.1:12,[fe80::14d5:8aff:fed9:2114]:123",
|
||||
},
|
||||
want: "127.0.0.1",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := parseIP(tt.args.source); got != tt.want {
|
||||
t.Errorf("parseIP() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
46
test/e2e/conformance/tests/go-wasm-ip-restriction-allow.yaml
Normal file
46
test/e2e/conformance/tests/go-wasm-ip-restriction-allow.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
# Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# 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.
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
name: httproute-app-root
|
||||
namespace: higress-conformance-infra
|
||||
spec:
|
||||
ingressClassName: higress
|
||||
rules:
|
||||
- host: "foo.com"
|
||||
http:
|
||||
paths:
|
||||
- pathType: Prefix
|
||||
path: "/"
|
||||
backend:
|
||||
service:
|
||||
name: infra-backend-v1
|
||||
port:
|
||||
number: 8080
|
||||
---
|
||||
apiVersion: extensions.higress.io/v1alpha1
|
||||
kind: WasmPlugin
|
||||
metadata:
|
||||
name: ip-restriction-allow
|
||||
namespace: higress-system
|
||||
spec:
|
||||
defaultConfig:
|
||||
ip_source_type: header
|
||||
ip_header_name: x-real-ip
|
||||
allow:
|
||||
- 192.168.0.1/16
|
||||
- 10.0.0.1
|
||||
url: file:///opt/plugins/wasm-go/extensions/ip-restriction/plugin.wasm
|
||||
46
test/e2e/conformance/tests/go-wasm-ip-restriction-deny.yaml
Normal file
46
test/e2e/conformance/tests/go-wasm-ip-restriction-deny.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
# Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
#
|
||||
# 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.
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
annotations:
|
||||
name: httproute-app-root
|
||||
namespace: higress-conformance-infra
|
||||
spec:
|
||||
ingressClassName: higress
|
||||
rules:
|
||||
- host: "foo.com"
|
||||
http:
|
||||
paths:
|
||||
- pathType: Prefix
|
||||
path: "/"
|
||||
backend:
|
||||
service:
|
||||
name: infra-backend-v1
|
||||
port:
|
||||
number: 8080
|
||||
---
|
||||
apiVersion: extensions.higress.io/v1alpha1
|
||||
kind: WasmPlugin
|
||||
metadata:
|
||||
name: ip-restriction-deny
|
||||
namespace: higress-system
|
||||
spec:
|
||||
defaultConfig:
|
||||
ip_source_type: header
|
||||
ip_header_name: x-real-ip
|
||||
deny:
|
||||
- 192.168.0.1/16
|
||||
- 10.0.0.1
|
||||
url: file:///opt/plugins/wasm-go/extensions/ip-restriction/plugin.wasm
|
||||
219
test/e2e/conformance/tests/go-wasm-ip-restriction.go
Normal file
219
test/e2e/conformance/tests/go-wasm-ip-restriction.go
Normal file
@@ -0,0 +1,219 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// 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 tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/alibaba/higress/test/e2e/conformance/utils/http"
|
||||
"github.com/alibaba/higress/test/e2e/conformance/utils/suite"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Register(WasmPluginsIPRestrictionAllow)
|
||||
Register(WasmPluginsIPRestrictionDeny)
|
||||
}
|
||||
|
||||
var WasmPluginsIPRestrictionAllow = suite.ConformanceTest{
|
||||
ShortName: "WasmPluginsIPRestrictionAllow",
|
||||
Description: "The Ingress in the higress-conformance-infra namespace test the ip-restriction wasmplugins.",
|
||||
Manifests: []string{"tests/go-wasm-ip-restriction-allow.yaml"},
|
||||
Features: []suite.SupportedFeature{suite.WASMGoConformanceFeature},
|
||||
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
|
||||
testcases := []http.Assertion{
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 200,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "10.0.0.2"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 403,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "192.168.5.0"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 200,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "192.169.5.0"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 403,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
t.Run("WasmPlugins ip-restriction", func(t *testing.T) {
|
||||
for _, testcase := range testcases {
|
||||
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, suite.GatewayAddress, testcase)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
var WasmPluginsIPRestrictionDeny = suite.ConformanceTest{
|
||||
ShortName: "WasmPluginsIPRestrictionDeny",
|
||||
Description: "The Ingress in the higress-conformance-infra namespace test the ip-restriction wasmplugins.",
|
||||
Manifests: []string{"tests/go-wasm-ip-restriction-deny.yaml"},
|
||||
Features: []suite.SupportedFeature{suite.WASMGoConformanceFeature},
|
||||
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
|
||||
testcases := []http.Assertion{
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "10.0.0.1"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 403,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "10.0.0.2"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 200,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "192.168.5.0"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 403,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Meta: http.AssertionMeta{
|
||||
TargetBackend: "infra-backend-v1",
|
||||
TargetNamespace: "higress-conformance-infra",
|
||||
},
|
||||
Request: http.AssertionRequest{
|
||||
ActualRequest: http.Request{
|
||||
Host: "foo.com",
|
||||
Path: "/info",
|
||||
UnfollowRedirect: true,
|
||||
Headers: map[string]string{"X-REAL-IP": "192.169.5.0"},
|
||||
},
|
||||
},
|
||||
Response: http.AssertionResponse{
|
||||
ExpectedResponse: http.Response{
|
||||
StatusCode: 200,
|
||||
},
|
||||
ExpectedResponseNoRequest: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
t.Run("WasmPlugins ip-restriction", func(t *testing.T) {
|
||||
for _, testcase := range testcases {
|
||||
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, suite.GatewayAddress, testcase)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user