go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/buildbucket/appengine/internal/buildtoken/buildtoken_test.go (about) 1 // Copyright 2022 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 buildtoken provide related functions for generating and parsing build 16 // tokens. 17 package buildtoken 18 19 import ( 20 "context" 21 "encoding/base64" 22 "testing" 23 24 "google.golang.org/protobuf/proto" 25 26 pb "go.chromium.org/luci/buildbucket/proto" 27 "go.chromium.org/luci/server/secrets" 28 "go.chromium.org/luci/server/secrets/testsecrets" 29 30 . "github.com/smartystreets/goconvey/convey" 31 32 . "go.chromium.org/luci/common/testing/assertions" 33 ) 34 35 func mkToken(ctx context.Context, buildID int64, purpose pb.TokenBody_Purpose) string { 36 token, err := GenerateToken(ctx, buildID, purpose) 37 So(err, ShouldBeNil) 38 return token 39 } 40 41 func TestBuildToken(t *testing.T) { 42 t.Parallel() 43 44 Convey("build token", t, func() { 45 secretStore := &testsecrets.Store{ 46 Secrets: map[string]secrets.Secret{ 47 "somekey": {Active: []byte("i r key")}, 48 }, 49 } 50 ctx := secrets.Use(context.Background(), secretStore) 51 ctx = secrets.GeneratePrimaryTinkAEADForTest(ctx) 52 53 Convey("success (encrypted)", func() { 54 bID := int64(123) 55 token := mkToken(ctx, bID, pb.TokenBody_BUILD) 56 tBody, err := parseToTokenBodyImpl(ctx, token, 123, pb.TokenBody_BUILD) 57 So(err, ShouldBeNil) 58 So(tBody.BuildId, ShouldEqual, bID) 59 So(tBody.Purpose, ShouldEqual, pb.TokenBody_BUILD) 60 So(len(tBody.State), ShouldNotEqual, 0) 61 }) 62 63 Convey("wrong build", func() { 64 bID := int64(123) 65 token := mkToken(ctx, bID, pb.TokenBody_BUILD) 66 _, err := parseToTokenBodyImpl(ctx, token, 321, pb.TokenBody_BUILD) 67 So(err, ShouldErrLike, "token is for build 123") 68 }) 69 70 Convey("skip build check", func() { 71 bID := int64(123) 72 token := mkToken(ctx, bID, pb.TokenBody_BUILD) 73 tBody, err := parseToTokenBodyImpl(ctx, token, 0, pb.TokenBody_BUILD) 74 So(err, ShouldBeNil) 75 So(tBody, ShouldNotBeNil) 76 }) 77 78 Convey("skip purpose check", func() { 79 bID := int64(123) 80 tBody, err := parseToTokenBodyImpl(ctx, mkToken(ctx, bID, pb.TokenBody_BUILD), bID) 81 So(err, ShouldBeNil) 82 So(tBody, ShouldNotBeNil) 83 84 tBody, err = parseToTokenBodyImpl(ctx, mkToken(ctx, bID, pb.TokenBody_TASK), bID) 85 So(err, ShouldBeNil) 86 So(tBody, ShouldNotBeNil) 87 }) 88 89 Convey("multi purpose check", func() { 90 bID := int64(123) 91 token := mkToken(ctx, bID, pb.TokenBody_BUILD) 92 tBody, err := parseToTokenBodyImpl(ctx, token, bID, pb.TokenBody_TASK, pb.TokenBody_BUILD) 93 So(err, ShouldBeNil) 94 So(tBody, ShouldNotBeNil) 95 96 tBody, err = parseToTokenBodyImpl(ctx, token, bID, pb.TokenBody_BUILD, pb.TokenBody_TASK) 97 So(err, ShouldBeNil) 98 So(tBody, ShouldNotBeNil) 99 }) 100 101 Convey("wrong purpose", func() { 102 bID := int64(123) 103 token := mkToken(ctx, bID, pb.TokenBody_BUILD) 104 _, err := parseToTokenBodyImpl(ctx, token, 123, pb.TokenBody_TASK) 105 So(err, ShouldErrLike, "token is for purpose BUILD") 106 107 _, err = parseToTokenBodyImpl(ctx, token, 123, pb.TokenBody_START_BUILD, pb.TokenBody_TASK) 108 So(err, ShouldErrLike, "token is for purpose BUILD") 109 }) 110 111 Convey("not base64 encoded token", func() { 112 _, err := parseToTokenBodyImpl(ctx, "invalid token", 123, pb.TokenBody_BUILD) 113 So(err, ShouldErrLike, "error decoding token") 114 }) 115 116 Convey("bad base64 encoded token", func() { 117 _, err := parseToTokenBodyImpl(ctx, "abckish", 123, pb.TokenBody_BUILD) 118 So(err, ShouldErrLike, "error unmarshalling token") 119 }) 120 121 Convey("unsupported token version", func() { 122 tkBody := &pb.TokenBody{ 123 BuildId: 1, 124 State: []byte("random"), 125 } 126 tkBytes, err := proto.Marshal(tkBody) 127 So(err, ShouldBeNil) 128 tkEnvelop := &pb.TokenEnvelope{ 129 Version: pb.TokenEnvelope_VERSION_UNSPECIFIED, 130 Payload: tkBytes, 131 } 132 tkeBytes, err := proto.Marshal(tkEnvelop) 133 So(err, ShouldBeNil) 134 _, err = parseToTokenBodyImpl(ctx, base64.RawURLEncoding.EncodeToString(tkeBytes), 123, pb.TokenBody_BUILD) 135 So(err, ShouldErrLike, "token with version 0 is not supported") 136 }) 137 }) 138 }