@@ -59,26 +59,35 @@ type ScopedPolicyRules struct {
5959
6060var objectVerbs = []string {"get" , "patch" , "update" , "delete" }
6161
62- // Here we are splitting collection verbs based on required scope
63- // NB: this split is tightly coupled to the requirements of the contentmanager, specifically
64- // its need for cluster-scoped list/watch permissions.
65- // TODO: We are accepting this coupling for now, but plan to decouple
66- // TODO: link for above https://github.com/operator-framework/operator-controller/issues/1911
6762var namespacedCollectionVerbs = []string {"create" }
68- var clusterCollectionVerbs = []string {"list" , "watch" }
63+
64+ type RBACPreAuthorizerOption func (* rbacPreAuthorizer )
65+
66+ // WithClusterCollectionVerbs configures cluster-scoped collection verbs (e.g. list, watch)
67+ // that are checked in addition to object and namespaced collection verbs.
68+ func WithClusterCollectionVerbs (verbs ... string ) RBACPreAuthorizerOption {
69+ return func (a * rbacPreAuthorizer ) {
70+ a .clusterCollectionVerbs = verbs
71+ }
72+ }
6973
7074type rbacPreAuthorizer struct {
71- authorizer authorizer.Authorizer
72- ruleResolver validation.AuthorizationRuleResolver
73- restMapper meta.RESTMapper
75+ authorizer authorizer.Authorizer
76+ ruleResolver validation.AuthorizationRuleResolver
77+ restMapper meta.RESTMapper
78+ clusterCollectionVerbs []string
7479}
7580
76- func NewRBACPreAuthorizer (cl client.Client ) PreAuthorizer {
77- return & rbacPreAuthorizer {
81+ func NewRBACPreAuthorizer (cl client.Client , opts ... RBACPreAuthorizerOption ) PreAuthorizer {
82+ a := & rbacPreAuthorizer {
7883 authorizer : newRBACAuthorizer (cl ),
7984 ruleResolver : newRBACRulesResolver (cl ),
8085 restMapper : cl .RESTMapper (),
8186 }
87+ for _ , opt := range opts {
88+ opt (a )
89+ }
90+ return a
8291}
8392
8493func (a * rbacPreAuthorizer ) PreAuthorize (ctx context.Context , user user.Info , manifestReader io.Reader , additionalRequiredPerms ... UserAuthorizerAttributesFactory ) ([]ScopedPolicyRules , error ) {
@@ -88,7 +97,7 @@ func (a *rbacPreAuthorizer) PreAuthorize(ctx context.Context, user user.Info, ma
8897 }
8998
9099 // derive manifest related attributes records
91- attributesRecords := dm .asAuthorizationAttributesRecordsForUser (user )
100+ attributesRecords := dm .asAuthorizationAttributesRecordsForUser (user , a . clusterCollectionVerbs )
92101
93102 // append additional required perms
94103 for _ , fn := range additionalRequiredPerms {
@@ -324,7 +333,7 @@ func (dm *decodedManifest) rbacObjects() []client.Object {
324333 return objects
325334}
326335
327- func (dm * decodedManifest ) asAuthorizationAttributesRecordsForUser (manifestManager user.Info ) []authorizer.AttributesRecord {
336+ func (dm * decodedManifest ) asAuthorizationAttributesRecordsForUser (manifestManager user.Info , clusterCollectionVerbs [] string ) []authorizer.AttributesRecord {
328337 // Calculate initial capacity as an upper-bound estimate:
329338 // - For each key: len(objectVerbs) records (4)
330339 // - For unique namespaces: len(namespacedCollectionVerbs) records (1 per unique namespace across all keys in a GVR)
@@ -369,7 +378,7 @@ func (dm *decodedManifest) asAuthorizationAttributesRecordsForUser(manifestManag
369378 })
370379 }
371380 }
372- // generate records for cluster-scoped collection verbs (list, watch) required by contentmanager
381+ // generate records for cluster-scoped collection verbs (e.g. list, watch)
373382 for _ , v := range clusterCollectionVerbs {
374383 attributeRecords = append (attributeRecords , authorizer.AttributesRecord {
375384 User : manifestManager ,
0 commit comments