@@ -3,6 +3,7 @@ package olm
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "github.com/google/uuid"
6
7
"hash/fnv"
7
8
"reflect"
8
9
"strings"
@@ -979,33 +980,19 @@ func (a *Operator) updateNamespaceList(op *operatorsv1.OperatorGroup) ([]string,
979
980
}
980
981
981
982
func (a * Operator ) ensureOpGroupClusterRole (op * operatorsv1.OperatorGroup , suffix string , apis cache.APISet ) error {
982
- clusterRole := & rbacv1.ClusterRole {
983
- ObjectMeta : metav1.ObjectMeta {
984
- Name : strings .Join ([]string {op .GetName (), suffix }, "-" ),
985
- },
986
- }
987
- var selectors []metav1.LabelSelector
988
- for api := range apis {
989
- aggregationLabel , err := aggregationLabelFromAPIKey (api , suffix )
990
- if err != nil {
991
- return err
992
- }
993
- selectors = append (selectors , metav1.LabelSelector {
994
- MatchLabels : map [string ]string {
995
- aggregationLabel : "true" ,
996
- },
997
- })
998
- }
999
- if len (selectors ) > 0 {
1000
- clusterRole .AggregationRule = & rbacv1.AggregationRule {
1001
- ClusterRoleSelectors : selectors ,
1002
- }
983
+ clusterRole , err := a .getOpGroupClusterRole (op , suffix )
984
+ if err != nil {
985
+ return err
1003
986
}
1004
- err := ownerutil . AddOwnerLabels ( clusterRole , op )
987
+ clusterRole . AggregationRule , err = a . getClusterRoleAggregationRule ( apis , suffix )
1005
988
if err != nil {
1006
989
return err
1007
990
}
1008
991
992
+ if err := ownerutil .AddOwnerLabels (clusterRole , op ); err != nil {
993
+ return err
994
+ }
995
+
1009
996
existingRole , err := a .lister .RbacV1 ().ClusterRoleLister ().Get (clusterRole .Name )
1010
997
if err != nil && ! apierrors .IsNotFound (err ) {
1011
998
return err
@@ -1032,6 +1019,86 @@ func (a *Operator) ensureOpGroupClusterRole(op *operatorsv1.OperatorGroup, suffi
1032
1019
return nil
1033
1020
}
1034
1021
1022
+ func hash (str string ) (string , error ) {
1023
+ // hash the string with some randomness to help avoid guessing attacks
1024
+ h := fnv .New32a ()
1025
+ rnd := uuid .NewString ()
1026
+ if _ , err := h .Write ([]byte (fmt .Sprintf ("%s.%s" , rnd , str ))); err != nil {
1027
+ return "" , err
1028
+ }
1029
+ return strings .Trim (fmt .Sprintf ("%016x" , h .Sum32 ()), "0" ), nil
1030
+ }
1031
+
1032
+ func (a * Operator ) getOpGroupClusterRole (op * operatorsv1.OperatorGroup , suffix string ) (* rbacv1.ClusterRole , error ) {
1033
+ roleNameHash , err := hash (fmt .Sprintf ("%s/%s" , op .GetNamespace (), op .GetName ()))
1034
+ if err != nil {
1035
+ return nil , err
1036
+ }
1037
+ roleName := fmt .Sprintf ("olm.operator-group.role.%s.%s" , roleNameHash , suffix )
1038
+
1039
+ clusterRole := & rbacv1.ClusterRole {
1040
+ ObjectMeta : metav1.ObjectMeta {
1041
+ Name : roleName ,
1042
+ },
1043
+ }
1044
+ return clusterRole , nil
1045
+ }
1046
+
1047
+ func (a * Operator ) getOldClusterRole (op * operatorsv1.OperatorGroup , suffix string ) (* rbacv1.ClusterRole , error ) {
1048
+ // check if old role name exists
1049
+ roles , err := a .lister .RbacV1 ().ClusterRoleLister ().List (ownerutil .ClusterRoleSelector (op ))
1050
+ if err != nil && ! apierrors .IsNotFound (err ) {
1051
+ return nil , err
1052
+ }
1053
+ var suffixRoles []* rbacv1.ClusterRole
1054
+ for idx , _ := range roles {
1055
+ role := roles [idx ]
1056
+ if strings .HasSuffix (role .GetName (), suffix ) {
1057
+ suffixRoles = append (suffixRoles , role )
1058
+ }
1059
+ }
1060
+ // todo: finding multiple owned cluster roles with the same suffix is highly unlikely to happen. However,
1061
+ // we need to test and document the manual clean up in case it ever happens
1062
+ if len (suffixRoles ) > 1 {
1063
+ err := fmt .Errorf ("found multiple cluster roles with suffix %s, please clean up manually" , suffix )
1064
+ a .logger .Error (err )
1065
+ return nil , err
1066
+ }
1067
+ return suffixRoles [0 ].DeepCopy (), nil
1068
+ }
1069
+
1070
+ func (a * Operator ) getClusterRoleAggregationRule (apis cache.APISet , suffix string ) (* rbacv1.AggregationRule , error ) {
1071
+ var selectors []metav1.LabelSelector
1072
+ for api := range apis {
1073
+ aggregationLabel , err := aggregationLabelFromAPIKey (api , suffix )
1074
+ if err != nil {
1075
+ return nil , err
1076
+ }
1077
+ selectors = append (selectors , metav1.LabelSelector {
1078
+ MatchLabels : map [string ]string {
1079
+ aggregationLabel : "true" ,
1080
+ },
1081
+ })
1082
+ }
1083
+ if len (selectors ) > 0 {
1084
+ return & rbacv1.AggregationRule {
1085
+ ClusterRoleSelectors : selectors ,
1086
+ }, nil
1087
+ }
1088
+ return nil , nil
1089
+ }
1090
+
1091
+ func (a * Operator ) clusterRoleExistsAndIsOwnedBy (roleName string , owner ownerutil.Owner ) (bool , error ) {
1092
+ role , err := a .lister .RbacV1 ().ClusterRoleLister ().Get (roleName )
1093
+ if err != nil && ! apierrors .IsNotFound (err ) {
1094
+ return false , err
1095
+ }
1096
+ if apierrors .IsNotFound (err ) {
1097
+ return false , nil
1098
+ }
1099
+ return ownerutil .IsOwnedBy (role , owner ), nil
1100
+ }
1101
+
1035
1102
func (a * Operator ) ensureOpGroupClusterRoles (op * operatorsv1.OperatorGroup , apis cache.APISet ) error {
1036
1103
for _ , suffix := range Suffices {
1037
1104
if err := a .ensureOpGroupClusterRole (op , suffix , apis ); err != nil {
0 commit comments