@@ -25,6 +25,8 @@ import (
2525 rbacv1 "k8s.io/api/rbac/v1"
2626 "k8s.io/apimachinery/pkg/api/errors"
2727 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+ "k8s.io/apimachinery/pkg/types"
29+ "k8s.io/klog/v2"
2830 "sigs.k8s.io/controller-runtime/pkg/cache"
2931 "sigs.k8s.io/controller-runtime/pkg/client"
3032
@@ -45,6 +47,7 @@ type reconciler struct {
4547}
4648
4749func (c * reconciler ) reconcile (ctx context.Context , client client.Client , cache cache.Cache , sns * kubebindv1alpha2.APIServiceNamespace ) error {
50+ logger := klog .FromContext (ctx )
4851 var ns * corev1.Namespace
4952 nsName := sns .Namespace + "-" + sns .Name
5053 if sns .Status .Namespace != "" {
@@ -75,6 +78,133 @@ func (c *reconciler) reconcile(ctx context.Context, client client.Client, cache
7578 sns .Status .Namespace = nsName
7679 }
7780
81+ // List APIServiceExports in the namespace
82+ apiServiceExports , err := c .listAPIServiceExports (ctx , cache , sns .Namespace )
83+ if err != nil {
84+ return fmt .Errorf ("failed to list APIServiceExports: %w" , err )
85+ }
86+
87+ for _ , export := range apiServiceExports .Items {
88+ name := "kube-binder-export-" + export .Name // unique name for the service export related permissions
89+ permissions := []rbacv1.PolicyRule {}
90+ for _ , claim := range export .Spec .PermissionClaims {
91+ permissions = append (permissions , rbacv1.PolicyRule {
92+ APIGroups : []string {claim .Group },
93+ Resources : []string {claim .Resource },
94+ // We need list and watch for informers to be able to start. And create to create initial object.
95+ Verbs : []string {"*" },
96+ })
97+
98+ }
99+ if c .scope == kubebindv1alpha2 .ClusterScope {
100+ role , err := c .getPermissionClaimsClusterRole (ctx , cache , name )
101+ if err != nil && ! errors .IsNotFound (err ) {
102+ return fmt .Errorf ("failed to get Role %s: %w" , name , err )
103+ }
104+ if role == nil {
105+ role = & rbacv1.ClusterRole {
106+ ObjectMeta : metav1.ObjectMeta {
107+ Name : name ,
108+ },
109+ Rules : permissions ,
110+ }
111+ // Create new ClusterRole
112+ if err := client .Create (ctx , role ); err != nil {
113+ return fmt .Errorf ("failed to create ClusterRole %s: %w" , name , err )
114+ }
115+ } else {
116+ role .Rules = permissions
117+ if err := client .Update (ctx , role ); err != nil {
118+ return fmt .Errorf ("failed to update ClusterRole %s: %w" , name , err )
119+ }
120+ }
121+
122+ clusterBinding , err := c .getPermissionClaimsClusterRoleBinding (ctx , cache , name )
123+ if err != nil && ! errors .IsNotFound (err ) {
124+ return fmt .Errorf ("failed to get ClusterRoleBinding %s: %w" , name , err )
125+ }
126+ if clusterBinding == nil {
127+ clusterBinding = & rbacv1.ClusterRoleBinding {
128+ ObjectMeta : metav1.ObjectMeta {
129+ Name : name ,
130+ },
131+ Subjects : []rbacv1.Subject {
132+ {
133+ Kind : "ServiceAccount" ,
134+ Namespace : sns .Namespace ,
135+ Name : kuberesources .ServiceAccountName ,
136+ },
137+ },
138+ RoleRef : rbacv1.RoleRef {
139+ Kind : "ClusterRole" ,
140+ Name : name ,
141+ APIGroup : "rbac.authorization.k8s.io" ,
142+ },
143+ }
144+ if err := client .Create (ctx , clusterBinding ); err != nil {
145+ return fmt .Errorf ("failed to create ClusterRoleBinding %s: %w" , name , err )
146+ }
147+ } else {
148+ logger .Info ("ClusterRoleBinding already exists, update not implemented." , "name" , name )
149+ }
150+
151+ } else {
152+ role , err := c .getPermissionClaimsRole (ctx , cache , sns .Status .Namespace , name )
153+ if err != nil && ! errors .IsNotFound (err ) {
154+ return fmt .Errorf ("failed to get Role %s: %w" , name , err )
155+ }
156+ if role == nil {
157+ role := & rbacv1.Role {
158+ ObjectMeta : metav1.ObjectMeta {
159+ Name : name ,
160+ Namespace : sns .Status .Namespace ,
161+ },
162+ Rules : permissions ,
163+ }
164+ // Create new Role
165+ if err := client .Create (ctx , role ); err != nil {
166+ return fmt .Errorf ("failed to create Role %s: %w" , name , err )
167+ }
168+ } else {
169+ role .Rules = permissions
170+ if err := client .Update (ctx , role ); err != nil {
171+ return fmt .Errorf ("failed to update Role %s: %w" , name , err )
172+ }
173+ }
174+
175+ rolebinding , err := c .getPermissionClaimsRoleBinding (ctx , cache , sns .Status .Namespace , name )
176+ if err != nil && ! errors .IsNotFound (err ) {
177+ return fmt .Errorf ("failed to get Role %s: %w" , name , err )
178+ }
179+
180+ if rolebinding == nil {
181+ rolebinding := & rbacv1.RoleBinding {
182+ ObjectMeta : metav1.ObjectMeta {
183+ Name : name ,
184+ Namespace : sns .Status .Namespace ,
185+ },
186+ Subjects : []rbacv1.Subject {
187+ {
188+ Kind : "ServiceAccount" ,
189+ Namespace : sns .Namespace ,
190+ Name : kuberesources .ServiceAccountName ,
191+ },
192+ },
193+ RoleRef : rbacv1.RoleRef {
194+ Kind : "Role" ,
195+ Name : name ,
196+ APIGroup : "rbac.authorization.k8s.io" ,
197+ },
198+ }
199+ if err := client .Create (ctx , rolebinding ); err != nil {
200+ return fmt .Errorf ("failed to create Role %s: %w" , name , err )
201+ }
202+ } else {
203+ logger .Info ("Role already exists, update not implemented." , "name" , name )
204+ }
205+ }
206+ }
207+
78208 return nil
79209}
80210
@@ -119,3 +249,47 @@ func (c *reconciler) ensureRBACRoleBinding(ctx context.Context, client client.Cl
119249
120250 return nil
121251}
252+
253+ func (r * reconciler ) getPermissionClaimsClusterRole (ctx context.Context , cache cache.Cache , name string ) (* rbacv1.ClusterRole , error ) {
254+ var role rbacv1.ClusterRole
255+ key := types.NamespacedName {Name : name }
256+ if err := cache .Get (ctx , key , & role ); err != nil {
257+ return nil , err
258+ }
259+ return & role , nil
260+ }
261+
262+ func (r * reconciler ) getPermissionClaimsRole (ctx context.Context , cache cache.Cache , namespace , name string ) (* rbacv1.Role , error ) {
263+ var role rbacv1.Role
264+ key := types.NamespacedName {Namespace : namespace , Name : name }
265+ if err := cache .Get (ctx , key , & role ); err != nil {
266+ return nil , err
267+ }
268+ return & role , nil
269+ }
270+
271+ func (r * reconciler ) getPermissionClaimsClusterRoleBinding (ctx context.Context , cache cache.Cache , name string ) (* rbacv1.ClusterRoleBinding , error ) {
272+ var roleBinding rbacv1.ClusterRoleBinding
273+ key := types.NamespacedName {Name : name }
274+ if err := cache .Get (ctx , key , & roleBinding ); err != nil {
275+ return nil , err
276+ }
277+ return & roleBinding , nil
278+ }
279+
280+ func (r * reconciler ) getPermissionClaimsRoleBinding (ctx context.Context , cache cache.Cache , namespace , name string ) (* rbacv1.RoleBinding , error ) {
281+ var roleBinding rbacv1.RoleBinding
282+ key := types.NamespacedName {Name : name , Namespace : namespace }
283+ if err := cache .Get (ctx , key , & roleBinding ); err != nil {
284+ return nil , err
285+ }
286+ return & roleBinding , nil
287+ }
288+
289+ func (r * reconciler ) listAPIServiceExports (ctx context.Context , cache cache.Cache , namespace string ) (* kubebindv1alpha2.APIServiceExportList , error ) {
290+ exports := & kubebindv1alpha2.APIServiceExportList {}
291+ if err := cache .List (ctx , exports , client .InNamespace (namespace )); err != nil {
292+ return nil , err
293+ }
294+ return exports , nil
295+ }
0 commit comments