go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/server/auth/authtest/db_test.go (about) 1 // Copyright 2015 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 authtest 16 17 import ( 18 "context" 19 "errors" 20 "net" 21 "sort" 22 "testing" 23 24 "go.chromium.org/luci/auth/identity" 25 26 "go.chromium.org/luci/server/auth/realms" 27 "go.chromium.org/luci/server/auth/service/protocol" 28 29 . "github.com/smartystreets/goconvey/convey" 30 . "go.chromium.org/luci/common/testing/assertions" 31 ) 32 33 var ( 34 testPerm1 = realms.RegisterPermission("testing.tests.perm1") 35 testPerm2 = realms.RegisterPermission("testing.tests.perm2") 36 testPerm3 = realms.RegisterPermission("testing.tests.perm3") 37 ) 38 39 func init() { 40 testPerm1.AddFlags(realms.UsedInQueryRealms) 41 } 42 43 func TestFakeDB(t *testing.T) { 44 t.Parallel() 45 46 ctx := context.Background() 47 48 dataRoot := &protocol.RealmData{EnforceInService: []string{"A"}} 49 dataSome := &protocol.RealmData{EnforceInService: []string{"B"}} 50 51 Convey("With FakeDB", t, func() { 52 db := NewFakeDB( 53 MockMembership("user:abc@def.com", "group-a"), 54 MockMembership("user:abc@def.com", "group-b"), 55 56 MockGroup("group-c", []identity.Identity{"user:abc@def.com"}), 57 MockGroup("group-d", nil), 58 59 MockPermission("user:abc@def.com", "proj:realm", testPerm1), 60 MockPermission("user:abc@def.com", "another:realm", testPerm1), 61 MockPermission("user:abc@def.com", "proj:realm", testPerm2), 62 63 MockPermission("user:abc@def.com", "proj:cond", testPerm1, 64 RestrictAttribute("attr1", "val1", "val2")), 65 MockPermission("user:abc@def.com", "proj:cond", testPerm2, 66 RestrictAttribute("attr1", "val1", "val2"), 67 RestrictAttribute("attr2", "val3")), 68 69 MockRealmData("proj:@root", dataRoot), 70 MockRealmData("proj:some", dataSome), 71 72 MockIPAllowlist("127.0.0.42", "allowlist"), 73 ) 74 75 Convey("Membership checks work", func() { 76 out, err := db.CheckMembership(ctx, "user:abc@def.com", []string{"group-a", "group-b", "group-c", "group-d"}) 77 So(err, ShouldBeNil) 78 So(out, ShouldResemble, []string{"group-a", "group-b", "group-c"}) 79 80 resp, err := db.IsMember(ctx, "user:abc@def.com", nil) 81 So(err, ShouldBeNil) 82 So(resp, ShouldBeFalse) 83 84 resp, err = db.IsMember(ctx, "user:abc@def.com", []string{"group-b"}) 85 So(err, ShouldBeNil) 86 So(resp, ShouldBeTrue) 87 88 resp, err = db.IsMember(ctx, "user:abc@def.com", []string{"group-c"}) 89 So(err, ShouldBeNil) 90 So(resp, ShouldBeTrue) 91 92 resp, err = db.IsMember(ctx, "user:abc@def.com", []string{"group-d"}) 93 So(err, ShouldBeNil) 94 So(resp, ShouldBeFalse) 95 96 resp, err = db.IsMember(ctx, "user:abc@def.com", []string{"another", "group-b"}) 97 So(err, ShouldBeNil) 98 So(resp, ShouldBeTrue) 99 100 resp, err = db.IsMember(ctx, "user:another@def.com", []string{"group-b"}) 101 So(err, ShouldBeNil) 102 So(resp, ShouldBeFalse) 103 104 resp, err = db.IsMember(ctx, "user:another@def.com", []string{"another", "group-b"}) 105 So(err, ShouldBeNil) 106 So(resp, ShouldBeFalse) 107 108 resp, err = db.IsMember(ctx, "user:abc@def.com", []string{"another"}) 109 So(err, ShouldBeNil) 110 So(resp, ShouldBeFalse) 111 }) 112 113 Convey("Permission checks work", func() { 114 resp, err := db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:realm", nil) 115 So(err, ShouldBeNil) 116 So(resp, ShouldBeTrue) 117 118 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm2, "proj:realm", nil) 119 So(err, ShouldBeNil) 120 So(resp, ShouldBeTrue) 121 122 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm3, "proj:realm", nil) 123 So(err, ShouldBeNil) 124 So(resp, ShouldBeFalse) 125 126 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:unknown", nil) 127 So(err, ShouldBeNil) 128 So(resp, ShouldBeFalse) 129 }) 130 131 Convey("Conditional permission checks work", func() { 132 resp, err := db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:cond", nil) 133 So(err, ShouldBeNil) 134 So(resp, ShouldBeFalse) 135 136 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:cond", realms.Attrs{ 137 "attr1": "val1", 138 }) 139 So(err, ShouldBeNil) 140 So(resp, ShouldBeTrue) 141 142 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:cond", realms.Attrs{ 143 "attr1": "val2", 144 }) 145 So(err, ShouldBeNil) 146 So(resp, ShouldBeTrue) 147 148 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:cond", realms.Attrs{ 149 "attr1": "val3", 150 }) 151 So(err, ShouldBeNil) 152 So(resp, ShouldBeFalse) 153 154 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:cond", realms.Attrs{ 155 "unknown": "val1", 156 }) 157 So(err, ShouldBeNil) 158 So(resp, ShouldBeFalse) 159 160 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm2, "proj:cond", realms.Attrs{ 161 "attr1": "val1", 162 }) 163 So(err, ShouldBeNil) 164 So(resp, ShouldBeFalse) 165 166 resp, err = db.HasPermission(ctx, "user:abc@def.com", testPerm2, "proj:cond", realms.Attrs{ 167 "attr1": "val1", 168 "attr2": "val3", 169 }) 170 So(err, ShouldBeNil) 171 So(resp, ShouldBeTrue) 172 }) 173 174 Convey("QueryRealms works", func() { 175 res, err := db.QueryRealms(ctx, "user:abc@def.com", testPerm1, "", nil) 176 So(err, ShouldBeNil) 177 sort.Strings(res) 178 So(res, ShouldResemble, []string{"another:realm", "proj:realm"}) 179 180 res, err = db.QueryRealms(ctx, "user:abc@def.com", testPerm1, "proj", nil) 181 So(err, ShouldBeNil) 182 So(res, ShouldResemble, []string{"proj:realm"}) 183 184 res, err = db.QueryRealms(ctx, "user:zzz@def.com", testPerm1, "", nil) 185 So(err, ShouldBeNil) 186 So(res, ShouldBeEmpty) 187 188 // Conditional bindings. 189 res, err = db.QueryRealms(ctx, "user:abc@def.com", testPerm1, "", realms.Attrs{ 190 "attr1": "val1", 191 }) 192 So(err, ShouldBeNil) 193 sort.Strings(res) 194 So(res, ShouldResemble, []string{"another:realm", "proj:cond", "proj:realm"}) 195 196 // Unflagged permission. 197 _, err = db.QueryRealms(ctx, "user:abc@def.com", testPerm2, "", nil) 198 So(err, ShouldErrLike, "permission testing.tests.perm2 cannot be used in QueryRealms") 199 }) 200 201 Convey("FilterKnownGroups works", func() { 202 known, err := db.FilterKnownGroups(ctx, []string{"missing", "group-b", "group-a", "group-c", "group-d", "group-a", "missing"}) 203 So(err, ShouldBeNil) 204 So(known, ShouldResemble, []string{ 205 "group-b", "group-a", "group-c", "group-d", "group-a", 206 }) 207 }) 208 209 Convey("GetRealmData works", func() { 210 data, err := db.GetRealmData(ctx, "proj:some") 211 So(err, ShouldBeNil) 212 So(data, ShouldEqual, dataSome) 213 214 // No automatic fallback to root happens, mock it yourself. 215 data, err = db.GetRealmData(ctx, "proj:zzz") 216 So(err, ShouldBeNil) 217 So(data, ShouldBeNil) 218 }) 219 220 Convey("IP allowlist checks work", func() { 221 resp, err := db.IsAllowedIP(ctx, net.ParseIP("127.0.0.42"), "allowlist") 222 So(err, ShouldBeNil) 223 So(resp, ShouldBeTrue) 224 225 resp, err = db.IsAllowedIP(ctx, net.ParseIP("127.0.0.42"), "another") 226 So(err, ShouldBeNil) 227 So(resp, ShouldBeFalse) 228 229 resp, err = db.IsAllowedIP(ctx, net.ParseIP("192.0.0.1"), "allowlist") 230 So(err, ShouldBeNil) 231 So(resp, ShouldBeFalse) 232 }) 233 234 Convey("Error works", func() { 235 mockedErr := errors.New("boom") 236 db.AddMocks(MockError(mockedErr)) 237 238 _, err := db.IsMember(ctx, "user:abc@def.com", []string{"group-a"}) 239 So(err, ShouldEqual, mockedErr) 240 241 _, err = db.HasPermission(ctx, "user:abc@def.com", testPerm1, "proj:realm", nil) 242 So(err, ShouldEqual, mockedErr) 243 244 _, err = db.IsAllowedIP(ctx, net.ParseIP("127.0.0.42"), "allowlist") 245 So(err, ShouldEqual, mockedErr) 246 247 _, err = db.FilterKnownGroups(ctx, []string{"a", "b"}) 248 So(err, ShouldEqual, mockedErr) 249 }) 250 }) 251 }