You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by zh...@apache.org on 2022/04/18 01:32:49 UTC

[apisix-ingress-controller] branch master updated: ci: add 3 plugin test cases for e2e (#965)

This is an automated email from the ASF dual-hosted git repository.

zhangjintao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git


The following commit(s) were added to refs/heads/master by this push:
     new 64e27681 ci: add 3 plugin test cases for e2e (#965)
64e27681 is described below

commit 64e276813eb539baed44e574c20d2336e119b101
Author: Xin Rong <79...@users.noreply.github.com>
AuthorDate: Mon Apr 18 09:32:43 2022 +0800

    ci: add 3 plugin test cases for e2e (#965)
    
    
    * consumer-restriction plugin
    * csrf plugin
    * client-control plugin
    
    Co-authored-by: rongxin <ro...@api7.ai>
---
 test/e2e/scaffold/consumer.go                  |  33 ++++
 test/e2e/suite-plugins/client-control.go       | 131 ++++++++++++++
 test/e2e/suite-plugins/consumer-restriction.go | 230 +++++++++++++++++++++++++
 test/e2e/suite-plugins/csrf.go                 | 141 +++++++++++++++
 4 files changed, 535 insertions(+)

diff --git a/test/e2e/scaffold/consumer.go b/test/e2e/scaffold/consumer.go
new file mode 100644
index 00000000..3c44a7c7
--- /dev/null
+++ b/test/e2e/scaffold/consumer.go
@@ -0,0 +1,33 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 scaffold
+
+import "fmt"
+
+func (s *Scaffold) ApisixConsumerBasicAuthCreated(name, username, password string) error {
+	ac := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixConsumer
+metadata:
+  name: %s
+spec:
+  authParameter:
+    basicAuth:
+      value:
+        username: %s
+        password: %s
+`, name, username, password)
+	return s.CreateResourceFromString(ac)
+}
diff --git a/test/e2e/suite-plugins/client-control.go b/test/e2e/suite-plugins/client-control.go
new file mode 100644
index 00000000..a1053366
--- /dev/null
+++ b/test/e2e/suite-plugins/client-control.go
@@ -0,0 +1,131 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 plugins
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/onsi/ginkgo"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+)
+
+var _ = ginkgo.Describe("suite-plugins: client-control plugin", func() {
+	opts := &scaffold.Options{
+		Name:                  "default",
+		Kubeconfig:            scaffold.GetKubeconfig(),
+		APISIXConfigPath:      "testdata/apisix-gw-config.yaml",
+		IngressAPISIXReplicas: 1,
+		HTTPBinServicePort:    80,
+		APISIXRouteVersion:    "apisix.apache.org/v2beta3",
+	}
+	s := scaffold.NewScaffold(opts)
+	ginkgo.It("Limit requset body size", func() {
+		backendSvc, backendPorts := s.DefaultHTTPBackend()
+		ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+   match:
+     hosts:
+     - httpbin.org
+     paths:
+       - /anything
+   backends:
+   - serviceName: %s
+     servicePort: %d
+   plugins:
+   - name: client-control
+     enable: true
+     config:
+       max_body_size: 1
+`, backendSvc, backendPorts[0])
+
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+		err := s.EnsureNumApisixUpstreamsCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+		err = s.EnsureNumApisixRoutesCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+		_ = s.NewAPISIXClient().
+			GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusOK)
+
+		msg413 := s.NewAPISIXClient().
+			POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithBytes([]byte("char number cannot be greater than 10")).
+			Expect().
+			Status(http.StatusRequestEntityTooLarge).
+			Body().
+			Raw()
+		assert.Contains(ginkgo.GinkgoT(), msg413, "Request Entity Too Large")
+	})
+
+	ginkgo.It("disable plugin", func() {
+		backendSvc, backendPorts := s.DefaultHTTPBackend()
+		ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+   match:
+     hosts:
+     - httpbin.org
+     paths:
+       - /anything
+   backends:
+   - serviceName: %s
+     servicePort: %d
+   plugins:
+   - name: client-control
+     enable: false
+     config:
+       max_body_size: 1
+`, backendSvc, backendPorts[0])
+
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+		err := s.EnsureNumApisixUpstreamsCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+		err = s.EnsureNumApisixRoutesCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+		_ = s.NewAPISIXClient().
+			GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusOK)
+
+		_ = s.NewAPISIXClient().
+			POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithBytes([]byte("char number can be greater than 10")).
+			Expect().
+			Status(http.StatusOK)
+	})
+})
diff --git a/test/e2e/suite-plugins/consumer-restriction.go b/test/e2e/suite-plugins/consumer-restriction.go
new file mode 100644
index 00000000..ac08386a
--- /dev/null
+++ b/test/e2e/suite-plugins/consumer-restriction.go
@@ -0,0 +1,230 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 plugins
+
+import (
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/onsi/ginkgo"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+)
+
+var _ = ginkgo.Describe("suite-plugins: consumer-restriction plugin", func() {
+	opts := &scaffold.Options{
+		Name:                  "default",
+		Kubeconfig:            scaffold.GetKubeconfig(),
+		APISIXConfigPath:      "testdata/apisix-gw-config.yaml",
+		IngressAPISIXReplicas: 1,
+		HTTPBinServicePort:    80,
+		APISIXRouteVersion:    "apisix.apache.org/v2beta3",
+	}
+	s := scaffold.NewScaffold(opts)
+
+	ginkgo.It("restrict consumer_name", func() {
+		err := s.ApisixConsumerBasicAuthCreated("jack1", "jack1-username", "jack1-password")
+		assert.Nil(ginkgo.GinkgoT(), err, "creating basicAuth ApisixConsumer")
+
+		err = s.ApisixConsumerBasicAuthCreated("jack2", "jack2-username", "jack2-password")
+		assert.Nil(ginkgo.GinkgoT(), err, "creating basicAuth ApisixConsumer")
+
+		// Wait until the ApisixConsumer create event was delivered.
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixConsumers()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing consumer")
+		assert.Len(ginkgo.GinkgoT(), grs, 2)
+
+		assert.Len(ginkgo.GinkgoT(), grs[0].Plugins, 1)
+		assert.Len(ginkgo.GinkgoT(), grs[1].Plugins, 1)
+
+		username := grs[0].Username
+		basicAuth := grs[0].Plugins["basic-auth"]
+		assert.Equal(ginkgo.GinkgoT(), basicAuth, map[string]interface{}{
+			"username": "jack1-username",
+			"password": "jack1-password",
+		})
+
+		basicAuth2 := grs[1].Plugins["basic-auth"]
+		assert.Equal(ginkgo.GinkgoT(), basicAuth2, map[string]interface{}{
+			"username": "jack2-username",
+			"password": "jack2-password",
+		})
+
+		backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+		ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+   match:
+     hosts:
+     - httpbin.org
+     paths:
+       - /anything
+   backends:
+   - serviceName: %s
+     servicePort: %d
+   authentication:
+     enable: true
+     type: basicAuth
+   plugins:
+   - name: consumer-restriction
+     enable: true
+     config:
+       whitelist:
+       - "%s"
+`, backendSvc, backendPorts[0], username)
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar), "creating ApisixRoute with basicAuth")
+		assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes")
+		assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixUpstreamsCreated(1), "Checking number of upstreams")
+
+		_ = s.NewAPISIXClient().GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("Authorization", "Basic amFjazEtdXNlcm5hbWU6amFjazEtcGFzc3dvcmQ=").
+			Expect().
+			Status(http.StatusOK)
+
+		msg401 := s.NewAPISIXClient().GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusUnauthorized).
+			Body().
+			Raw()
+		assert.Contains(ginkgo.GinkgoT(), msg401, "Missing authorization in request")
+
+		msg403 := s.NewAPISIXClient().GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("Authorization", "Basic amFjazItdXNlcm5hbWU6amFjazItcGFzc3dvcmQ=").
+			Expect().
+			Status(http.StatusForbidden).
+			Body().
+			Raw()
+
+		assert.Contains(ginkgo.GinkgoT(), msg403, "The consumer_name is forbidden")
+	})
+
+	ginkgo.It("restrict allowed_by_methods", func() {
+		err := s.ApisixConsumerBasicAuthCreated("jack1", "jack1-username", "jack1-password")
+		assert.Nil(ginkgo.GinkgoT(), err, "creating basicAuth ApisixConsumer")
+
+		err = s.ApisixConsumerBasicAuthCreated("jack2", "jack2-username", "jack2-password")
+		assert.Nil(ginkgo.GinkgoT(), err, "creating basicAuth ApisixConsumer")
+
+		// Wait until the ApisixConsumer create event was delivered.
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixConsumers()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing consumer")
+		assert.Len(ginkgo.GinkgoT(), grs, 2)
+
+		assert.Len(ginkgo.GinkgoT(), grs[0].Plugins, 1)
+		assert.Len(ginkgo.GinkgoT(), grs[1].Plugins, 1)
+
+		username := grs[0].Username
+		basicAuth := grs[0].Plugins["basic-auth"]
+		assert.Equal(ginkgo.GinkgoT(), basicAuth, map[string]interface{}{
+			"username": "jack1-username",
+			"password": "jack1-password",
+		})
+
+		username2 := grs[1].Username
+		basicAuth2 := grs[1].Plugins["basic-auth"]
+		assert.Equal(ginkgo.GinkgoT(), basicAuth2, map[string]interface{}{
+			"username": "jack2-username",
+			"password": "jack2-password",
+		})
+
+		backendSvc, backendPorts := s.DefaultHTTPBackend()
+
+		ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+   match:
+     hosts:
+     - httpbin.org
+     paths:
+       - /anything
+   backends:
+   - serviceName: %s
+     servicePort: %d
+   authentication:
+     enable: true
+     type: basicAuth
+   plugins:
+   - name: consumer-restriction
+     enable: true
+     config:
+       allowed_by_methods:
+       - user: "%s"
+         methods:
+         - "POST"
+         - "GET"
+       - user: "%s"
+         methods:
+         - "GET"
+`, backendSvc, backendPorts[0], username, username2)
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar), "creating ApisixRoute with basicAuth")
+		assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixRoutesCreated(1), "Checking number of routes")
+		assert.Nil(ginkgo.GinkgoT(), s.EnsureNumApisixUpstreamsCreated(1), "Checking number of upstreams")
+
+		_ = s.NewAPISIXClient().GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("Authorization", "Basic amFjazEtdXNlcm5hbWU6amFjazEtcGFzc3dvcmQ=").
+			Expect().
+			Status(http.StatusOK)
+
+		_ = s.NewAPISIXClient().POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("Authorization", "Basic amFjazEtdXNlcm5hbWU6amFjazEtcGFzc3dvcmQ=").
+			Expect().
+			Status(http.StatusOK)
+
+		_ = s.NewAPISIXClient().GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("Authorization", "Basic amFjazItdXNlcm5hbWU6amFjazItcGFzc3dvcmQ=").
+			Expect().
+			Status(http.StatusOK)
+
+		msg403 := s.NewAPISIXClient().POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("Authorization", "Basic amFjazItdXNlcm5hbWU6amFjazItcGFzc3dvcmQ=").
+			Expect().
+			Status(http.StatusForbidden).
+			Body().
+			Raw()
+		assert.Contains(ginkgo.GinkgoT(), msg403, "The consumer_name is forbidden")
+
+		msg401 := s.NewAPISIXClient().GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusUnauthorized).
+			Body().
+			Raw()
+		assert.Contains(ginkgo.GinkgoT(), msg401, "Missing authorization in request")
+	})
+})
diff --git a/test/e2e/suite-plugins/csrf.go b/test/e2e/suite-plugins/csrf.go
new file mode 100644
index 00000000..04321140
--- /dev/null
+++ b/test/e2e/suite-plugins/csrf.go
@@ -0,0 +1,141 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 plugins
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/onsi/ginkgo"
+	"github.com/stretchr/testify/assert"
+
+	"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
+)
+
+var _ = ginkgo.Describe("suite-plugins: csrf plugin", func() {
+	opts := &scaffold.Options{
+		Name:                  "default",
+		Kubeconfig:            scaffold.GetKubeconfig(),
+		APISIXConfigPath:      "testdata/apisix-gw-config.yaml",
+		IngressAPISIXReplicas: 1,
+		HTTPBinServicePort:    80,
+		APISIXRouteVersion:    "apisix.apache.org/v2beta3",
+	}
+	s := scaffold.NewScaffold(opts)
+	ginkgo.It("prevent csrf", func() {
+		backendSvc, backendPorts := s.DefaultHTTPBackend()
+		ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+   match:
+     hosts:
+     - httpbin.org
+     paths:
+       - /anything
+   backends:
+   - serviceName: %s
+     servicePort: %d
+   plugins:
+   - name: csrf
+     enable: true
+     config:
+       key: "edd1c9f034335f136f87ad84b625c8f1"
+`, backendSvc, backendPorts[0])
+
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+		err := s.EnsureNumApisixUpstreamsCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+		err = s.EnsureNumApisixRoutesCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+		msg401 := s.NewAPISIXClient().
+			POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusUnauthorized).
+			Body().
+			Raw()
+		assert.Contains(ginkgo.GinkgoT(), msg401, "no csrf token in headers")
+
+		resp := s.NewAPISIXClient().
+			GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusOK)
+		resp.Header("Set-Cookie").NotEmpty()
+
+		cookie := resp.Cookie("apisix-csrf-token")
+		token := cookie.Value().Raw()
+
+		_ = s.NewAPISIXClient().
+			POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			WithHeader("apisix-csrf-token", token).
+			WithCookie("apisix-csrf-token", token).
+			Expect().
+			Status(http.StatusOK)
+	})
+
+	ginkgo.It("disable plugin", func() {
+		backendSvc, backendPorts := s.DefaultHTTPBackend()
+		ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+   match:
+     hosts:
+     - httpbin.org
+     paths:
+       - /anything
+   backends:
+   - serviceName: %s
+     servicePort: %d
+   plugins:
+   - name: csrf
+     enable: false
+     config:
+       key: "edd1c9f034335f136f87ad84b625c8f1"
+`, backendSvc, backendPorts[0])
+
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+
+		err := s.EnsureNumApisixUpstreamsCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams")
+		err = s.EnsureNumApisixRoutesCreated(1)
+		assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes")
+
+		_ = s.NewAPISIXClient().
+			GET("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusOK)
+
+		_ = s.NewAPISIXClient().
+			POST("/anything").
+			WithHeader("Host", "httpbin.org").
+			Expect().
+			Status(http.StatusOK)
+	})
+})