@@ -54,10 +54,12 @@ type reconciler struct {
5454
5555func (r * reconciler ) reconcile (ctx context.Context , cl client.Client , cache cache.Cache , req * kubebindv1alpha2.APIServiceExportRequest ) error {
5656 if err := r .ensureBoundSchemas (ctx , cl , cache , req ); err != nil {
57+ conditions .SetSummary (req )
5758 return err
5859 }
5960
6061 if err := r .ensureExports (ctx , cl , cache , req ); err != nil {
62+ conditions .SetSummary (req )
6163 return err
6264 }
6365
@@ -75,7 +77,7 @@ func (r *reconciler) ensureBoundSchemas(ctx context.Context, cl client.Client, c
7577 for _ , res := range req .Spec .Resources {
7678 parts := strings .SplitN (r .schemaSource , "." , 3 )
7779 if len (parts ) != 3 { // We check this in validation, but just in case.
78- return fmt .Errorf ("invalid schema source: %q" , r .schemaSource )
80+ return fmt .Errorf ("malformed schema source: %q" , r .schemaSource )
7981 }
8082
8183 gvk := schema.GroupVersionKind {
@@ -107,19 +109,41 @@ func (r *reconciler) ensureBoundSchemas(ctx context.Context, cl client.Client, c
107109
108110 for _ , item := range list .Items {
109111 obj := item .UnstructuredContent ()
110- spec , ok := obj [ "spec" ].( map [ string ] interface {} )
111- if ! ok {
112- klog .FromContext (ctx ).Error (nil , "Skipping invalid schema: missing spec " , "ns" , item .GetNamespace (), "name" , item .GetName ())
112+ group , ok , err := unstructured . NestedString ( obj , "spec" , "group" )
113+ if ! ok || err != nil || group == "" {
114+ klog .FromContext (ctx ).Error (err , "Skipping invalid schema: missing group " , "ns" , item .GetNamespace (), "name" , item .GetName ())
113115 continue
114116 }
115- g , _ := spec ["group" ].(string )
116- names , _ := spec ["names" ].(map [string ]interface {})
117- p , _ := names ["plural" ].(string )
118- if g == "" || p == "" {
119- klog .FromContext (ctx ).Error (nil , "Skipping invalid schema: missing group or names.plural" , "ns" , item .GetNamespace (), "name" , item .GetName ())
117+ plural , ok , err := unstructured .NestedString (obj , "spec" , "names" , "plural" )
118+ if ! ok || err != nil || plural == "" {
119+ klog .FromContext (ctx ).Error (err , "Skipping invalid schema: missing names.plural" , "ns" , item .GetNamespace (), "name" , item .GetName ())
120120 continue
121121 }
122- if g == res .Group && p == res .Resource {
122+
123+ scope , ok , err := unstructured .NestedString (obj , "spec" , "scope" )
124+ if ! ok || err != nil || scope == "" {
125+ klog .FromContext (ctx ).Error (err , "Skipping invalid schema: missing scope" , "ns" , item .GetNamespace (), "name" , item .GetName ())
126+ continue
127+ }
128+
129+ if group == res .Group && plural == res .Resource {
130+ // Important: This checks if the resource are correctly scoped. If consumer is namespaced, we can't allow this.
131+ // We terminate early to prevent triggering other controllers.
132+ if r .informerScope .String () != scope && r .informerScope != kubebindv1alpha2 .ClusterScope {
133+ conditions .MarkFalse (
134+ req ,
135+ kubebindv1alpha2 .APIServiceExportRequestConditionExportsReady ,
136+ "APIServiceExportRequestInvalid" ,
137+ conditionsapi .ConditionSeverityError ,
138+ "APIServiceExportRequest %s is invalid: resource %s/%s has scope %q which is incompatible with backend informer scope %q" ,
139+ req .Name , group , plural , scope , r .informerScope ,
140+ )
141+ req .Status .Phase = kubebindv1alpha2 .APIServiceExportRequestPhaseFailed
142+ req .Status .TerminalMessage = conditions .GetMessage (req , kubebindv1alpha2 .APIServiceExportRequestConditionExportsReady )
143+ // We can't proceed with this request.
144+ return fmt .Errorf ("resource %s/%s has scope %q which is incompatible with backend informer scope %q" , group , plural , scope , r .informerScope )
145+ }
146+
123147 boundSchema , err := helpers .UnstructuredToBoundSchema (item )
124148 if err != nil {
125149 return err
@@ -189,7 +213,10 @@ func (r *reconciler) ensureExports(ctx context.Context, cl client.Client, cache
189213 return nil
190214 }
191215
192- hash := helpers .BoundSchemasSpecHash (schemas )
216+ hash , err := helpers .BoundSchemasSpecHash (schemas )
217+ if err != nil {
218+ return err
219+ }
193220 export := & kubebindv1alpha2.APIServiceExport {
194221 ObjectMeta : metav1.ObjectMeta {
195222 Name : req .Name ,
0 commit comments