Skip to content

Commit cb856d4

Browse files
committed
moving to new repo
Signed-off-by: audrastump <a.e.stump@wustl.edu>
1 parent 62f0d28 commit cb856d4

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

pkg/webhook/fleetresourcehandler/fleetresourcehandler_webhook_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,89 @@ func TestHandleMemberCluster(t *testing.T) {
634634
},
635635
wantResponse: admission.Allowed(fmt.Sprintf(validation.ResourceAllowedFormat, "aks-support", utils.GenerateGroupString([]string{"system:authenticated"}), admissionv1.Delete, &utils.MCMetaGVK, "", types.NamespacedName{Name: "test-mc"})),
636636
},
637+
638+
"allow label modification by RP client": {
639+
req: admission.Request{
640+
AdmissionRequest: admissionv1.AdmissionRequest{
641+
Name: "test-mc",
642+
Object: runtime.RawExtension{
643+
Raw: func() []byte {
644+
updatedMC := &clusterv1beta1.MemberCluster{
645+
ObjectMeta: metav1.ObjectMeta{
646+
Name: "test-mc",
647+
Labels: map[string]string{"key1": "value1"},
648+
Annotations: map[string]string{
649+
"fleet.azure.com/cluster-resource-id": "test-cluster-resource-id",
650+
},
651+
},
652+
}
653+
raw, _ := json.Marshal(updatedMC)
654+
return raw
655+
}(),
656+
},
657+
OldObject: runtime.RawExtension{
658+
Raw: fleetMCObjectBytes,
659+
},
660+
UserInfo: authenticationv1.UserInfo{
661+
Username: "aksService",
662+
Groups: []string{"system:masters"},
663+
},
664+
RequestKind: &utils.MCMetaGVK,
665+
Operation: admissionv1.Update,
666+
},
667+
},
668+
resourceValidator: fleetResourceValidator{
669+
decoder: decoder,
670+
},
671+
wantResponse: admission.Allowed(fmt.Sprintf(validation.ResourceAllowedFormat, "aksService", utils.GenerateGroupString([]string{"system:masters"}), admissionv1.Update, &utils.MCMetaGVK, "", types.NamespacedName{Name: "test-mc"})),
672+
},
673+
"deny label modification by non-RP client": {
674+
req: admission.Request{
675+
AdmissionRequest: admissionv1.AdmissionRequest{
676+
Name: "test-mc",
677+
Object: runtime.RawExtension{
678+
Raw: func() []byte {
679+
updatedMC := &clusterv1beta1.MemberCluster{
680+
ObjectMeta: metav1.ObjectMeta{
681+
Name: "test-mc",
682+
Labels: map[string]string{"key1": "value1"},
683+
Annotations: map[string]string{
684+
"fleet.azure.com/cluster-resource-id": "test-cluster-resource-id",
685+
},
686+
},
687+
}
688+
raw, _ := json.Marshal(updatedMC)
689+
return raw
690+
}(),
691+
},
692+
OldObject: runtime.RawExtension{
693+
Raw: func() []byte {
694+
oldMC := &clusterv1beta1.MemberCluster{
695+
ObjectMeta: metav1.ObjectMeta{
696+
Name: "test-mc",
697+
Labels: map[string]string{"key1": "value2"},
698+
Annotations: map[string]string{
699+
"fleet.azure.com/cluster-resource-id": "test-cluster-resource-id",
700+
},
701+
},
702+
}
703+
raw, _ := json.Marshal(oldMC)
704+
return raw
705+
}(),
706+
},
707+
UserInfo: authenticationv1.UserInfo{
708+
Username: "nonRPUser",
709+
Groups: []string{"system:authenticated"},
710+
},
711+
RequestKind: &utils.MCMetaGVK,
712+
Operation: admissionv1.Update,
713+
},
714+
},
715+
resourceValidator: fleetResourceValidator{
716+
decoder: decoder,
717+
},
718+
wantResponse: admission.Denied(fmt.Sprintf(validation.DeniedModifyFleetLabels)),
719+
},
637720
}
638721

639722
for testName, testCase := range testCases {

pkg/webhook/validation/uservalidation.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const (
3636
deniedModifyResource = "user in groups is not allowed to modify resource"
3737
deniedAddFleetAnnotation = "no user is allowed to add a fleet pre-fixed annotation to an upstream member cluster"
3838
deniedRemoveFleetAnnotation = "no user is allowed to remove all fleet pre-fixed annotations from a fleet member cluster"
39+
DeniedModifyFleetLabels = "users are not allowed to modify labels through hub cluster directly"
3940

4041
ResourceAllowedFormat = "user: '%s' in '%s' is allowed to %s resource %+v/%s: %+v"
4142
ResourceDeniedFormat = "user: '%s' in '%s' is not allowed to %s resource %+v/%s: %+v"
@@ -107,6 +108,14 @@ func ValidateFleetMemberClusterUpdate(currentMC, oldMC clusterv1beta1.MemberClus
107108
if err != nil {
108109
return admission.Denied(err.Error())
109110
}
111+
112+
// users are no longer allowed to modify labels of fleet member cluster through webhook.
113+
isLabelUpdated := isMapFieldUpdated(currentMC.GetLabels(), oldMC.GetLabels())
114+
if isLabelUpdated && !isRPClient(userInfo) {
115+
klog.V(2).InfoS(DeniedModifyFleetLabels, "user", userInfo.Username, "groups", userInfo.Groups, "operation", req.Operation, "GVK", req.RequestKind, "subResource", req.SubResource, "namespacedName", namespacedName)
116+
return admission.Denied(DeniedModifyFleetLabels)
117+
}
118+
110119
isAnnotationUpdated := isFleetAnnotationUpdated(currentMC.Annotations, oldMC.Annotations)
111120
if isObjUpdated || isAnnotationUpdated {
112121
return ValidateUserForResource(req, whiteListedUsers)
@@ -167,6 +176,11 @@ func isNodeGroupUser(userInfo authenticationv1.UserInfo) bool {
167176
return slices.Contains(userInfo.Groups, nodeGroup)
168177
}
169178

179+
// isRPClient returns true if user is aksService and belongs to system:masters group.
180+
func isRPClient(userInfo authenticationv1.UserInfo) bool {
181+
return userInfo.Username == "aksService" && slices.Contains(userInfo.Groups, mastersGroup)
182+
}
183+
170184
// isMemberClusterMapFieldUpdated return true if member cluster label is updated.
171185
func isMapFieldUpdated(currentMap, oldMap map[string]string) bool {
172186
return !reflect.DeepEqual(currentMap, oldMap)

0 commit comments

Comments
 (0)