go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/tokenserver/appengine/impl/delegation/rpc_import_delegation_configs_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 "time" 21 22 "go.chromium.org/luci/appengine/gaetesting" 23 "go.chromium.org/luci/common/clock/testclock" 24 "go.chromium.org/luci/config" 25 "go.chromium.org/luci/config/cfgclient" 26 "go.chromium.org/luci/config/impl/memory" 27 admin "go.chromium.org/luci/tokenserver/api/admin/v1" 28 "go.chromium.org/luci/tokenserver/appengine/impl/utils/policy" 29 30 . "github.com/smartystreets/goconvey/convey" 31 . "go.chromium.org/luci/common/testing/assertions" 32 ) 33 34 func TestImportDelegationConfigs(t *testing.T) { 35 t.Parallel() 36 37 Convey("Works", t, func() { 38 ctx := gaetesting.TestingContext() 39 ctx, clk := testclock.UseTime(ctx, testclock.TestTimeUTC) 40 41 ctx = prepareCfg(ctx, `rules { 42 name: "rule 1" 43 requestor: "user:some-user@example.com" 44 target_service: "service:some-service" 45 allowed_to_impersonate: "group:some-group" 46 allowed_audience: "REQUESTOR" 47 max_validity_duration: 86400 48 }`) 49 50 rules := NewRulesCache() 51 rpc := ImportDelegationConfigsRPC{RulesCache: rules} 52 53 // No config. 54 r, err := rules.Rules(ctx) 55 So(err, ShouldEqual, policy.ErrNoPolicy) 56 57 resp, err := rpc.ImportDelegationConfigs(ctx, nil) 58 So(err, ShouldBeNil) 59 So(resp, ShouldResemble, &admin.ImportedConfigs{ 60 Revision: "669865709d488bd6fbcec4fd87d6d1070253f42f", 61 }) 62 63 // Have config now. 64 r, err = rules.Rules(ctx) 65 So(err, ShouldBeNil) 66 So(r.rules[0].rule.Name, ShouldEqual, "rule 1") 67 So(r.revision, ShouldEqual, "669865709d488bd6fbcec4fd87d6d1070253f42f") 68 69 // Noop import. 70 resp, err = rpc.ImportDelegationConfigs(ctx, nil) 71 So(err, ShouldBeNil) 72 So(resp.Revision, ShouldEqual, "669865709d488bd6fbcec4fd87d6d1070253f42f") 73 74 // Try to import completely broken config. 75 ctx = prepareCfg(ctx, `I'm broken`) 76 _, err = rpc.ImportDelegationConfigs(ctx, nil) 77 So(err, ShouldErrLike, `line 1.0: unknown field name`) 78 79 // Old config is not replaced. 80 r, _ = rules.Rules(ctx) 81 So(r.revision, ShouldEqual, "669865709d488bd6fbcec4fd87d6d1070253f42f") 82 83 // Try to import a config that doesn't pass validation. 84 ctx = prepareCfg(ctx, `rules { 85 name: "rule 1" 86 }`) 87 _, err = rpc.ImportDelegationConfigs(ctx, nil) 88 So(err, ShouldErrLike, `"requestor" is required (and 4 other errors)`) 89 90 // Old config is not replaced. 91 r, _ = rules.Rules(ctx) 92 So(r.revision, ShouldEqual, "669865709d488bd6fbcec4fd87d6d1070253f42f") 93 94 // Roll time to expire local rules cache. 95 clk.Add(10 * time.Minute) 96 97 // Have new config now! 98 ctx = prepareCfg(ctx, `rules { 99 name: "rule 2" 100 requestor: "user:some-user@example.com" 101 target_service: "service:some-service" 102 allowed_to_impersonate: "group:some-group" 103 allowed_audience: "REQUESTOR" 104 max_validity_duration: 86400 105 }`) 106 107 // Import it. 108 resp, err = rpc.ImportDelegationConfigs(ctx, nil) 109 So(err, ShouldBeNil) 110 So(resp, ShouldResemble, &admin.ImportedConfigs{ 111 Revision: "7826cf5f5d3922ff363a2df0c363df088a81f261", 112 }) 113 114 // It is now active. 115 r, err = rules.Rules(ctx) 116 So(err, ShouldBeNil) 117 So(r.rules[0].rule.Name, ShouldEqual, "rule 2") 118 So(r.revision, ShouldEqual, "7826cf5f5d3922ff363a2df0c363df088a81f261") 119 }) 120 } 121 122 func prepareCfg(c context.Context, configFile string) context.Context { 123 return cfgclient.Use(c, memory.New(map[config.Set]memory.Files{ 124 "services/${appid}": { 125 "delegation.cfg": configFile, 126 }, 127 })) 128 }