go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/auth/grpc_test.go (about) 1 // Copyright 2023 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package auth 16 17 import ( 18 "context" 19 "net" 20 "net/http" 21 "testing" 22 23 "google.golang.org/grpc" 24 "google.golang.org/grpc/codes" 25 "google.golang.org/grpc/metadata" 26 "google.golang.org/grpc/peer" 27 28 "go.chromium.org/luci/auth/identity" 29 30 . "github.com/smartystreets/goconvey/convey" 31 . "go.chromium.org/luci/common/testing/assertions" 32 ) 33 34 func TestAuthenticatingInterceptor(t *testing.T) { 35 t.Parallel() 36 37 Convey("With request", t, func() { 38 ctx := injectTestDB(context.Background(), &fakeDB{ 39 allowedClientID: "some_client_id", 40 }) 41 42 requestCtx := metadata.NewIncomingContext(ctx, metadata.MD{ 43 ":authority": {"some.example.com"}, 44 "x-boom": {"val1", "val2"}, 45 // Can happen when using pRPC transport. 46 "cookie": { 47 "cookie_1=value_1; cookie_2=value_2", 48 "cookie_3=value_3", 49 }, 50 }) 51 requestCtx = peer.NewContext(requestCtx, &peer.Peer{ 52 Addr: &net.IPAddr{ 53 IP: net.IPv4(1, 2, 3, 4), 54 }, 55 }) 56 57 Convey("Pass", func() { 58 intr := AuthenticatingInterceptor([]Method{ 59 fakeAuthMethod{ 60 clientID: "some_client_id", 61 email: "someone@example.com", 62 observe: func(r RequestMetadata) { 63 So(r.Header("X-Boom"), ShouldEqual, "val1") 64 65 cookie, err := r.Cookie("cookie_1") 66 So(err, ShouldBeNil) 67 So(cookie.Value, ShouldEqual, "value_1") 68 69 cookie, err = r.Cookie("cookie_2") 70 So(err, ShouldBeNil) 71 So(cookie.Value, ShouldEqual, "value_2") 72 73 cookie, err = r.Cookie("cookie_3") 74 So(err, ShouldBeNil) 75 So(cookie.Value, ShouldEqual, "value_3") 76 77 _, err = r.Cookie("cookie_4") 78 So(err, ShouldEqual, http.ErrNoCookie) 79 80 So(r.RemoteAddr(), ShouldEqual, "1.2.3.4") 81 So(r.Host(), ShouldEqual, "some.example.com") 82 }, 83 }, 84 }) 85 86 var innerCtx context.Context 87 _, err := intr.Unary()(requestCtx, "request", &grpc.UnaryServerInfo{}, func(ctx context.Context, req any) (any, error) { 88 innerCtx = ctx 89 return "response", nil 90 }) 91 So(err, ShouldBeNil) 92 93 // The handler was actually called and with the correct state. 94 So(innerCtx, ShouldNotBeNil) 95 So(CurrentIdentity(innerCtx), ShouldEqual, identity.Identity("user:someone@example.com")) 96 }) 97 98 Convey("Blocked", func() { 99 intr := AuthenticatingInterceptor([]Method{ 100 fakeAuthMethod{ 101 clientID: "another_client_id", 102 }, 103 }) 104 _, err := intr.Unary()(requestCtx, "request", &grpc.UnaryServerInfo{}, func(ctx context.Context, req any) (any, error) { 105 panic("must not be called") 106 }) 107 So(err, ShouldHaveGRPCStatus, codes.PermissionDenied) 108 }) 109 }) 110 }