go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/acls/run_read_test.go (about) 1 // Copyright 2021 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 acls 16 17 import ( 18 "testing" 19 20 "google.golang.org/grpc/codes" 21 22 "go.chromium.org/luci/auth/identity" 23 "go.chromium.org/luci/gae/service/datastore" 24 "go.chromium.org/luci/grpc/appstatus" 25 "go.chromium.org/luci/server/auth" 26 "go.chromium.org/luci/server/auth/authtest" 27 28 cfgpb "go.chromium.org/luci/cv/api/config/v2" 29 "go.chromium.org/luci/cv/internal/common" 30 "go.chromium.org/luci/cv/internal/configs/prjcfg/prjcfgtest" 31 "go.chromium.org/luci/cv/internal/configs/validation" 32 "go.chromium.org/luci/cv/internal/cvtesting" 33 "go.chromium.org/luci/cv/internal/run" 34 35 . "github.com/smartystreets/goconvey/convey" 36 . "go.chromium.org/luci/common/testing/assertions" 37 ) 38 39 func TestRunReadChecker(t *testing.T) { 40 t.Parallel() 41 42 Convey("NewRunReadChecker works", t, func() { 43 ct := cvtesting.Test{} 44 ctx, cancel := ct.SetUp(t) 45 defer cancel() 46 47 const projectPublic = "infra" 48 const projectInternal = "infra-internal" 49 50 prjcfgtest.Create(ctx, projectPublic, &cfgpb.Config{ 51 // TODO(crbug/1233963): update this test to stop relying on legacy-based 52 // ACL. 53 CqStatusHost: validation.CQStatusHostPublic, 54 ConfigGroups: []*cfgpb.ConfigGroup{{ 55 Name: "first", 56 }}, 57 }) 58 prjcfgtest.Create(ctx, projectInternal, &cfgpb.Config{ 59 // TODO(crbug/1233963): update this test to stop relying on legacy-based 60 // ACL. 61 CqStatusHost: validation.CQStatusHostInternal, 62 ConfigGroups: []*cfgpb.ConfigGroup{{ 63 Name: "first", 64 }}, 65 }) 66 67 publicRun := &run.Run{ 68 ID: common.RunID(projectPublic + "/123-visible"), 69 EVersion: 5, 70 ConfigGroupID: prjcfgtest.MustExist(ctx, projectPublic).ConfigGroupIDs[0], 71 } 72 internalRun := &run.Run{ 73 ID: common.RunID(projectInternal + "/456-invisible"), 74 EVersion: 5, 75 ConfigGroupID: prjcfgtest.MustExist(ctx, projectInternal).ConfigGroupIDs[0], 76 } 77 So(datastore.Put(ctx, publicRun, internalRun), ShouldBeNil) 78 79 ctx = auth.WithState(ctx, &authtest.FakeState{ 80 Identity: identity.AnonymousIdentity, 81 }) 82 83 Convey("Loading individual Runs", func() { 84 Convey("Run doesn't exist", func() { 85 _, err1 := run.LoadRun(ctx, common.RunID("foo/bar"), NewRunReadChecker()) 86 So(err1, ShouldHaveAppStatus, codes.NotFound) 87 88 Convey("No access must be indistinguishable from not existing Run", func() { 89 _, err2 := run.LoadRun(ctx, internalRun.ID, NewRunReadChecker()) 90 So(err2, ShouldHaveAppStatus, codes.NotFound) 91 92 st1, _ := appstatus.Get(err1) 93 st2, _ := appstatus.Get(err2) 94 So(st1.Message(), ShouldResemble, st2.Message()) 95 So(st1.Details(), ShouldBeEmpty) 96 So(st2.Details(), ShouldBeEmpty) 97 }) 98 }) 99 100 Convey("OK public", func() { 101 r, err := run.LoadRun(ctx, publicRun.ID, NewRunReadChecker()) 102 So(err, ShouldBeNil) 103 So(r, cvtesting.SafeShouldResemble, publicRun) 104 }) 105 106 Convey("OK internal", func() { 107 // TODO(crbug/1233963): add a test once non-legacy ACLs are working. 108 ctx = auth.WithState(ctx, &authtest.FakeState{ 109 Identity: "user:googler@example.com", 110 IdentityGroups: []string{"googlers"}, 111 }) 112 r, err := run.LoadRun(ctx, internalRun.ID, NewRunReadChecker()) 113 So(err, ShouldBeNil) 114 So(r, cvtesting.SafeShouldResemble, internalRun) 115 }) 116 117 Convey("OK v0 API users", func() { 118 ctx = auth.WithState(ctx, &authtest.FakeState{ 119 Identity: "user:v0-api-users@example.com", 120 IdentityGroups: []string{V0APIAllowGroup}, 121 }) 122 r, err := run.LoadRun(ctx, publicRun.ID, NewRunReadChecker()) 123 So(err, ShouldBeNil) 124 So(r, cvtesting.SafeShouldResemble, publicRun) 125 r, err = run.LoadRun(ctx, internalRun.ID, NewRunReadChecker()) 126 So(err, ShouldBeNil) 127 So(r, cvtesting.SafeShouldResemble, internalRun) 128 }) 129 130 Convey("PermissionDenied", func() { 131 ctx = auth.WithState(ctx, &authtest.FakeState{ 132 Identity: "user:public-user@example.com", 133 IdentityGroups: []string{"insufficient"}, 134 }) 135 _, err := run.LoadRun(ctx, internalRun.ID, NewRunReadChecker()) 136 So(err, ShouldHaveAppStatus, codes.NotFound) 137 }) 138 }) 139 }) 140 }