Skip to content

Commit d0d5688

Browse files
ArvindthiruRyan Zhang
andauthored
allow fleet networking CR (#574)
Co-authored-by: Ryan Zhang <zhangryan@microsoft.com>
1 parent cb7ac59 commit d0d5688

File tree

8 files changed

+333
-24
lines changed

8 files changed

+333
-24
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/spf13/cobra v1.7.0
1616
github.com/spf13/pflag v1.0.5
1717
github.com/stretchr/testify v1.8.4
18+
go.goms.io/fleet-networking v0.2.7
1819
go.uber.org/atomic v1.11.0
1920
go.uber.org/zap v1.24.0
2021
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
188188
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
189189
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
190190
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
191+
go.goms.io/fleet-networking v0.2.7 h1:lVs2/GiCjo18BRgACib+VPnENUMh+2YbYXoeNtcAvw0=
192+
go.goms.io/fleet-networking v0.2.7/go.mod h1:JoWG82La5nV29mooOnPpIhy6/Pi4oGXQk21CPF1UStg=
191193
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
192194
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
193195
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=

pkg/webhook/fleetresourcehandler/fleetresourcehandler_webhook.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"regexp"
88
"strings"
99

10+
fleetnetworkingv1alpha1 "go.goms.io/fleet-networking/api/v1alpha1"
1011
admissionv1 "k8s.io/api/admission/v1"
1112
"k8s.io/apimachinery/pkg/runtime"
1213
"k8s.io/apimachinery/pkg/types"
@@ -29,7 +30,6 @@ const (
2930
fleetMemberNamespacePrefix = "fleet-member"
3031
fleetNamespacePrefix = "fleet"
3132
kubeNamespacePrefix = "kube"
32-
handleResourceFmt = "handling %s resource"
3333
)
3434

3535
// Add registers the webhook for K8s built-in object types.
@@ -56,28 +56,31 @@ func (v *fleetResourceValidator) Handle(ctx context.Context, req admission.Reque
5656
if req.Operation == admissionv1.Create || req.Operation == admissionv1.Update || req.Operation == admissionv1.Delete {
5757
switch {
5858
case req.Kind == validation.CRDGVK:
59-
klog.V(2).InfoS("handling CRD resource", "GVK", validation.CRDGVK, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
59+
klog.V(2).InfoS("handling CRD resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
6060
response = v.handleCRD(req)
6161
case req.Kind == validation.V1Alpha1MCGVK:
62-
klog.V(2).InfoS("handling v1alpha1 member cluster resource", "GVK", validation.V1Alpha1MCGVK, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
62+
klog.V(2).InfoS("handling v1alpha1 member cluster resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
6363
response = v.handleV1Alpha1MemberCluster(req)
6464
case req.Kind == validation.MCGVK:
65-
klog.V(2).InfoS("handling member cluster resource", "GVK", validation.MCGVK, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
65+
klog.V(2).InfoS("handling member cluster resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
6666
response = v.handleMemberCluster(req)
6767
case req.Kind == validation.NamespaceGVK:
68-
klog.V(2).InfoS("handling namespace resource", "GVK", validation.NamespaceGVK, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
68+
klog.V(2).InfoS("handling namespace resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
6969
response = v.handleNamespace(req)
7070
case req.Kind == validation.V1Alpha1IMCGVK || req.Kind == validation.V1Alpha1WorkGVK || req.Kind == validation.IMCGVK || req.Kind == validation.WorkGVK:
71-
klog.V(2).InfoS(fmt.Sprintf(handleResourceFmt, req.RequestKind.Kind), "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
71+
klog.V(2).InfoS("handling fleet owned namespaced resource in system namespace", "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
7272
response = v.handleFleetMemberNamespacedResource(ctx, req)
7373
case req.Kind == validation.EventGVK:
74-
klog.V(2).InfoS("handling event resource", "GVK", validation.EventGVK, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
74+
klog.V(3).InfoS("handling event resource", "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
7575
response = v.handleEvent(ctx, req)
76+
case req.Kind.Group == fleetnetworkingv1alpha1.GroupVersion.Group && req.Kind.Version == fleetnetworkingv1alpha1.GroupVersion.Version:
77+
klog.V(2).InfoS("handling fleet networking resource", "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
78+
response = v.handleFleetNetworkingResources(req)
7679
case req.Namespace != "":
77-
klog.V(2).InfoS(fmt.Sprintf(handleResourceFmt, req.RequestKind.Kind), "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
80+
klog.V(2).InfoS("handling namespaced resource created in system namespace", "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
7881
response = validation.ValidateUserForResource(req, v.whiteListedUsers)
7982
default:
80-
klog.V(2).InfoS("resource is not monitored by fleet resource validator webhook", "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
83+
klog.V(3).InfoS("resource is not monitored by fleet resource validator webhook", "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
8184
response = admission.Allowed(fmt.Sprintf("user: %s in groups: %v is allowed to modify resource with GVK: %s", req.UserInfo.Username, req.UserInfo.Groups, req.Kind.String()))
8285
}
8386
}
@@ -141,7 +144,7 @@ func (v *fleetResourceValidator) handleFleetMemberNamespacedResource(ctx context
141144
}
142145
return response
143146
}
144-
klog.InfoS("namespace name doesn't begin with fleet-member prefix so we allow all operations on these namespaces",
147+
klog.V(3).InfoS("namespace name doesn't begin with fleet-member prefix so we allow all operations on these namespaces",
145148
"user", req.UserInfo.Username, "groups", req.UserInfo.Groups, "operation", req.Operation, "kind", req.RequestKind.Kind, "subResource", req.SubResource, "namespacedName", types.NamespacedName{Name: req.Name, Namespace: req.Namespace})
146149
return admission.Allowed("namespace name doesn't begin with fleet-member prefix so we allow all operations on these namespaces for the request object")
147150
}
@@ -152,6 +155,12 @@ func (v *fleetResourceValidator) handleEvent(_ context.Context, _ admission.Requ
152155
return admission.Allowed("all events are allowed")
153156
}
154157

158+
// handleFleetNetworkingResources allows requests to modify fleet networking resources.
159+
func (v *fleetResourceValidator) handleFleetNetworkingResources(_ admission.Request) admission.Response {
160+
// TODO: add more check on the fleet networking resources.
161+
return admission.Allowed("requests for fleet networking resources are all allowed")
162+
}
163+
155164
// handlerNamespace allows/denies request to modify namespace after validation.
156165
func (v *fleetResourceValidator) handleNamespace(req admission.Request) admission.Response {
157166
fleetMatchResult := strings.HasPrefix(req.Name, fleetNamespacePrefix)

pkg/webhook/validation/uservalidation.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func ValidateUserForFleetCRD(req admission.Request, whiteListedUsers []string, g
6060
klog.V(2).InfoS(deniedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
6161
return admission.Denied(fmt.Sprintf(resourceDeniedFormat, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
6262
}
63-
klog.V(2).InfoS(allowedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
63+
klog.V(3).InfoS(allowedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
6464
return admission.Allowed(fmt.Sprintf(resourceAllowedFormat, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
6565
}
6666

@@ -69,7 +69,7 @@ func ValidateUserForResource(req admission.Request, whiteListedUsers []string) a
6969
namespacedName := types.NamespacedName{Name: req.Name, Namespace: req.Namespace}
7070
userInfo := req.UserInfo
7171
if isMasterGroupUserOrWhiteListedUser(whiteListedUsers, userInfo) || isUserAuthenticatedServiceAccount(userInfo) || isUserKubeScheduler(userInfo) || isUserKubeControllerManager(userInfo) || isNodeGroupUser(userInfo) {
72-
klog.V(2).InfoS(allowedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
72+
klog.V(3).InfoS(allowedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
7373
return admission.Allowed(fmt.Sprintf(resourceAllowedFormat, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
7474
}
7575
klog.V(2).InfoS(deniedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
@@ -89,7 +89,7 @@ func ValidateMemberClusterUpdate(currentObj, oldObj client.Object, req admission
8989
}
9090
if (isLabelUpdated || isAnnotationUpdated) && !isObjUpdated {
9191
// we allow any user to modify MemberCluster/Namespace labels/annotations.
92-
klog.V(2).InfoS("user in groups is allowed to modify member cluster labels/annotations", "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
92+
klog.V(3).InfoS("user in groups is allowed to modify member cluster labels/annotations", "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
9393
response = admission.Allowed(fmt.Sprintf(resourceAllowedFormat, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
9494
}
9595
if isObjUpdated {
@@ -184,7 +184,7 @@ func ValidateMCIdentity(ctx context.Context, client client.Client, req admission
184184
var mc fleetv1alpha1.MemberCluster
185185
if err := client.Get(ctx, types.NamespacedName{Name: mcName}, &mc); err != nil {
186186
// fail open, if the webhook cannot get member cluster resources we don't block the request.
187-
klog.V(2).ErrorS(err, fmt.Sprintf("failed to get v1alpha1 member cluster resource for request to modify %+v/%s, allowing request to be handled by api server", req.RequestKind, req.SubResource),
187+
klog.ErrorS(err, fmt.Sprintf("failed to get v1alpha1 member cluster resource for request to modify %+v/%s, allowing request to be handled by api server", req.RequestKind, req.SubResource),
188188
"user", userInfo.Username, "groups", userInfo.Groups, "namespacedName", namespacedName)
189189
return admission.Allowed(fmt.Sprintf(resourceAllowedGetMCFailed, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
190190
}
@@ -193,7 +193,7 @@ func ValidateMCIdentity(ctx context.Context, client client.Client, req admission
193193
var mc clusterv1beta1.MemberCluster
194194
if err := client.Get(ctx, types.NamespacedName{Name: mcName}, &mc); err != nil {
195195
// fail open, if the webhook cannot get member cluster resources we don't block the request.
196-
klog.V(2).ErrorS(err, fmt.Sprintf("failed to get member cluster resource for request to modify %+v/%s, allowing request to be handled by api server", req.RequestKind, req.SubResource),
196+
klog.ErrorS(err, fmt.Sprintf("failed to get member cluster resource for request to modify %+v/%s, allowing request to be handled by api server", req.RequestKind, req.SubResource),
197197
"user", userInfo.Username, "groups", userInfo.Groups, "namespacedName", namespacedName)
198198
return admission.Allowed(fmt.Sprintf(resourceAllowedGetMCFailed, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
199199
}
@@ -202,7 +202,7 @@ func ValidateMCIdentity(ctx context.Context, client client.Client, req admission
202202

203203
// For the upstream E2E we use hub agent service account's token which allows member agent to modify Work status, hence we use serviceAccountFmt to make the check.
204204
if identity == userInfo.Username || fmt.Sprintf(serviceAccountFmt, identity) == userInfo.Username {
205-
klog.V(2).InfoS(allowedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
205+
klog.V(3).InfoS(allowedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
206206
return admission.Allowed(fmt.Sprintf(resourceAllowedFormat, userInfo.Username, userInfo.Groups, req.Operation, req.RequestKind, req.SubResource, namespacedName))
207207
}
208208
klog.V(2).InfoS(deniedModifyResource, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)

test/e2e/v1alpha1/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ test suites, follow the steps below:
3030
5. Run the tests:
3131

3232
```shell
33-
make run-e2e
33+
make run-e2e-v1alpha1
3434
```
3535

3636
## Access the `Kind` clusters

test/e2e/v1alpha1/e2e_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
2727
workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1"
2828

29+
fleetnetworkingv1alpha1 "go.goms.io/fleet-networking/api/v1alpha1"
2930
"go.goms.io/fleet/apis/v1alpha1"
3031
"go.goms.io/fleet/pkg/utils"
3132
"go.goms.io/fleet/test/e2e/framework"
@@ -161,6 +162,7 @@ func init() {
161162
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
162163
utilruntime.Must(v1alpha1.AddToScheme(scheme))
163164
utilruntime.Must(workv1alpha1.AddToScheme(scheme))
165+
utilruntime.Must(fleetnetworkingv1alpha1.AddToScheme(scheme))
164166
utilruntime.Must(apiextensionsv1.AddToScheme(scheme))
165167
}
166168

0 commit comments

Comments
 (0)