vaidate manifests size

Signed-off-by: Zhiwei Yin <zyin@redhat.com>
This commit is contained in:
Zhiwei Yin
2021-04-16 15:00:22 +08:00
parent 6655e14ce7
commit 30b03bec32
5 changed files with 99 additions and 9 deletions

View File

@@ -51,6 +51,25 @@ func NewSecret(name, namespace string, content string) *corev1.Secret {
}
}
func NewUnstructuredSecretBySize(namespace, name string, size int32) *unstructured.Unstructured {
data := ""
for i := int32(0); i < size; i++ {
data += "a"
}
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"namespace": namespace,
"name": name,
},
"data": data,
},
}
}
func NewUnstructuredSecret(namespace, name string, terminated bool, uid string) *unstructured.Unstructured {
u := NewUnstructured("v1", "Secret", namespace, name)
if terminated {

View File

@@ -16,7 +16,8 @@ import (
"k8s.io/klog/v2"
)
var manifestLimit = 10
// ManifestLimit is the max size of manifests data which is 50k bytes.
const ManifestLimit = 50 * 1024
// ManifestWorkAdmissionHook will validate the creating/updating manifestwork request.
type ManifestWorkAdmissionHook struct{}
@@ -90,8 +91,13 @@ func (a *ManifestWorkAdmissionHook) validateManifestWorkObj(requestObj runtime.R
return fmt.Errorf("manifests should not be empty")
}
if len(work.Spec.Workload.Manifests) > manifestLimit {
return fmt.Errorf("number of manifests should not be larger than %d", manifestLimit)
totalSize := 0
for _, manifest := range work.Spec.Workload.Manifests {
totalSize = totalSize + manifest.Size()
}
if totalSize > ManifestLimit {
return fmt.Errorf("the size of manifests is %v bytes which exceeds the 50k limit", totalSize)
}
for _, manifest := range work.Spec.Workload.Manifests {

View File

@@ -21,7 +21,6 @@ var manifestWorkSchema = metav1.GroupVersionResource{
}
func TestManifestWorkValidate(t *testing.T) {
manifestLimit = 3
cases := []struct {
name string
request *admissionv1beta1.AdmissionRequest
@@ -153,16 +152,17 @@ func TestManifestWorkValidate(t *testing.T) {
UserInfo: authenticationv1.UserInfo{Username: "tester"},
},
manifests: []*unstructured.Unstructured{
spoketesting.NewUnstructured("v1", "Kind", "testns", "test"),
spoketesting.NewUnstructured("v1", "Kind", "testns", "test1"),
spoketesting.NewUnstructured("v1", "Kind", "testns", "test2"),
spoketesting.NewUnstructured("v1", "Kind", "testns", "test3"),
spoketesting.NewUnstructuredSecretBySize("test1", "testns", 10*1024),
spoketesting.NewUnstructuredSecretBySize("test2", "testns", 10*1024),
spoketesting.NewUnstructuredSecretBySize("test3", "testns", 10*1024),
spoketesting.NewUnstructuredSecretBySize("test4", "testns", 10*1024),
spoketesting.NewUnstructuredSecretBySize("test5", "testns", 10*1024),
},
expectedResponse: &admissionv1beta1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Status: metav1.StatusFailure, Code: http.StatusBadRequest, Reason: metav1.StatusReasonBadRequest,
Message: "number of manifests should not be larger than 3",
Message: "the size of manifests is 51685 bytes which exceeds the 50k limit",
},
},
},

View File

@@ -91,5 +91,49 @@ var _ = ginkgo.Describe("ManifestWork admission webhook", func() {
admissionName,
)))
})
ginkgo.It("Should respond bad request when the size of manifests is more than the limit", func() {
manifests := []workapiv1.Manifest{
{
RawExtension: runtime.RawExtension{
Object: newSecretBySize("default", "test1", 10*1024),
},
},
{
RawExtension: runtime.RawExtension{
Object: newSecretBySize("default", "test2", 10*1024),
},
},
{
RawExtension: runtime.RawExtension{
Object: newSecretBySize("default", "test3", 10*1024),
},
},
{
RawExtension: runtime.RawExtension{
Object: newSecretBySize("default", "test4", 10*1024),
},
},
{
RawExtension: runtime.RawExtension{
Object: newSecretBySize("default", "test5", 10*1024),
},
},
}
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
work, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
gomega.Expect(err).NotTo(gomega.HaveOccurred())
work.Spec.Workload.Manifests = append(work.Spec.Workload.Manifests, manifests...)
_, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Update(context.Background(), work, metav1.UpdateOptions{})
return err
})
gomega.Expect(err).To(gomega.HaveOccurred())
gomega.Expect(errors.IsBadRequest(err)).Should(gomega.BeTrue())
gomega.Expect(err.Error()).Should(gomega.HavePrefix(fmt.Sprintf(
"admission webhook \"%s\" denied the request: the size of manifests is", admissionName)))
})
})
})

View File

@@ -541,6 +541,27 @@ func newConfigmap(namespace, name string, data map[string]string, finalizers []s
return cm
}
func newSecretBySize(namespace, name string, size int32) *corev1.Secret {
data := ""
for i := int32(0); i < size; i++ {
data += "a"
}
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string][]byte{
"test": []byte(data),
},
}
}
func haveManifestCondition(conditions []workapiv1.ManifestCondition, expectedType string, expectedStatuses []metav1.ConditionStatus) bool {
if len(conditions) != len(expectedStatuses) {
return false