Skip to content

Commit 3301e18

Browse files
committed
prevent claim wrong scope @ backend
1 parent 72d8140 commit 3301e18

12 files changed

Lines changed: 182 additions & 28 deletions

File tree

backend/controllers/clusterbinding/clusterbinding_reconcile.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,15 @@ func (r *reconciler) ensureRBACClusterRole(ctx context.Context, client client.Cl
150150
},
151151
},
152152
},
153-
}
153+
Rules: []rbacv1.PolicyRule{
154+
// Always need to be able to get/list/watch the BoundSchemas
155+
// to be able to figure out what to bind.
156+
{
157+
APIGroups: []string{kubebindv1alpha2.GroupName},
158+
Resources: []string{"boundschemas"},
159+
Verbs: []string{"get", "list", "watch"},
160+
},
161+
}}
154162
for _, export := range exports {
155163
// Collect unique GroupResources and sort for stable rule ordering.
156164
grSet := map[string]kubebindv1alpha2.GroupResource{}
@@ -172,11 +180,6 @@ func (r *reconciler) ensureRBACClusterRole(ctx context.Context, client client.Cl
172180
Resources: []string{schema.Spec.Names.Plural},
173181
Verbs: []string{"get", "list", "watch", "create", "update", "patch", "delete"},
174182
},
175-
rbacv1.PolicyRule{
176-
APIGroups: []string{kubebindv1alpha2.GroupName},
177-
Resources: []string{"boundschemas"},
178-
Verbs: []string{"get", "list", "watch"},
179-
},
180183
)
181184
}
182185
}
@@ -202,7 +205,6 @@ func (r *reconciler) ensureRBACClusterRoleBinding(ctx context.Context, client cl
202205
if err != nil && !errors.IsNotFound(err) {
203206
return fmt.Errorf("failed to get ClusterRoleBinding %s: %w", name, err)
204207
}
205-
206208
if r.scope != kubebindv1alpha2.ClusterScope {
207209
if err := r.deleteClusterRoleBinding(ctx, client, name); err != nil && !errors.IsNotFound(err) {
208210
return fmt.Errorf("failed to delete ClusterRoleBinding %s: %w", name, err)

backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,12 @@ type reconciler struct {
5454

5555
func (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

@@ -119,7 +121,26 @@ func (r *reconciler) ensureBoundSchemas(ctx context.Context, cl client.Client, c
119121
klog.FromContext(ctx).Error(nil, "Skipping invalid schema: missing group or names.plural", "ns", item.GetNamespace(), "name", item.GetName())
120122
continue
121123
}
124+
scope := apiextensionsv1.ResourceScope(spec["scope"].(string))
125+
122126
if g == res.Group && p == res.Resource {
127+
// Important: This checks if the resource are right-scoped. If consumer is namespaced, we can't allow this.
128+
// We terminate early to prevent triggering other controllers.
129+
if r.informerScope.String() != string(scope) && r.informerScope != kubebindv1alpha2.ClusterScope {
130+
conditions.MarkFalse(
131+
req,
132+
kubebindv1alpha2.APIServiceExportRequestConditionExportsReady,
133+
"APIServiceExportRequestInvalid",
134+
conditionsapi.ConditionSeverityError,
135+
"APIServiceExportRequest %s is invalid: resource %s/%s has scope %q which is incompatible with backend informer scope %q",
136+
req.Name, g, p, scope, r.informerScope,
137+
)
138+
req.Status.Phase = kubebindv1alpha2.APIServiceExportRequestPhaseFailed
139+
req.Status.TerminalMessage = conditions.GetMessage(req, kubebindv1alpha2.APIServiceExportRequestConditionExportsReady)
140+
// We can't proceed with this request.
141+
return fmt.Errorf("resource %s/%s has scope %q which is incompatible with backend informer scope %q", g, p, scope, r.informerScope)
142+
}
143+
123144
boundSchema, err := helpers.UnstructuredToBoundSchema(item)
124145
if err != nil {
125146
return err

backend/kubernetes/manager.go

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -192,24 +192,3 @@ func (m *Manager) ListDynamicResources(ctx context.Context, cluster string, gvk
192192

193193
return list, nil
194194
}
195-
196-
/* func (m *Manager) CreateBoundSchema(ctx context.Context, cluster string, name string, u *unstructured.Unstructured) error {
197-
cl, err := m.manager.GetCluster(ctx, cluster)
198-
if err != nil {
199-
return err
200-
}
201-
c := cl.GetClient()
202-
203-
boundSchema := &kubebindv1alpha2.BoundSchema{}
204-
err = runtime.DefaultUnstructuredConverter.FromUnstructured(u.UnstructuredContent(), boundSchema)
205-
if err != nil {
206-
return err
207-
}
208-
209-
boundSchema.ResourceVersion = ""
210-
boundSchema.Name = name
211-
boundSchema.Spec.InformerScope = m.scope
212-
213-
return c.Create(ctx, boundSchema)
214-
}
215-
*/

kcp/deploy/examples/apiexport.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@ spec:
77
- group: wildwest.dev
88
name: cowboys
99
schema: today.cowboys.wildwest.dev
10+
storage:
11+
crd: {}
12+
- group: wildwest.dev
13+
name: sheriffs
14+
schema: today.sheriffs.wildwest.dev
1015
storage:
1116
crd: {}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
apiVersion: apis.kcp.io/v1alpha1
2+
kind: APIResourceSchema
3+
metadata:
4+
name: today.cowboys.wildwest.dev
5+
labels:
6+
kube-bind.io/exported: "true"
7+
spec:
8+
group: wildwest.dev
9+
names:
10+
kind: Cowboy
11+
listKind: CowboyList
12+
plural: cowboys
13+
singular: cowboy
14+
scope: Namespaced
15+
versions:
16+
- name: v1alpha1
17+
schema:
18+
description: Cowboy is part of the wild west
19+
properties:
20+
apiVersion:
21+
description: 'APIVersion defines the versioned schema of this representation
22+
of an object. Servers should convert recognized schemas to the latest
23+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
24+
type: string
25+
kind:
26+
description: 'Kind is a string value representing the REST resource this
27+
object represents. Servers may infer this from the endpoint the client
28+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
29+
type: string
30+
metadata:
31+
type: object
32+
spec:
33+
description: CowboySpec holds the desired state of the Cowboy.
34+
properties:
35+
intent:
36+
type: string
37+
type: object
38+
status:
39+
description: CowboyStatus communicates the observed state of the Cowboy.
40+
properties:
41+
result:
42+
type: string
43+
type: object
44+
type: object
45+
served: true
46+
storage: true
47+
subresources:
48+
status: {}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
apiVersion: apis.kcp.io/v1alpha1
2+
kind: APIResourceSchema
3+
metadata:
4+
name: today.sheriffs.wildwest.dev
5+
labels:
6+
kube-bind.io/exported: "true"
7+
spec:
8+
group: wildwest.dev
9+
names:
10+
kind: Sheriff
11+
listKind: SheriffList
12+
plural: sheriffs
13+
singular: sheriff
14+
scope: Cluster
15+
versions:
16+
- name: v1alpha1
17+
schema:
18+
description: Sheriff is part of the wild west
19+
properties:
20+
apiVersion:
21+
description: 'APIVersion defines the versioned schema of this representation
22+
of an object. Servers should convert recognized schemas to the latest
23+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
24+
type: string
25+
kind:
26+
description: 'Kind is a string value representing the REST resource this
27+
object represents. Servers may infer this from the endpoint the client
28+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
29+
type: string
30+
metadata:
31+
type: object
32+
spec:
33+
description: SheriffSpec holds the desired state of the Sheriff.
34+
properties:
35+
intent:
36+
type: string
37+
type: object
38+
status:
39+
description: SheriffStatus communicates the observed state of the Sheriff.
40+
properties:
41+
result:
42+
type: string
43+
type: object
44+
type: object
45+
served: true
46+
storage: true
47+
subresources:
48+
status: {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: kube-bind.io/v1alpha2
2+
kind: APIServiceExportRequest
3+
metadata:
4+
name: sheriffs.wildwest.dev
5+
spec:
6+
resources:
7+
- group: wildwest.dev
8+
resource: sheriffs
9+
versions:
10+
- v1alpha1
11+
status: {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: kube-bind.io/v1alpha2
2+
kind: APIServiceExportRequest
3+
metadata:
4+
name: cowboys.wildwest.dev
5+
spec:
6+
resources:
7+
- group: wildwest.dev
8+
resource: cowboys
9+
versions:
10+
- v1alpha1
11+
status: {}

kcp/deploy/examples/sheriff.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: wildwest.dev/v1alpha1
2+
kind: Sheriff
3+
metadata:
4+
name: sheriff
5+
spec:
6+
intent: "ride into the sunset"
7+
status:
8+
result: "ready to ride"

pkg/konnector/controllers/cluster/cluster_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ func NewController(
132132
providerConfig,
133133
serviceBindingInformer,
134134
providerBindInformers.KubeBind().V1alpha2().APIServiceExports(),
135+
providerBindInformers.KubeBind().V1alpha2().APIServiceExportRequests(),
135136
crdInformer,
136137
)
137138
if err != nil {

0 commit comments

Comments
 (0)