go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/client/tokenclient_test.go (about) 1 // Copyright 2016 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 client 16 17 import ( 18 "context" 19 "crypto/x509" 20 "testing" 21 "time" 22 23 "google.golang.org/grpc" 24 "google.golang.org/protobuf/proto" 25 "google.golang.org/protobuf/types/known/timestamppb" 26 27 "go.chromium.org/luci/common/clock" 28 "go.chromium.org/luci/common/clock/testclock" 29 30 tokenserver "go.chromium.org/luci/tokenserver/api" 31 "go.chromium.org/luci/tokenserver/api/minter/v1" 32 33 . "github.com/smartystreets/goconvey/convey" 34 35 . "go.chromium.org/luci/common/testing/assertions" 36 ) 37 38 func TestTokenClient(t *testing.T) { 39 Convey("works", t, func() { 40 ctx := context.Background() 41 ctx, _ = testclock.UseTime(ctx, time.Date(2015, time.February, 3, 4, 5, 6, 7, time.UTC)) 42 43 expectedResp := &minter.MachineTokenResponse{ 44 TokenType: &minter.MachineTokenResponse_LuciMachineToken{ 45 LuciMachineToken: &minter.LuciMachineToken{ 46 MachineToken: "blah", 47 }, 48 }, 49 } 50 51 c := Client{ 52 Client: &fakeRPCClient{ 53 Out: minter.MintMachineTokenResponse{TokenResponse: expectedResp}, 54 }, 55 Signer: &fakeSigner{}, 56 } 57 58 resp, err := c.MintMachineToken(ctx, &minter.MachineTokenRequest{ 59 TokenType: tokenserver.MachineTokenType_LUCI_MACHINE_TOKEN, 60 }) 61 So(err, ShouldBeNil) 62 So(resp, ShouldResemble, expectedResp) 63 64 rpc := c.Client.(*fakeRPCClient).In 65 So(rpc.Signature, ShouldResemble, []byte("fake signature")) 66 67 tokReq := &minter.MachineTokenRequest{} 68 So(proto.Unmarshal(rpc.SerializedTokenRequest, tokReq), ShouldBeNil) 69 So(tokReq, ShouldResembleProto, &minter.MachineTokenRequest{ 70 Certificate: []byte("fake certificate"), 71 SignatureAlgorithm: minter.SignatureAlgorithm_SHA256_RSA_ALGO, 72 IssuedAt: timestamppb.New(clock.Now(ctx)), 73 TokenType: tokenserver.MachineTokenType_LUCI_MACHINE_TOKEN, 74 }) 75 }) 76 77 Convey("handles error", t, func() { 78 ctx := context.Background() 79 80 c := Client{ 81 Client: &fakeRPCClient{ 82 Out: minter.MintMachineTokenResponse{ 83 ErrorCode: 1234, 84 ErrorMessage: "blah", 85 }, 86 }, 87 Signer: &fakeSigner{}, 88 } 89 90 _, err := c.MintMachineToken(ctx, &minter.MachineTokenRequest{ 91 TokenType: tokenserver.MachineTokenType_LUCI_MACHINE_TOKEN, 92 }) 93 So(err.Error(), ShouldEqual, "token server error 1234 - blah") 94 }) 95 } 96 97 // fakeRPCClient implements minter.TokenMinterClient. 98 type fakeRPCClient struct { 99 In minter.MintMachineTokenRequest 100 Out minter.MintMachineTokenResponse 101 } 102 103 func (f *fakeRPCClient) MintMachineToken(ctx context.Context, in *minter.MintMachineTokenRequest, opts ...grpc.CallOption) (*minter.MintMachineTokenResponse, error) { 104 f.In = *in 105 return &f.Out, nil 106 } 107 108 // fakeSigner implements Signer. 109 type fakeSigner struct{} 110 111 func (f *fakeSigner) Algo(ctx context.Context) (x509.SignatureAlgorithm, error) { 112 return x509.SHA256WithRSA, nil 113 } 114 115 func (f *fakeSigner) Certificate(ctx context.Context) ([]byte, error) { 116 return []byte("fake certificate"), nil 117 } 118 119 func (f *fakeSigner) Sign(ctx context.Context, blob []byte) ([]byte, error) { 120 return []byte("fake signature"), nil 121 }