@@ -17,9 +17,10 @@ package remoteresourceslicecontroller
1717import (
1818 "context"
1919 "fmt"
20+ "strings"
2021
2122 corev1 "k8s.io/api/core/v1"
22- "k8s.io/apimachinery/pkg/api/errors"
23+ kerrors "k8s.io/apimachinery/pkg/api/errors"
2324 "k8s.io/apimachinery/pkg/api/resource"
2425 "k8s.io/apimachinery/pkg/runtime"
2526 "k8s.io/apimachinery/pkg/types"
@@ -98,7 +99,7 @@ type RemoteResourceSliceReconciler struct {
9899func (r * RemoteResourceSliceReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (res ctrl.Result , err error ) {
99100 var resourceSlice authv1beta1.ResourceSlice
100101 if err = r .Get (ctx , req .NamespacedName , & resourceSlice ); err != nil {
101- if errors .IsNotFound (err ) {
102+ if kerrors .IsNotFound (err ) {
102103 klog .V (4 ).Infof ("resourceSlice %q not found" , req .NamespacedName )
103104 return ctrl.Result {}, nil
104105 }
@@ -135,6 +136,19 @@ func (r *RemoteResourceSliceReconciler) Reconcile(ctx context.Context, req ctrl.
135136 }
136137 }()
137138
139+ // Make sure that the resource slice has been created in the tentant namespace dedicated to the current consumer
140+ err = validateRSNamespace (ctx , r .Client , req .Namespace , string (* resourceSlice .Spec .ConsumerClusterID ))
141+ switch {
142+ case kerrors .IsBadRequest (err ):
143+ klog .Errorf ("Invalid ResourceSlice %q provided: %s" , req .NamespacedName , err )
144+ r .eventRecorder .Event (& resourceSlice , corev1 .EventTypeWarning , "Invalid ResourceSlice" , err .Error ())
145+ denyAuthentication (& resourceSlice , r .eventRecorder )
146+ return ctrl.Result {}, nil
147+ case err != nil :
148+ klog .Errorf ("unable to get tenant Namespace of ResourceSlice %q: %v" , req .NamespacedName , err )
149+ return ctrl.Result {}, err
150+ }
151+
138152 // Handle the ResourceSlice authentication status
139153 if err = r .handleAuthenticationStatus (ctx , & resourceSlice , tenant ); err != nil {
140154 return ctrl.Result {}, err
@@ -389,3 +403,23 @@ func isInResourceClasses(resourceSlice *authv1beta1.ResourceSlice, classes ...au
389403 }
390404 return false
391405}
406+
407+ // validateRSNamespace makes sure that the ResourceSlice has been created in the tenant namespace dedicated to the consumer cluster.
408+ func validateRSNamespace (ctx context.Context , c client.Client , namespace , consumerClusterID string ) error {
409+ var tenantNamespace corev1.Namespace
410+ if err := c .Get (ctx , types.NamespacedName {Name : namespace }, & tenantNamespace ); err != nil {
411+ return err
412+ }
413+
414+ if tenantLabel , labelPresent := tenantNamespace .Labels [consts .TenantNamespaceLabel ]; ! labelPresent || strings .EqualFold (tenantLabel , "false" ) {
415+ return kerrors .NewBadRequest ("A ResourceSlice cannot be created in a namespace different than the Tenant namespace" )
416+ }
417+
418+ if clusterIDLabel , labelPresent := tenantNamespace .Labels [consts .RemoteClusterID ]; ! labelPresent || clusterIDLabel != consumerClusterID {
419+ return kerrors .NewBadRequest (
420+ fmt .Sprintf ("ResourceSlice belonging to %q has been created in the Tenant namespace of %q" , consumerClusterID , clusterIDLabel ),
421+ )
422+ }
423+
424+ return nil
425+ }
0 commit comments