diff --git a/pkg/admitter/cloudinit.go b/pkg/admitter/cloudinit.go index 22a0c7b8..b0567d5e 100644 --- a/pkg/admitter/cloudinit.go +++ b/pkg/admitter/cloudinit.go @@ -7,6 +7,7 @@ import ( "path/filepath" "github.com/harvester/webhook/pkg/server/admission" + "gopkg.in/yaml.v3" admissionregv1 "k8s.io/api/admissionregistration/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -21,6 +22,7 @@ var ( errFilenameTaken = errors.New("filename already in use") errProtectedFilename = errors.New("filename conflicts with a critical system-owned file") errMissingExt = errors.New("filename does not end in .yaml or .yml") + errNotYAML = errors.New("could not parse document as yaml") ) var builtinFilenameDenyList = []string{ @@ -85,6 +87,16 @@ func (v *CloudInit) validate(cloudinit *v1beta1.CloudInit) error { return errFilenameTaken } + var obj map[string]any + var typeErr *yaml.TypeError + err = yaml.Unmarshal([]byte(cloudinit.Spec.Contents), &obj) + if errors.As(err, &typeErr) { + return errNotYAML + } + if err != nil { + return err + } + return nil } diff --git a/pkg/admitter/cloudinit_test.go b/pkg/admitter/cloudinit_test.go index b2453814..ab9a0964 100644 --- a/pkg/admitter/cloudinit_test.go +++ b/pkg/admitter/cloudinit_test.go @@ -56,6 +56,7 @@ func TestCreate(t *testing.T) { {"filename collision", v1beta1.CloudInitSpec{Filename: "99_ssh.yaml"}, errFilenameTaken}, {"conflicts with protected file", v1beta1.CloudInitSpec{Filename: "helloworld.yaml"}, errProtectedFilename}, {"not yaml or yml file ext", v1beta1.CloudInitSpec{Filename: "a"}, errMissingExt}, + {"not yaml contents", v1beta1.CloudInitSpec{Filename: "not.yaml", Contents: "hello, there"}, errNotYAML}, } for _, tt := range tests { @@ -96,6 +97,7 @@ func TestUpdate(t *testing.T) { {"filename collision", v1beta1.CloudInitSpec{Filename: "99_ssh.yaml"}, errFilenameTaken}, {"conflicts with protected file", v1beta1.CloudInitSpec{Filename: "helloworld.yaml"}, errProtectedFilename}, {"not yaml or yml file ext", v1beta1.CloudInitSpec{Filename: "a"}, errMissingExt}, + {"not yaml contents", v1beta1.CloudInitSpec{Filename: "not.yaml", Contents: "hello, there"}, errNotYAML}, } for _, tt := range tests {