@@ -4,8 +4,11 @@ import (
44 "crypto/sha256"
55 "encoding/json"
66 "fmt"
7+ "hash/fnv"
78 "math/big"
89
10+ utilrand "k8s.io/apimachinery/pkg/util/rand"
11+
912 "github.com/operator-framework/api/pkg/operators/v1alpha1"
1013 "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
1114 hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash"
@@ -29,6 +32,16 @@ func generateName(base string, o interface{}) (string, error) {
2932 return fmt .Sprintf ("%s-%s" , base , hash ), nil
3033}
3134
35+ func legacyGenerateName (base string , o interface {}) string {
36+ hasher := fnv .New32a ()
37+ hashutil .LegacyDeepHashObject (hasher , o )
38+ hash := utilrand .SafeEncodeString (fmt .Sprint (hasher .Sum32 ()))
39+ if len (base )+ len (hash ) > maxNameLength {
40+ base = base [:maxNameLength - len (hash )- 1 ]
41+ }
42+ return fmt .Sprintf ("%s-%s" , base , hash )
43+ }
44+
3245type OperatorPermissions struct {
3346 ServiceAccount * corev1.ServiceAccount
3447 Roles []* rbacv1.Role
@@ -233,3 +246,128 @@ func RBACForClusterServiceVersion(csv *v1alpha1.ClusterServiceVersion) (map[stri
233246 }
234247 return permissions , nil
235248}
249+
250+ func LegacyRBACForClusterServiceVersion (csv * v1alpha1.ClusterServiceVersion ) (map [string ]* OperatorPermissions , error ) {
251+ permissions := map [string ]* OperatorPermissions {}
252+
253+ // Use a StrategyResolver to get the strategy details
254+ strategyResolver := install.StrategyResolver {}
255+ strategy , err := strategyResolver .UnmarshalStrategy (csv .Spec .InstallStrategy )
256+ if err != nil {
257+ return nil , err
258+ }
259+
260+ // Assume the strategy is for a deployment
261+ strategyDetailsDeployment , ok := strategy .(* v1alpha1.StrategyDetailsDeployment )
262+ if ! ok {
263+ return nil , fmt .Errorf ("could not assert strategy implementation as deployment for CSV %s" , csv .GetName ())
264+ }
265+
266+ // Resolve Permissions
267+ for _ , permission := range strategyDetailsDeployment .Permissions {
268+ // Create ServiceAccount if necessary
269+ if _ , ok := permissions [permission .ServiceAccountName ]; ! ok {
270+ serviceAccount := & corev1.ServiceAccount {}
271+ serviceAccount .SetNamespace (csv .GetNamespace ())
272+ serviceAccount .SetName (permission .ServiceAccountName )
273+ ownerutil .AddNonBlockingOwner (serviceAccount , csv )
274+
275+ permissions [permission .ServiceAccountName ] = NewOperatorPermissions (serviceAccount )
276+ }
277+
278+ // Create Role
279+ role := & rbacv1.Role {
280+ ObjectMeta : metav1.ObjectMeta {
281+ Name : legacyGenerateName (fmt .Sprintf ("%s-%s" , csv .GetName (), permission .ServiceAccountName ), []interface {}{csv .GetName (), permission }),
282+ Namespace : csv .GetNamespace (),
283+ OwnerReferences : []metav1.OwnerReference {ownerutil .NonBlockingOwner (csv )},
284+ Labels : ownerutil .OwnerLabel (csv , v1alpha1 .ClusterServiceVersionKind ),
285+ },
286+ Rules : permission .Rules ,
287+ }
288+ hash , err := PolicyRuleHashLabelValue (permission .Rules )
289+ if err != nil {
290+ return nil , fmt .Errorf ("failed to hash permission rules: %w" , err )
291+ }
292+ role .Labels [ContentHashLabelKey ] = hash
293+ permissions [permission .ServiceAccountName ].AddRole (role )
294+
295+ // Create RoleBinding
296+ roleBinding := & rbacv1.RoleBinding {
297+ ObjectMeta : metav1.ObjectMeta {
298+ Name : role .GetName (),
299+ Namespace : csv .GetNamespace (),
300+ OwnerReferences : []metav1.OwnerReference {ownerutil .NonBlockingOwner (csv )},
301+ Labels : ownerutil .OwnerLabel (csv , v1alpha1 .ClusterServiceVersionKind ),
302+ },
303+ RoleRef : rbacv1.RoleRef {
304+ Kind : "Role" ,
305+ Name : role .GetName (),
306+ APIGroup : rbacv1 .GroupName },
307+ Subjects : []rbacv1.Subject {{
308+ Kind : "ServiceAccount" ,
309+ Name : permission .ServiceAccountName ,
310+ Namespace : csv .GetNamespace (),
311+ }},
312+ }
313+ hash , err = RoleReferenceAndSubjectHashLabelValue (roleBinding .RoleRef , roleBinding .Subjects )
314+ if err != nil {
315+ return nil , fmt .Errorf ("failed to hash binding content: %w" , err )
316+ }
317+ roleBinding .Labels [ContentHashLabelKey ] = hash
318+ permissions [permission .ServiceAccountName ].AddRoleBinding (roleBinding )
319+ }
320+
321+ // Resolve ClusterPermissions as StepResources
322+ for _ , permission := range strategyDetailsDeployment .ClusterPermissions {
323+ // Create ServiceAccount if necessary
324+ if _ , ok := permissions [permission .ServiceAccountName ]; ! ok {
325+ serviceAccount := & corev1.ServiceAccount {}
326+ ownerutil .AddOwner (serviceAccount , csv , false , false )
327+ serviceAccount .SetName (permission .ServiceAccountName )
328+
329+ permissions [permission .ServiceAccountName ] = NewOperatorPermissions (serviceAccount )
330+ }
331+
332+ // Create ClusterRole
333+ role := & rbacv1.ClusterRole {
334+ ObjectMeta : metav1.ObjectMeta {
335+ Name : legacyGenerateName (csv .GetName (), []interface {}{csv .GetName (), csv .GetNamespace (), permission }),
336+ Labels : ownerutil .OwnerLabel (csv , v1alpha1 .ClusterServiceVersionKind ),
337+ },
338+ Rules : permission .Rules ,
339+ }
340+ hash , err := PolicyRuleHashLabelValue (permission .Rules )
341+ if err != nil {
342+ return nil , fmt .Errorf ("failed to hash permission rules: %w" , err )
343+ }
344+ role .Labels [ContentHashLabelKey ] = hash
345+ permissions [permission .ServiceAccountName ].AddClusterRole (role )
346+
347+ // Create ClusterRoleBinding
348+ roleBinding := & rbacv1.ClusterRoleBinding {
349+ ObjectMeta : metav1.ObjectMeta {
350+ Name : role .GetName (),
351+ Namespace : csv .GetNamespace (),
352+ Labels : ownerutil .OwnerLabel (csv , v1alpha1 .ClusterServiceVersionKind ),
353+ },
354+ RoleRef : rbacv1.RoleRef {
355+ Kind : "ClusterRole" ,
356+ Name : role .GetName (),
357+ APIGroup : rbacv1 .GroupName ,
358+ },
359+ Subjects : []rbacv1.Subject {{
360+ Kind : "ServiceAccount" ,
361+ Name : permission .ServiceAccountName ,
362+ Namespace : csv .GetNamespace (),
363+ }},
364+ }
365+ hash , err = RoleReferenceAndSubjectHashLabelValue (roleBinding .RoleRef , roleBinding .Subjects )
366+ if err != nil {
367+ return nil , fmt .Errorf ("failed to hash binding content: %w" , err )
368+ }
369+ roleBinding .Labels [ContentHashLabelKey ] = hash
370+ permissions [permission .ServiceAccountName ].AddClusterRoleBinding (roleBinding )
371+ }
372+ return permissions , nil
373+ }
0 commit comments