@@ -19,15 +19,14 @@ import (
19
19
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
20
20
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver"
21
21
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
22
+ "github.com/operator-framework/operator-registry/pkg/registry"
22
23
opregistry "github.com/operator-framework/operator-registry/pkg/registry"
23
24
)
24
25
25
26
const (
26
- operatorGroupAggregrationKeyPrefix = "olm.opgroup.permissions/aggregate-to-"
27
- kubeRBACAggregationKeyPrefix = "rbac.authorization.k8s.io/aggregate-to-"
28
- AdminSuffix = "admin"
29
- EditSuffix = "edit"
30
- ViewSuffix = "view"
27
+ AdminSuffix = "admin"
28
+ EditSuffix = "edit"
29
+ ViewSuffix = "view"
31
30
)
32
31
33
32
var (
42
41
}
43
42
)
44
43
44
+ func aggregationLabelFromAPIKey (k opregistry.APIKey , suffix string ) (string , error ) {
45
+ hash , err := resolver .APIKeyToGVKHash (k )
46
+ if err != nil {
47
+ return "" , err
48
+ }
49
+ return fmt .Sprintf ("olm.opgroup.permissions/aggregate-to-%s-%s" , hash , suffix ), nil
50
+ }
51
+
45
52
func (a * Operator ) syncOperatorGroups (obj interface {}) error {
46
53
op , ok := obj .(* v1.OperatorGroup )
47
54
if ! ok {
@@ -115,12 +122,6 @@ func (a *Operator) syncOperatorGroups(obj interface{}) error {
115
122
}
116
123
logger .Debug ("OperatorGroup CSV annotation completed" )
117
124
118
- if err := a .ensureOpGroupClusterRoles (op ); err != nil {
119
- logger .WithError (err ).Warn ("failed to ensure operatorgroup clusterroles" )
120
- return err
121
- }
122
- logger .Debug ("operatorgroup clusterroles ensured" )
123
-
124
125
// Requeue all CSVs that provide the same APIs (including those removed). This notifies conflicting CSVs in
125
126
// intersecting groups that their conflict has possibly been resolved, either through resizing or through
126
127
// deletion of the conflicting CSV.
@@ -135,6 +136,12 @@ func (a *Operator) syncOperatorGroups(obj interface{}) error {
135
136
providedAPIsForGroup [api ] = struct {}{}
136
137
}
137
138
139
+ if err := a .ensureOpGroupClusterRoles (op , providedAPIsForGroup ); err != nil {
140
+ logger .WithError (err ).Warn ("failed to ensure operatorgroup clusterroles" )
141
+ return err
142
+ }
143
+ logger .Debug ("operatorgroup clusterroles ensured" )
144
+
138
145
csvs , err := a .findCSVsThatProvideAnyOf (providedAPIsForGroup )
139
146
if err != nil {
140
147
logger .WithError (err ).Warn ("could not find csvs that provide group apis" )
@@ -295,32 +302,43 @@ func (a *Operator) pruneProvidedAPIs(group *v1.OperatorGroup, groupProvidedAPIs
295
302
}
296
303
297
304
// ensureProvidedAPIClusterRole ensures that a clusterrole exists (admin, edit, or view) for a single provided API Type
298
- func (a * Operator ) ensureProvidedAPIClusterRole (operatorGroup * v1.OperatorGroup , csv * v1alpha1.ClusterServiceVersion , namePrefix , suffix string , verbs []string , group , resource string , resourceNames []string ) error {
305
+ func (a * Operator ) ensureProvidedAPIClusterRole (operatorGroup * v1.OperatorGroup , csv * v1alpha1.ClusterServiceVersion , namePrefix , suffix string , verbs []string , group , resource string , resourceNames []string , api ownerutil.Owner , key opregistry.APIKey ) error {
306
+ aggregationLabel , err := aggregationLabelFromAPIKey (key , suffix )
307
+ if err != nil {
308
+ return err
309
+ }
299
310
clusterRole := & rbacv1.ClusterRole {
300
311
ObjectMeta : metav1.ObjectMeta {
301
312
Name : namePrefix + suffix ,
302
313
Labels : map [string ]string {
303
- kubeRBACAggregationKeyPrefix + suffix : "true" ,
304
- operatorGroupAggregrationKeyPrefix + suffix : operatorGroup .GetName (),
314
+ // Matches aggregation rules on the bootstrap ClusterRoles.
315
+ // https://github.com/kubernetes/kubernetes/blob/61847eab61788fb0543b4cf147773c9da646ed2f/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go#L232
316
+ fmt .Sprintf ("rbac.authorization.k8s.io/aggregate-to-%s" , suffix ): "true" ,
317
+ aggregationLabel : "true" ,
305
318
},
319
+ OwnerReferences : []metav1.OwnerReference {ownerutil .NonBlockingOwner (api )},
306
320
},
307
321
Rules : []rbacv1.PolicyRule {{Verbs : verbs , APIGroups : []string {group }, Resources : []string {resource }, ResourceNames : resourceNames }},
308
322
}
309
- err := ownerutil .AddOwnerLabels (clusterRole , csv )
310
- if err != nil {
311
- return err
312
- }
313
- existingCR , err := a .opClient .KubernetesInterface ().RbacV1 ().ClusterRoles ().Create (clusterRole )
314
- if k8serrors .IsAlreadyExists (err ) {
315
- if existingCR != nil && reflect .DeepEqual (existingCR .Labels , clusterRole .Labels ) && reflect .DeepEqual (existingCR .Rules , clusterRole .Rules ) {
323
+
324
+ existingCR , err := a .lister .RbacV1 ().ClusterRoleLister ().Get (clusterRole .Name )
325
+ if existingCR == nil {
326
+ existingCR , err = a .opClient .KubernetesInterface ().RbacV1 ().ClusterRoles ().Create (clusterRole )
327
+ if err == nil {
316
328
return nil
317
329
}
318
- if _ , err = a . opClient . UpdateClusterRole ( clusterRole ); err != nil {
319
- a .logger .WithError (err ).Errorf ("Update existing cluster role failed: %v" , clusterRole )
330
+ if ! k8serrors . IsAlreadyExists ( err ) {
331
+ a .logger .WithError (err ).Errorf ("Create cluster role failed: %v" , clusterRole )
320
332
return err
321
333
}
322
- } else if err != nil {
323
- a .logger .WithError (err ).Errorf ("Create cluster role failed: %v" , clusterRole )
334
+ }
335
+
336
+ if existingCR != nil && reflect .DeepEqual (existingCR .Rules , clusterRole .Rules ) && ownerutil .IsOwnedBy (existingCR , api ) && labels .Equals (existingCR .Labels , clusterRole .Labels ) {
337
+ return nil
338
+ }
339
+
340
+ if _ , err := a .opClient .UpdateClusterRole (clusterRole ); err != nil {
341
+ a .logger .WithError (err ).Errorf ("Update existing cluster role failed: %v" , clusterRole )
324
342
return err
325
343
}
326
344
return nil
@@ -329,27 +347,37 @@ func (a *Operator) ensureProvidedAPIClusterRole(operatorGroup *v1.OperatorGroup,
329
347
// ensureClusterRolesForCSV ensures that ClusterRoles for writing and reading provided APIs exist for each operator
330
348
func (a * Operator ) ensureClusterRolesForCSV (csv * v1alpha1.ClusterServiceVersion , operatorGroup * v1.OperatorGroup ) error {
331
349
for _ , owned := range csv .Spec .CustomResourceDefinitions .Owned {
350
+ crd , err := a .lister .APIExtensionsV1beta1 ().CustomResourceDefinitionLister ().Get (owned .Name )
351
+ if err != nil {
352
+ return fmt .Errorf ("crd %q not found: %s" , owned .Name , err .Error ())
353
+ }
332
354
nameGroupPair := strings .SplitN (owned .Name , "." , 2 ) // -> etcdclusters etcd.database.coreos.com
333
355
if len (nameGroupPair ) != 2 {
334
356
return fmt .Errorf ("invalid parsing of name '%v', got %v" , owned .Name , nameGroupPair )
335
357
}
336
358
plural := nameGroupPair [0 ]
337
359
group := nameGroupPair [1 ]
338
360
namePrefix := fmt .Sprintf ("%s-%s-" , owned .Name , owned .Version )
339
-
361
+ key := registry. APIKey { Group : group , Version : owned . Version , Kind : owned . Kind , Plural : plural }
340
362
for suffix , verbs := range VerbsForSuffix {
341
- if err := a .ensureProvidedAPIClusterRole (operatorGroup , csv , namePrefix , suffix , verbs , group , plural , nil ); err != nil {
363
+ if err := a .ensureProvidedAPIClusterRole (operatorGroup , csv , namePrefix , suffix , verbs , group , plural , nil , crd , key ); err != nil {
342
364
return err
343
365
}
344
366
}
345
- if err := a .ensureProvidedAPIClusterRole (operatorGroup , csv , namePrefix + "crd" , ViewSuffix , []string {"get" }, "apiextensions.k8s.io" , "customresourcedefinitions" , []string {owned .Name }); err != nil {
367
+ if err := a .ensureProvidedAPIClusterRole (operatorGroup , csv , namePrefix + "crd" , ViewSuffix , []string {"get" }, "apiextensions.k8s.io" , "customresourcedefinitions" , []string {owned .Name }, crd , key ); err != nil {
346
368
return err
347
369
}
348
370
}
349
371
for _ , owned := range csv .Spec .APIServiceDefinitions .Owned {
372
+ svcName := strings .Join ([]string {owned .Version , owned .Group }, "." )
373
+ svc , err := a .lister .APIRegistrationV1 ().APIServiceLister ().Get (svcName )
374
+ if err != nil {
375
+ return fmt .Errorf ("apiservice %q not found: %s" , svcName , err .Error ())
376
+ }
350
377
namePrefix := fmt .Sprintf ("%s-%s-" , owned .Name , owned .Version )
378
+ key := registry.APIKey {Group : owned .Group , Version : owned .Version , Kind : owned .Kind }
351
379
for suffix , verbs := range VerbsForSuffix {
352
- if err := a .ensureProvidedAPIClusterRole (operatorGroup , csv , namePrefix , suffix , verbs , owned .Group , owned .Name , nil ); err != nil {
380
+ if err := a .ensureProvidedAPIClusterRole (operatorGroup , csv , namePrefix , suffix , verbs , owned .Group , owned .Name , nil , svc , key ); err != nil {
353
381
return err
354
382
}
355
383
}
@@ -853,38 +881,60 @@ func (a *Operator) updateNamespaceList(op *v1.OperatorGroup) ([]string, error) {
853
881
return namespaceList , nil
854
882
}
855
883
856
- func (a * Operator ) ensureOpGroupClusterRole (op * v1.OperatorGroup , suffix string ) error {
884
+ func (a * Operator ) ensureOpGroupClusterRole (op * v1.OperatorGroup , suffix string , apis resolver. APISet ) error {
857
885
clusterRole := & rbacv1.ClusterRole {
858
886
ObjectMeta : metav1.ObjectMeta {
859
887
Name : strings .Join ([]string {op .GetName (), suffix }, "-" ),
860
888
},
861
- AggregationRule : & rbacv1.AggregationRule {
862
- ClusterRoleSelectors : []metav1.LabelSelector {
863
- {
864
- MatchLabels : map [string ]string {
865
- operatorGroupAggregrationKeyPrefix + suffix : op .GetName (),
866
- },
867
- },
889
+ }
890
+ var selectors []metav1.LabelSelector
891
+ for api := range apis {
892
+ aggregationLabel , err := aggregationLabelFromAPIKey (api , suffix )
893
+ if err != nil {
894
+ return err
895
+ }
896
+ selectors = append (selectors , metav1.LabelSelector {
897
+ MatchLabels : map [string ]string {
898
+ aggregationLabel : "true" ,
868
899
},
869
- },
900
+ })
901
+ }
902
+ if len (selectors ) > 0 {
903
+ clusterRole .AggregationRule = & rbacv1.AggregationRule {
904
+ ClusterRoleSelectors : selectors ,
905
+ }
870
906
}
871
907
err := ownerutil .AddOwnerLabels (clusterRole , op )
872
908
if err != nil {
873
909
return err
874
910
}
875
- _ , err = a .opClient .KubernetesInterface ().RbacV1 ().ClusterRoles ().Create (clusterRole )
876
- if k8serrors .IsAlreadyExists (err ) {
911
+
912
+ existingRole , err := a .lister .RbacV1 ().ClusterRoleLister ().Get (clusterRole .Name )
913
+ if existingRole == nil {
914
+ existingRole , err = a .opClient .KubernetesInterface ().RbacV1 ().ClusterRoles ().Create (clusterRole )
915
+ if err == nil {
916
+ return nil
917
+ }
918
+ if ! k8serrors .IsAlreadyExists (err ) {
919
+ a .logger .WithError (err ).Errorf ("Create cluster role failed: %v" , clusterRole )
920
+ return err
921
+ }
922
+ }
923
+
924
+ if existingRole != nil && labels .Equals (existingRole .Labels , clusterRole .Labels ) && reflect .DeepEqual (existingRole .AggregationRule , clusterRole .AggregationRule ) {
877
925
return nil
878
- } else if err != nil {
879
- a .logger .WithError (err ).Errorf ("Create cluster role failed: %v" , clusterRole )
926
+ }
927
+
928
+ if _ , err := a .opClient .UpdateClusterRole (clusterRole ); err != nil {
929
+ a .logger .WithError (err ).Errorf ("Update existing cluster role failed: %v" , clusterRole )
880
930
return err
881
931
}
882
932
return nil
883
933
}
884
934
885
- func (a * Operator ) ensureOpGroupClusterRoles (op * v1.OperatorGroup ) error {
935
+ func (a * Operator ) ensureOpGroupClusterRoles (op * v1.OperatorGroup , apis resolver. APISet ) error {
886
936
for _ , suffix := range Suffices {
887
- if err := a .ensureOpGroupClusterRole (op , suffix ); err != nil {
937
+ if err := a .ensureOpGroupClusterRole (op , suffix , apis ); err != nil {
888
938
return err
889
939
}
890
940
}
0 commit comments