go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/delegation/config_validation_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 delegation 16 17 import ( 18 "context" 19 "testing" 20 21 "google.golang.org/protobuf/encoding/prototext" 22 23 "go.chromium.org/luci/config/validation" 24 25 "go.chromium.org/luci/tokenserver/api/admin/v1" 26 "go.chromium.org/luci/tokenserver/appengine/impl/utils/policy" 27 28 . "github.com/smartystreets/goconvey/convey" 29 . "go.chromium.org/luci/common/testing/assertions" 30 ) 31 32 func TestValidation(t *testing.T) { 33 t.Parallel() 34 35 cases := []struct { 36 Cfg string 37 Errors []string 38 }{ 39 { 40 // No errors, "normal looking" config. 41 Cfg: ` 42 rules { 43 name: "rule 1" 44 requestor: "user:some-app@appspot.gserviceaccount.com" 45 target_service: "service:some-service" 46 allowed_to_impersonate: "group:some-group" 47 allowed_audience: "REQUESTOR" 48 max_validity_duration: 86400 49 } 50 51 rules { 52 name: "rule 2" 53 requestor: "group:some-group" 54 target_service: "*" 55 allowed_to_impersonate: "group:another-group" 56 allowed_audience: "*" 57 max_validity_duration: 86400 58 } 59 `, 60 }, 61 62 { 63 // Duplicate names. 64 Cfg: ` 65 rules { 66 name: "rule 1" 67 requestor: "user:some-app@appspot.gserviceaccount.com" 68 target_service: "service:some-service" 69 allowed_to_impersonate: "group:some-group" 70 allowed_audience: "REQUESTOR" 71 max_validity_duration: 86400 72 } 73 74 rules { 75 name: "rule 1" 76 requestor: "group:some-group" 77 target_service: "*" 78 allowed_to_impersonate: "group:another-group" 79 allowed_audience: "*" 80 max_validity_duration: 86400 81 } 82 `, 83 Errors: []string{`two rules with identical name "rule 1"`}, 84 }, 85 86 { 87 // Missing required fields. 88 Cfg: ` 89 rules { 90 } 91 `, 92 Errors: []string{ 93 `"name" is required`, 94 `"requestor" is required`, 95 `"allowed_to_impersonate" is required`, 96 `"allowed_audience" is required`, 97 `"target_service" is required`, 98 `"max_validity_duration" is required`, 99 }, 100 }, 101 102 { 103 // Validity duration out of range. 104 Cfg: ` 105 rules { 106 name: "rule 1" 107 requestor: "user:some-app@appspot.gserviceaccount.com" 108 target_service: "service:some-service" 109 allowed_to_impersonate: "group:some-group" 110 allowed_audience: "REQUESTOR" 111 max_validity_duration: -1 112 } 113 rules { 114 name: "rule 2" 115 requestor: "user:some-app@appspot.gserviceaccount.com" 116 target_service: "service:some-service" 117 allowed_to_impersonate: "group:some-group" 118 allowed_audience: "REQUESTOR" 119 max_validity_duration: 86401 120 } 121 `, 122 Errors: []string{ 123 `in "delegation.cfg" (rule #1: "rule 1"): "max_validity_duration" must be positive`, 124 `in "delegation.cfg" (rule #2: "rule 2"): "max_validity_duration" must be smaller than 86401`, 125 }, 126 }, 127 128 { 129 // Bad requestor. 130 Cfg: ` 131 rules { 132 name: "rule 1" 133 requestor: "user:some-app@appspot.gserviceaccount.com" # ok 134 requestor: "service:blah" # ok 135 requestor: "group:some-group" # ok 136 requestor: "*" # not ok 137 requestor: "some junk" # not ok 138 requestor: "group:" # not ok 139 target_service: "service:some-service" 140 allowed_to_impersonate: "group:some-group" 141 allowed_audience: "REQUESTOR" 142 max_validity_duration: 3600 143 } 144 `, 145 Errors: []string{ 146 `in "delegation.cfg" (rule #1: "rule 1" / "requestor"): auth: bad identity string "*"`, 147 `in "delegation.cfg" (rule #1: "rule 1" / "requestor"): auth: bad identity string "some junk"`, 148 `in "delegation.cfg" (rule #1: "rule 1" / "requestor"): bad group entry "group:"`, 149 }, 150 }, 151 152 { 153 // Bad allowed_to_impersonate. 154 Cfg: ` 155 rules { 156 name: "rule 1" 157 requestor: "user:some-app@appspot.gserviceaccount.com" 158 target_service: "service:some-service" 159 allowed_to_impersonate: "user:abc@example.com" # ok 160 allowed_to_impersonate: "group:some-group" # ok 161 allowed_to_impersonate: "REQUESTOR" # ok 162 allowed_to_impersonate: "*" # not OK 163 allowed_audience: "REQUESTOR" 164 max_validity_duration: 86400 165 } 166 `, 167 Errors: []string{ 168 `in "delegation.cfg" (rule #1: "rule 1" / "allowed_to_impersonate"): auth: bad identity string "*"`, 169 }, 170 }, 171 172 { 173 // Bad allowed_audience. 174 Cfg: ` 175 rules { 176 name: "rule 1" 177 requestor: "user:some-app@appspot.gserviceaccount.com" 178 target_service: "service:some-service" 179 allowed_to_impersonate: "user:abc@example.com" 180 allowed_audience: "REQUESTOR" # ok 181 allowed_audience: "*" # ok 182 allowed_audience: "user:abc@example.com" # ok 183 allowed_audience: "group:abc" # ok 184 allowed_audience: "some junk" # not ok 185 max_validity_duration: 86400 186 } 187 `, 188 Errors: []string{ 189 `in "delegation.cfg" (rule #1: "rule 1" / "allowed_audience"): auth: bad identity string "some junk"`, 190 }, 191 }, 192 193 { 194 // Bad target_service. 195 Cfg: ` 196 rules { 197 name: "rule 1" 198 requestor: "user:some-app@appspot.gserviceaccount.com" 199 target_service: "service:some-service" # ok 200 target_service: "user:abc@example.com" # not ok 201 target_service: "group:some-group" # not ok 202 allowed_to_impersonate: "user:abc@example.com" 203 allowed_audience: "REQUESTOR" 204 max_validity_duration: 86400 205 } 206 `, 207 Errors: []string{ 208 `in "delegation.cfg" (rule #1: "rule 1" / "target_service"): identity of kind "user" is not allowed here`, 209 `in "delegation.cfg" (rule #1: "rule 1" / "target_service"): group entries are not allowed`, 210 }, 211 }, 212 } 213 214 Convey("Validation works", t, func(c C) { 215 for idx, cs := range cases { 216 c.Printf("Case #%d\n", idx) 217 218 cfg := &admin.DelegationPermissions{} 219 err := prototext.Unmarshal([]byte(cs.Cfg), cfg) 220 So(err, ShouldBeNil) 221 222 ctx := &validation.Context{Context: context.Background()} 223 validateConfigBundle(ctx, policy.ConfigBundle{delegationCfg: cfg}) 224 verr := ctx.Finalize() 225 226 if len(cs.Errors) == 0 { // no errors expected 227 So(verr, ShouldBeNil) 228 } else { 229 verr := verr.(*validation.Error) 230 So(len(verr.Errors), ShouldEqual, len(cs.Errors)) 231 for i, err := range verr.Errors { 232 So(err, ShouldErrLike, cs.Errors[i]) 233 } 234 } 235 } 236 }) 237 }