Skip to content

Commit

Permalink
e2e test
Browse files Browse the repository at this point in the history
Signed-off-by: huabing zhao <[email protected]>
  • Loading branch information
zhaohuabing committed Nov 23, 2023
1 parent d7fd3fb commit f8258db
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 0 deletions.
80 changes: 80 additions & 0 deletions test/e2e/testdata/basic-auth.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
apiVersion: v1
kind: Secret
metadata:
namespace: gateway-conformance-infra
name: basic-auth-users-secret
data:
.htpasswd: "dXNlcjE6e1NIQX10RVNzQm1FL3lOWTNsYjZhMEw2dlZRRVpOcXc9CnVzZXIyOntTSEF9RUo5TFBGRFhzTjl5blNtYnh2anA3NUJtbHg4PQo="
---
apiVersion: v1
kind: Secret
metadata:
namespace: gateway-conformance-infra
name: basic-auth-users-secret-2
data:
.htpasswd: "dXNlcjM6e1NIQX1QcitqQWR4WkdXOFlXVHhGNVJrb2VpTXBkWWs9CnVzZXI0OntTSEF9SC9LemNFcnQ0RTdzdFI1UXltbU8vVkNoTjVzPQ=="
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: basic-auth
namespace: gateway-conformance-infra
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-basic-auth
namespace: gateway-conformance-infra
basicAuth:
users:
name: "basic-auth-users-secret"
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: basic-auth-2
namespace: gateway-conformance-infra
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-basic-auth-2
namespace: gateway-conformance-infra
basicAuth:
users:
name: "basic-auth-users-secret-2"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-basic-auth
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: same-namespace
rules:
- matches:
- path:
type: PathPrefix
value: /basic-auth
backendRefs:
- name: infra-backend-v1
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-basic-auth-2
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: same-namespace
rules:
- matches:
- path:
type: PathPrefix
value: /basic-auth-2
backendRefs:
- name: infra-backend-v1
port: 8080
182 changes: 182 additions & 0 deletions test/e2e/tests/basic-auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

//go:build e2e
// +build e2e

package tests

import (
"context"
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
"sigs.k8s.io/gateway-api/conformance/utils/http"
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
"sigs.k8s.io/gateway-api/conformance/utils/suite"

egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
)

func init() {
ConformanceTests = append(ConformanceTests, BasicAuthTest)
}

var BasicAuthTest = suite.ConformanceTest{
ShortName: "BasicAuth",
Description: "Resource with BasicAuth enabled",
Manifests: []string{"testdata/basic-auth.yaml"},
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
t.Run("valid username password", func(t *testing.T) {
ns := "gateway-conformance-infra"
routeNN := types.NamespacedName{Name: "http-with-basic-auth", Namespace: ns}
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "basic-auth", Namespace: ns})
SecurityPolicyMustBeAccepted(t, suite.Client, types.NamespacedName{Name: "basic-auth-2", Namespace: ns})
expectedResponse := http.ExpectedResponse{
Request: http.Request{
Path: "/basic-auth",
Headers: map[string]string{
"Authorization": "Basic dXNlcjE6dGVzdDE=", // user1:test1
},
},
Response: http.Response{
StatusCode: 200,
},
Namespace: ns,
}

req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http")
cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req)
if err != nil {
t.Errorf("failed to get expected response: %v", err)
}

if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil {
t.Errorf("failed to compare request and response: %v", err)
}
})

t.Run("without Authorization header", func(t *testing.T) {
ns := "gateway-conformance-infra"
routeNN := types.NamespacedName{Name: "http-with-basic-auth", Namespace: ns}
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)

expectedResponse := http.ExpectedResponse{
Request: http.Request{
Path: "/basic-auth",
},
Response: http.Response{
StatusCode: 401,
},
Namespace: ns,
}

req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http")
cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req)
if err != nil {
t.Errorf("failed to get expected response: %v", err)
}

if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil {
t.Errorf("failed to compare request and response: %v", err)
}
})

t.Run("invalid username password", func(t *testing.T) {
ns := "gateway-conformance-infra"
routeNN := types.NamespacedName{Name: "http-with-basic-auth", Namespace: ns}
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)

expectedResponse := http.ExpectedResponse{
Request: http.Request{
Path: "/basic-auth",
Headers: map[string]string{
"Authorization": "Basic dXNlcjE6dGVzdDI=", // user1:test2
},
},
Response: http.Response{
StatusCode: 401,
},
Namespace: ns,
}

req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http")
cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req)
if err != nil {
t.Errorf("failed to get expected response: %v", err)
}

if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil {
t.Errorf("failed to compare request and response: %v", err)
}
})

t.Run("per-route configuration-second route", func(t *testing.T) {
ns := "gateway-conformance-infra"
routeNN := types.NamespacedName{Name: "http-with-basic-auth", Namespace: ns}
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)

expectedResponse := http.ExpectedResponse{
Request: http.Request{
Path: "/basic-auth-2",
Headers: map[string]string{
"Authorization": "Basic dXNlcjQ6dGVzdDQ=", // user4:test4
},
},
Response: http.Response{
StatusCode: 200,
},
Namespace: ns,
}

req := http.MakeRequest(t, &expectedResponse, gwAddr, "HTTP", "http")
cReq, cResp, err := suite.RoundTripper.CaptureRoundTrip(req)
if err != nil {
t.Errorf("failed to get expected response: %v", err)
}

if err := http.CompareRequest(t, &req, cReq, cResp, expectedResponse); err != nil {
t.Errorf("failed to compare request and response: %v", err)
}
})
},
}

// SecurityPolicyMustBeAccepted waits for the specified SecurityPolicy to be accepted.
func SecurityPolicyMustBeAccepted(
t *testing.T,
client client.Client,
securityPolicyName types.NamespacedName) {
t.Helper()

waitErr := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 60*time.Second, true, func(ctx context.Context) (bool, error) {
securityPolicy := &egv1a1.SecurityPolicy{}
err := client.Get(ctx, securityPolicyName, securityPolicy)
if err != nil {
return false, fmt.Errorf("error fetching SecurityPolicy: %w", err)
}

for _, condition := range securityPolicy.Status.Conditions {
if condition.Type == string(gwv1a2.PolicyConditionAccepted) && condition.Status == metav1.ConditionTrue {
return true, nil
}
}
t.Logf("SecurityPolicy not yet accepted: %v", securityPolicy)
return false, nil
})
require.NoErrorf(t, waitErr, "error waiting for HTTPRoute to have parents matching expectations")
}

0 comments on commit f8258db

Please sign in to comment.