Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: tokenserver/appengine/impl/serviceaccounts/config_validation.go

Issue 2997433002: tokenserver: Validate and parse service_accounts.cfg rules. (Closed)
Patch Set: tokenserver: Validate and parse service_accounts.cfg rules. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The LUCI Authors. 1 // Copyright 2017 The LUCI Authors.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 package serviceaccounts 15 package serviceaccounts
16 16
17 import ( 17 import (
18 "fmt"
19 "strings"
20
18 "github.com/luci/luci-go/common/config/validation" 21 "github.com/luci/luci-go/common/config/validation"
22 "github.com/luci/luci-go/common/data/stringset"
23 "github.com/luci/luci-go/server/auth/identity"
19 24
20 "github.com/luci/luci-go/tokenserver/api/admin/v1" 25 "github.com/luci/luci-go/tokenserver/api/admin/v1"
21 "github.com/luci/luci-go/tokenserver/appengine/impl/utils/policy" 26 "github.com/luci/luci-go/tokenserver/appengine/impl/utils/policy"
22 ) 27 )
23 28
24 // validateConfigs validates the structure of configs fetched by fetchConfigs. 29 // validateConfigs validates the structure of configs fetched by fetchConfigs.
25 func validateConfigs(bundle policy.ConfigBundle, ctx *validation.Context) { 30 func validateConfigs(bundle policy.ConfigBundle, ctx *validation.Context) {
26 ctx.SetFile(serviceAccountsCfg) 31 ctx.SetFile(serviceAccountsCfg)
27 cfg, ok := bundle[serviceAccountsCfg].(*admin.ServiceAccountsPermissions ) 32 cfg, ok := bundle[serviceAccountsCfg].(*admin.ServiceAccountsPermissions )
28 if !ok { 33 if !ok {
29 ctx.Error("unexpectedly wrong proto type %T", cfg) 34 ctx.Error("unexpectedly wrong proto type %T", cfg)
30 return 35 return
31 } 36 }
32 37
33 » // TODO(vadimsh): Validate cfg.Rules. 38 » names := stringset.New(0)
39 » accounts := map[string]string{} // service account -> rule name where it s defined
40 » for i, rule := range cfg.Rules {
41 » » // Rule name must be unique. Missing name will be handled by 'va lidateRule'.
42 » » if rule.Name != "" {
43 » » » if names.Has(rule.Name) {
44 » » » » ctx.Error("two rules with identical name %q", ru le.Name)
45 » » » } else {
46 » » » » names.Add(rule.Name)
47 » » » }
48 » » }
49
50 » » // There should be no overlap between service account sets cover ed by each
51 » » // rule.
52 » » for _, account := range rule.ServiceAccount {
53 » » » if name, ok := accounts[account]; ok {
54 » » » » ctx.Error("service account %q is mentioned by mo re than one rule (%q and %q)", account, name, rule.Name)
55 » » » } else {
56 » » » » accounts[account] = rule.Name
57 » » » }
58 » » }
59
60 » » validateRule(fmt.Sprintf("rule #%d: %q", i+1, rule.Name), rule, ctx)
61 » }
34 } 62 }
63
64 // validateRule checks single ServiceAccountRule proto.
65 func validateRule(title string, r *admin.ServiceAccountRule, ctx *validation.Con text) {
66 ctx.Enter(title)
67 defer ctx.Exit()
68
69 if r.Name == "" {
70 ctx.Error(`"name" is required`)
71 }
72
73 // Note: we allow any of the sets to be empty. The rule will just not ma tch
74 // anything in this case, this is fine.
75 validateEmails("service_account", r.ServiceAccount, ctx)
76 validateScopes("allowed_scope", r.AllowedScope, ctx)
77 validateIdSet("end_user", r.EndUser, ctx)
78 validateIdSet("proxy", r.Proxy, ctx)
79
80 if r.MaxGrantValidityDuration != 0 {
81 switch {
82 case r.MaxGrantValidityDuration < 0:
83 ctx.Error(`"max_grant_validity_duration" must be positiv e`)
84 case r.MaxGrantValidityDuration > maxAllowedMaxGrantValidityDura tion:
85 ctx.Error(`"max_grant_validity_duration" must not exceed %d`, maxAllowedMaxGrantValidityDuration)
86 }
87 }
88 }
89
90 func validateEmails(field string, emails []string, ctx *validation.Context) {
91 ctx.Enter("%q", field)
92 defer ctx.Exit()
93 for _, email := range emails {
94 // We reuse 'user:' identity validator, user identities are emai ls too.
95 if _, err := identity.MakeIdentity("user:" + email); err != nil {
96 ctx.Error("bad email %q - %s", email, err)
97 }
98 }
99 }
100
101 func validateScopes(field string, scopes []string, ctx *validation.Context) {
102 ctx.Enter("%q", field)
103 defer ctx.Exit()
104 for _, scope := range scopes {
105 if !strings.HasPrefix(scope, "https://www.googleapis.com/") {
106 ctx.Error("bad scope %q", scope)
107 }
108 }
109 }
110
111 func validateIdSet(field string, ids []string, ctx *validation.Context) {
112 ctx.Enter("%q", field)
113 defer ctx.Exit()
114 for _, entry := range ids {
115 if strings.HasPrefix(entry, "group:") {
116 if entry[len("group:"):] == "" {
117 ctx.Error("bad group entry - no group name")
118 }
119 } else if _, err := identity.MakeIdentity(entry); err != nil {
120 ctx.Error("bad identity %q - %s", entry, err)
121 }
122 }
123 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698