From 5c5922a922f225a9ebc5f99a5008ddcf182b7da6 Mon Sep 17 00:00:00 2001 From: Yuhang Wei Date: Thu, 10 Aug 2023 17:24:50 +0800 Subject: [PATCH 05/17] KubeOS: fix validate image name bug fix the bug that incorrectly granted illegal image names path:tag@sha256 Signed-off-by: Yuhang Wei --- cmd/agent/server/utils.go | 2 +- cmd/agent/server/utils_test.go | 109 ++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/cmd/agent/server/utils.go b/cmd/agent/server/utils.go index 7134d74..b42db18 100644 --- a/cmd/agent/server/utils.go +++ b/cmd/agent/server/utils.go @@ -316,7 +316,7 @@ func isCommandAvailable(name string) bool { } func isValidImageName(image string) error { - pattern := `^((?:[\w.-]+)(?::\d+)?\/)*(?:[\w.-]+)(?::[\w_.-]+)?(?:@sha256:[a-fA-F0-9]+)?$` + pattern := `^((?:[\w.-]+)(?::\d+)?\/)*(?:[\w.-]+)((?::[\w_.-]+)?|(?:@sha256:[a-fA-F0-9]+)?)$` regEx, err := regexp.Compile(pattern) if err != nil { return err diff --git a/cmd/agent/server/utils_test.go b/cmd/agent/server/utils_test.go index 89b2c3b..0796bce 100644 --- a/cmd/agent/server/utils_test.go +++ b/cmd/agent/server/utils_test.go @@ -56,10 +56,16 @@ func Test_install(t *testing.T) { args args wantErr bool }{ - {name: "normal", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false}, + {name: "normal uefi", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false}, + {name: "normal legacy", args: args{imagePath: "aa.txt", side: "/dev/sda3", next: "A"}, wantErr: false}, } patchRunCommand := gomonkey.ApplyFuncReturn(runCommand, nil) defer patchRunCommand.Reset() + patchGetBootMode := gomonkey.ApplyFuncSeq(getBootMode, []gomonkey.OutputCell{ + {Values: gomonkey.Params{"uefi", nil}}, + {Values: gomonkey.Params{"legacy", nil}}, + }) + defer patchGetBootMode.Reset() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if err := install(tt.args.imagePath, tt.args.side, tt.args.next); (err != nil) != tt.wantErr { @@ -219,3 +225,104 @@ func createTmpTarFile(tarPath string) (string, error) { } return tempFile.Name(), nil } + +func Test_getBootMode(t *testing.T) { + tests := []struct { + name string + want string + wantErr bool + }{ + { + name: "uefi", + want: "uefi", + wantErr: false, + }, + { + name: "legacy", + want: "legacy", + wantErr: false, + }, + } + patchOSStat := gomonkey.ApplyFuncSeq(os.Stat, []gomonkey.OutputCell{ + {Values: gomonkey.Params{nil, nil}}, + {Values: gomonkey.Params{nil, os.ErrNotExist}}, + }) + defer patchOSStat.Reset() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getBootMode() + if (err != nil) != tt.wantErr { + t.Errorf("getBootMode() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("getBootMode() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_isValidImageName(t *testing.T) { + type args struct { + image string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "valid", args: args{image: "alpine"}, wantErr: false}, + {name: "valid", args: args{image: "alpine:latest"}, wantErr: false}, + {name: "valid", args: args{image: "localhost:1234/test"}, wantErr: false}, + {name: "valid", args: args{image: "alpine:3.7"}, wantErr: false}, + {name: "valid", args: args{image: "docker.example.edu/gmr/alpine:3.7"}, wantErr: false}, + {name: "valid", args: args{image: "docker.example.com:5000/gmr/alpine@sha256:11111111111111111111111111111111"}, wantErr: false}, + {name: "valid", args: args{image: "registry.dobby.org/dobby/dobby-servers/arthound:2019-08-08"}, wantErr: false}, + {name: "valid", args: args{image: "registry.dobby.org/dobby/dobby-servers/lerphound:latest"}, wantErr: false}, + {name: "valid", args: args{image: "registry.dobby.org/dobby/dobby-servers/loophole@sha256:5a156ff125e5a12ac7ff43ee5120fa249cf62248337b6d04abc574c8"}, wantErr: false}, + {name: "valid", args: args{image: "sosedoff/pgweb@sha256:5a156ff125e5a12ac7ff43ee5120fa249cf62248337b6d04574c8"}, wantErr: false}, + {name: "valid", args: args{image: "registry.dobby.org/dobby/antique-penguin:release-production"}, wantErr: false}, + {name: "valid", args: args{image: "dalprodictus/halcon:6.7.5"}, wantErr: false}, + {name: "valid", args: args{image: "antigua/antigua:v31"}, wantErr: false}, + {name: "invalid ;", args: args{image: "alpine;v1.0"}, wantErr: true}, + {name: "invalid tag and digest1", args: args{image: "alpine:latest@sha256:11111111111111111111111111111111"}, wantErr: true}, + {name: "invalid |", args: args{image: "alpine|v1.0"}, wantErr: true}, + {name: "invalid &", args: args{image: "alpine&v1.0"}, wantErr: true}, + {name: "invalid tag and digest2", args: args{image: "sosedoff/pgweb:latest@sha256:5a156ff125e5a12ac7ff43ee5120fa249cf62248337b6d04574c8"}, wantErr: true}, + {name: "invalid tag and digest3", args: args{image: "192.168.122.123:5000/kubeos_uefi-x86_64:euleros_v2_docker-2023-01@sha256:1a1a1a1a1a1a1a1a1a1a1a1a1a1a"}, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := isValidImageName(tt.args.image); (err != nil) != tt.wantErr { + t.Errorf("isValidImageName() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_checkOCIImageDigestMatch(t *testing.T) { + type args struct { + containerRuntime string + imageName string + checkSum string + } + tests := []struct { + name string + args args + wantErr bool + }{ + {name: "invalid container runtion", args: args{containerRuntime: "dockctl", imageName: "docker.io/library/hello-world:latest", checkSum: "1abf18abf9bf9baa0a4a38d1afad4abf0d7da4544e163186e036c906c09c94fe"}, wantErr: true}, + {name: "nil image digets", args: args{containerRuntime: "crictl", imageName: "docker.io/library/hello-world:latest", checkSum: "1abf18abf9bf9baa0a4a38d1afad4abf0d7da4544e163186e036c906c09c94fe"}, wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.name == "nil image digets" { + patchGetOCIImageDigest := gomonkey.ApplyFuncReturn(getOCIImageDigest, "", nil) + defer patchGetOCIImageDigest.Reset() + } + if err := checkOCIImageDigestMatch(tt.args.containerRuntime, tt.args.imageName, tt.args.checkSum); (err != nil) != tt.wantErr { + t.Errorf("checkOCIImageDigestMatch() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} -- 2.39.0