@@ -18,7 +18,7 @@ import (
18
18
)
19
19
20
20
// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterroles;clusterrolebindings,verbs=get;list;watch;create;delete;patch;update;edit
21
- // +kubebuilder:rbac:groups=rbac.appuio.io,resources=billingentities,verbs=*
21
+ // +kubebuilder:rbac:groups=rbac.appuio.io;billing.appuio.io ,resources=billingentities,verbs=*
22
22
23
23
// createRBACWrapper is a wrapper around the storage that creates a ClusterRole and ClusterRoleBinding for each BillingEntity on creation.
24
24
type createRBACWrapper struct {
@@ -44,11 +44,10 @@ func (c *createRBACWrapper) Create(ctx context.Context, obj runtime.Object, crea
44
44
return createdObj , fmt .Errorf ("could not get name of created object: %w" , err )
45
45
}
46
46
47
- rolename := fmt .Sprintf ("billingentities-%s-viewer" , objName )
48
-
49
- role := & rbacv1.ClusterRole {
47
+ viewRoleName := fmt .Sprintf ("billingentities-%s-viewer" , objName )
48
+ viewRole := & rbacv1.ClusterRole {
50
49
ObjectMeta : metav1.ObjectMeta {
51
- Name : rolename ,
50
+ Name : viewRoleName ,
52
51
},
53
52
Rules : []rbacv1.PolicyRule {
54
53
{
@@ -59,10 +58,40 @@ func (c *createRBACWrapper) Create(ctx context.Context, obj runtime.Object, crea
59
58
},
60
59
},
61
60
}
62
-
63
- rolebinding := & rbacv1.ClusterRoleBinding {
61
+ viewRoleBinding := & rbacv1.ClusterRoleBinding {
62
+ ObjectMeta : metav1.ObjectMeta {
63
+ Name : viewRoleName ,
64
+ },
65
+ Subjects : []rbacv1.Subject {},
66
+ RoleRef : rbacv1.RoleRef {
67
+ Kind : "ClusterRole" ,
68
+ APIGroup : "rbac.authorization.k8s.io" ,
69
+ Name : viewRoleName ,
70
+ },
71
+ }
72
+ adminRoleName := fmt .Sprintf ("billingentities-%s-admin" , objName )
73
+ adminRole := & rbacv1.ClusterRole {
74
+ ObjectMeta : metav1.ObjectMeta {
75
+ Name : adminRoleName ,
76
+ },
77
+ Rules : []rbacv1.PolicyRule {
78
+ {
79
+ APIGroups : []string {"rbac.appuio.io" , "billing.appuio.io" },
80
+ Resources : []string {"billingentities" },
81
+ Verbs : []string {"get" , "patch" , "update" , "edit" },
82
+ ResourceNames : []string {objName },
83
+ },
84
+ {
85
+ APIGroups : []string {"rbac.authorization.k8s.io" },
86
+ Resources : []string {"clusterrolebindings" },
87
+ Verbs : []string {"get" , "edit" , "update" , "patch" },
88
+ ResourceNames : []string {viewRoleName , adminRoleName },
89
+ },
90
+ },
91
+ }
92
+ adminRoleBinding := & rbacv1.ClusterRoleBinding {
64
93
ObjectMeta : metav1.ObjectMeta {
65
- Name : rolename ,
94
+ Name : adminRoleName ,
66
95
},
67
96
Subjects : []rbacv1.Subject {
68
97
{
@@ -74,7 +103,7 @@ func (c *createRBACWrapper) Create(ctx context.Context, obj runtime.Object, crea
74
103
RoleRef : rbacv1.RoleRef {
75
104
Kind : "ClusterRole" ,
76
105
APIGroup : "rbac.authorization.k8s.io" ,
77
- Name : rolename ,
106
+ Name : adminRoleName ,
78
107
},
79
108
}
80
109
@@ -87,16 +116,21 @@ func (c *createRBACWrapper) Create(ctx context.Context, obj runtime.Object, crea
87
116
return nil
88
117
}
89
118
90
- err = c .client .Create (ctx , role , & client.CreateOptions {DryRun : opts .DryRun })
91
- if err != nil {
92
- rollbackErr := rollback ()
93
- return createdObj , multierr .Append (err , rollbackErr )
119
+ toCreate := []client.Object {viewRole , viewRoleBinding , adminRole , adminRoleBinding }
120
+ created := make ([]client.Object , 0 , len (toCreate ))
121
+ var createErr error
122
+ for _ , obj := range toCreate {
123
+ if err := c .client .Create (ctx , obj , & client.CreateOptions {DryRun : opts .DryRun }); err != nil {
124
+ createErr = err
125
+ break
126
+ }
127
+ created = append (created , obj )
94
128
}
95
- err = c . client . Create ( ctx , rolebinding , & client. CreateOptions { DryRun : opts . DryRun })
96
- if err != nil {
97
- rollbackErr := rollback ( )
98
- roleRollbackErr := c . client . Delete ( ctx , role , & client. DeleteOptions { DryRun : opts . DryRun })
99
- return createdObj , multierr .Combine (err , rollbackErr , roleRollbackErr )
129
+ if err := createErr ; err != nil {
130
+ for _ , obj := range created {
131
+ multierr . AppendInto ( & err , c . client . Delete ( ctx , obj , & client. DeleteOptions { DryRun : opts . DryRun }) )
132
+ }
133
+ return createdObj , multierr .Combine (err , rollback () )
100
134
}
101
135
102
136
return createdObj , nil
0 commit comments