Skip to content

Commit cc45bdd

Browse files
committed
validate APIServiceExportRequest permission claims via CEL
Signed-off-by: olalekan odukoya <odukoyaonline@gmail.com>
1 parent 73c7af1 commit cc45bdd

6 files changed

Lines changed: 19 additions & 55 deletions

File tree

backend/controllers/serviceexportrequest/serviceexportrequest_reconcile.go

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,7 @@ func (r *reconciler) ensureExports(ctx context.Context, cl client.Client, existi
319319
}
320320

321321
// Validate validates if the APIServiceExportRequest is in a valid state.
322-
// Currently it validates if all requested schemas are of the same scope and
323-
// if claimable apis are allowed and valid.
324-
//
325-
// TODO: Move this to validatingAdmissionWebhook as this is not really part of reconciliation.
326-
// https://github.com/kube-bind/kube-bind/issues/325
322+
// Currently it validates if all requested schemas are of the same scope.
327323
func (r *reconciler) validate(ctx context.Context, cl client.Client, req *kubebindv1alpha2.APIServiceExportRequest) error {
328324
exportedSchemas, err := r.getExportedSchemas(ctx, cl)
329325
if err != nil {
@@ -371,56 +367,9 @@ func (r *reconciler) validate(ctx context.Context, cl client.Client, req *kubebi
371367
}
372368
}
373369

374-
// Add validation if claimable apis are valid here
375-
for _, claim := range req.Spec.PermissionClaims {
376-
if !isClaimableAPI(claim) {
377-
conditions.MarkFalse(
378-
req,
379-
kubebindv1alpha2.APIServiceExportConditionPermissionClaim,
380-
"InvalidPermissionClaim",
381-
conditionsapi.ConditionSeverityError,
382-
"Resource %s is not a valid claimable API",
383-
claim.GroupResource.String(),
384-
)
385-
req.Status.Phase = kubebindv1alpha2.APIServiceExportRequestPhaseFailed
386-
req.Status.TerminalMessage = conditions.GetMessage(req, kubebindv1alpha2.APIServiceExportConditionPermissionClaim)
387-
return fmt.Errorf("resource %s is not a valid claimable API", claim.GroupResource.String())
388-
}
389-
}
390-
391-
// Add validation for duplicate group/resource combinations
392-
seenGroupResources := make(map[string]bool)
393-
for _, claim := range req.Spec.PermissionClaims {
394-
key := claim.Group + "/" + claim.Resource
395-
if seenGroupResources[key] {
396-
conditions.MarkFalse(
397-
req,
398-
kubebindv1alpha2.APIServiceExportConditionPermissionClaim,
399-
"DuplicatePermissionClaim",
400-
conditionsapi.ConditionSeverityError,
401-
"Duplicate permission claim found for group/resource %s",
402-
claim.GroupResource.String(),
403-
)
404-
req.Status.Phase = kubebindv1alpha2.APIServiceExportRequestPhaseFailed
405-
req.Status.TerminalMessage = conditions.GetMessage(req, kubebindv1alpha2.APIServiceExportConditionPermissionClaim)
406-
return fmt.Errorf("duplicate permission claim found for group/resource %s", claim.GroupResource.String())
407-
}
408-
seenGroupResources[key] = true
409-
}
410-
411370
return nil
412371
}
413372

414-
// isClaimableAPI checks if a permission claim is for a claimable API.
415-
func isClaimableAPI(claim kubebindv1alpha2.PermissionClaim) bool {
416-
for _, api := range kubebindv1alpha2.ClaimableAPIs {
417-
if claim.Group == api.GroupVersionResource.Group && claim.Resource == api.Names.Plural {
418-
return true
419-
}
420-
}
421-
return false
422-
}
423-
424373
func (r *reconciler) ensureAPIServiceNamespaces(ctx context.Context, cl client.Client, cache cache.Cache, req *kubebindv1alpha2.APIServiceExportRequest) error {
425374
logger := klog.FromContext(ctx)
426375

contrib/kcp/deploy/resources/apiexport-kube-bind.io.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ spec:
6666
crd: {}
6767
- group: kube-bind.io
6868
name: apiserviceexportrequests
69-
schema: v260220-f03e1ee.apiserviceexportrequests.kube-bind.io
69+
schema: v260608-edcd0b51.apiserviceexportrequests.kube-bind.io
7070
storage:
7171
crd: {}
7272
- group: kube-bind.io

contrib/kcp/deploy/resources/apiresourceschema-apiserviceexportrequests.kube-bind.io.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: apis.kcp.io/v1alpha1
22
kind: APIResourceSchema
33
metadata:
4-
name: v260220-f03e1ee.apiserviceexportrequests.kube-bind.io
4+
name: v260608-edcd0b51.apiserviceexportrequests.kube-bind.io
55
spec:
66
conversion:
77
strategy: None
@@ -384,6 +384,10 @@ spec:
384384
x-kubernetes-validations:
385385
- message: permissionClaims are immutable
386386
rule: self == oldSelf
387+
- message: Resource is not a valid claimable API
388+
rule: self.all(c, (c.group == '' && c.resource == 'configmaps') ||
389+
(c.group == '' && c.resource == 'secrets') || (c.group == '' &&
390+
c.resource == 'serviceaccounts'))
387391
resources:
388392
description: resources is a list of resources that should be exported.
389393
items:

deploy/charts/backend/crds/kube-bind.io_apiserviceexportrequests.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,10 @@ spec:
388388
x-kubernetes-validations:
389389
- message: permissionClaims are immutable
390390
rule: self == oldSelf
391+
- message: Resource is not a valid claimable API
392+
rule: self.all(c, (c.group == '' && c.resource == 'configmaps')
393+
|| (c.group == '' && c.resource == 'secrets') || (c.group == ''
394+
&& c.resource == 'serviceaccounts'))
391395
resources:
392396
description: resources is a list of resources that should be exported.
393397
items:

deploy/crd/kube-bind.io_apiserviceexportrequests.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,10 @@ spec:
389389
x-kubernetes-validations:
390390
- message: permissionClaims are immutable
391391
rule: self == oldSelf
392+
- message: Resource is not a valid claimable API
393+
rule: self.all(c, (c.group == '' && c.resource == 'configmaps')
394+
|| (c.group == '' && c.resource == 'secrets') || (c.group == ''
395+
&& c.resource == 'serviceaccounts'))
392396
resources:
393397
description: resources is a list of resources that should be exported.
394398
items:

sdk/apis/kubebind/v1alpha2/apiserviceexportrequest_types.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,11 @@ type APIServiceExportRequestSpec struct {
114114
// Access is granted per GroupResource.
115115
//
116116
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="permissionClaims are immutable"
117+
// +kubebuilder:validation:XListType=map
118+
// +kubebuilder:validation:XListMapKey=resource
119+
// +kubebuilder:validation:XListMapKey=group
120+
// +kubebuilder:validation:XValidation:rule="self.all(c, (c.group == '' && c.resource == 'configmaps') || (c.group == '' && c.resource == 'secrets') || (c.group == '' && c.resource == 'serviceaccounts'))",message="Resource is not a valid claimable API"
117121
PermissionClaims []PermissionClaim `json:"permissionClaims,omitempty"`
118-
119122
// namespaces specifies the namespaces to bootstrap as part of this request.
120123
// When objects originate from provider side, the consumer does not always know the necessary details.
121124
// This field allows provider to pre-heat the necessary namespaces on provider side by creating

0 commit comments

Comments
 (0)