Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add e2e tests for ext auth with grpc auth service #2841

Merged
merged 5 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions test/e2e/testdata/ext-auth-grpc-securitypolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-with-ext-auth
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: same-namespace
hostnames: ["www.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /myapp # This is the path that will be protected by ext auth
backendRefs:
- name: infra-backend-v1
port: 8080
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: http-without-ext-auth
namespace: gateway-conformance-infra
spec:
parentRefs:
- name: same-namespace
hostnames: ["www.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /public # This is the path that will be public
backendRefs:
- name: infra-backend-v1
port: 8080
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: ext-auth-test
namespace: gateway-conformance-infra
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: http-with-ext-auth
extAuth:
grpc:
backendRef:
name: grpc-ext-auth
zhaohuabing marked this conversation as resolved.
Show resolved Hide resolved
namespace: gateway-conformance-infra
port: 9002
249 changes: 249 additions & 0 deletions test/e2e/testdata/ext-auth-grpc-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: grpc-ext-auth
namespace: gateway-conformance-infra
data:
go.mod: |
module github.com/envoyproxy/gateway

go 1.21

require (
github.com/envoyproxy/go-control-plane v0.12.0
github.com/golang/protobuf v1.5.4
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8
google.golang.org/grpc v1.62.1
)

require (
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect
github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
)

go.sum: |
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 h1:IR+hp6ypxjH24bkMfEJ0yHR21+gwPWdV+/IBrPQyn3k=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
main.go: |
package main

import (
"context"
"flag"
"fmt"
"log"
"net"
"net/http"
"strings"

envoy_api_v3_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
envoy_service_auth_v3 "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
"github.com/golang/protobuf/ptypes/wrappers"
"google.golang.org/genproto/googleapis/rpc/code"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"google.golang.org/genproto/googleapis/rpc/status"
)

func main() {
port := flag.Int("port", 9002, "gRPC port")
flag.Parse()

lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
log.Fatalf("failed to listen to %d: %v", *port, err)
}

users := TestUsers()
gs := grpc.NewServer()

envoy_service_auth_v3.RegisterAuthorizationServer(gs, NewAuthServer(users))

log.Printf("starting gRPC server on: %d\n", *port)

go func() {
err = gs.Serve(lis)
if err != nil {
log.Fatalf("failed to serve: %v", err)
}
}()

http.HandleFunc("/healthz", healthCheckHandler)
err = http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatalf("failed to serve: %v", err)
}
}

type authServer struct {
users Users
}

var _ envoy_service_auth_v3.AuthorizationServer = &authServer{}

// NewAuthServer creates a new authorization server.
func NewAuthServer(users Users) envoy_service_auth_v3.AuthorizationServer {
return &authServer{users}
}

// Check implements authorization's Check interface which performs authorization check based on the
// attributes associated with the incoming request.
func (s *authServer) Check(
_ context.Context,
req *envoy_service_auth_v3.CheckRequest) (*envoy_service_auth_v3.CheckResponse, error) {
authorization := req.Attributes.Request.Http.Headers["authorization"]
log.Println(authorization)

extracted := strings.Fields(authorization)
if len(extracted) == 2 && extracted[0] == "Bearer" {
valid, user := s.users.Check(extracted[1])
if valid {
return &envoy_service_auth_v3.CheckResponse{
HttpResponse: &envoy_service_auth_v3.CheckResponse_OkResponse{
OkResponse: &envoy_service_auth_v3.OkHttpResponse{
Headers: []*envoy_api_v3_core.HeaderValueOption{
{
Append: &wrappers.BoolValue{Value: false},
Header: &envoy_api_v3_core.HeaderValue{
// For a successful request, the authorization server sets the
// x-current-user value.
Key: "x-current-user",
Value: user,
},
},
},
},
},
Status: &status.Status{
Code: int32(code.Code_OK),
},
}, nil
}
}

return &envoy_service_auth_v3.CheckResponse{
Status: &status.Status{
Code: int32(code.Code_PERMISSION_DENIED),
},
}, nil
}

// Users holds a list of users.
type Users map[string]string

// Check checks if a key could retrieve a user from a list of users.
func (u Users) Check(key string) (bool, string) {
value, ok := u[key]
if !ok {
return false, ""
}
return ok, value
}

func TestUsers() Users {
return map[string]string{
"token1": "user1",
"token2": "user2",
"token3": "user3",
}
}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
conn, err := grpc.Dial("localhost:9002", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatalf("Could not connect: %v", err)
}
client := envoy_service_auth_v3.NewAuthorizationClient(conn)

response, err := client.Check(context.Background(), &envoy_service_auth_v3.CheckRequest{
Attributes: &envoy_service_auth_v3.AttributeContext{
Request: &envoy_service_auth_v3.AttributeContext_Request{
Http: &envoy_service_auth_v3.AttributeContext_HttpRequest{
Headers: map[string]string{
"authorization": "Bearer token1",
},
},
},
},
})
if response != nil && response.Status.Code == int32(code.Code_OK) {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusServiceUnavailable)
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpc-ext-auth
namespace: gateway-conformance-infra
spec:
replicas: 1
selector:
matchLabels:
app: grpc-ext-auth
template:
metadata:
labels:
app: grpc-ext-auth
spec:
containers:
- name: golang-app-container
command:
- sh
- "-c"
- "cp -a /app /app-live && cd /app-live && go run . "
image: golang:1.21.3-alpine
ports:
- containerPort: 8000
volumeMounts:
- name: grpc-ext-auth
mountPath: /app
readinessProbe:
httpGet:
path: /healthz
port: 8080
volumes:
- name: grpc-ext-auth
configMap:
name: grpc-ext-auth
---
apiVersion: v1
kind: Service
metadata:
name: grpc-ext-auth
namespace: gateway-conformance-infra
spec:
selector:
app: grpc-ext-auth
ports:
- protocol: TCP
port: 9002
targetPort: 9002
6 changes: 6 additions & 0 deletions test/e2e/testdata/ext-auth-http-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ spec:
volumeMounts:
- name: http-ext-auth
mountPath: /usr/src/app
readinessProbe:
zhaohuabing marked this conversation as resolved.
Show resolved Hide resolved
httpGet:
httpHeaders:
- name: authorization
value: "Bearer token1"
port: 9002
volumes:
- name: http-ext-auth
configMap:
Expand Down
Loading