From 0634985b4edb242268dc1d1effd25f88627a19d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Ar=C3=A9jula=20A=C3=ADsa?= Date: Thu, 9 Nov 2023 17:49:56 +0100 Subject: [PATCH 1/5] feat: [#2] Add checksum for downloaded archives Add checksum validation for downloaded archives. New field added to the `Source` struct. The checksum is calculated using the `sha256` algorithm and compared. --- core/resolver.go | 25 ++++++++++++++++++++----- core/structs.go | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/core/resolver.go b/core/resolver.go index 4269c42..53dfe7a 100644 --- a/core/resolver.go +++ b/core/resolver.go @@ -153,27 +153,42 @@ func DownloadGitSource(recipe *Recipe, source Source) error { // DownloadTarSource downloads a tar archive to the downloads directory func DownloadTarSource(recipe *Recipe, source Source) error { fmt.Printf("Source is tar: %s\n", source.URL) - + //Create the destination path dest := filepath.Join(recipe.DownloadsPath, source.Module) - + //Download the resource res, err := http.Get(source.URL) if err != nil { return err } defer res.Body.Close() - + //Create the destination tar file file, err := os.Create(dest) if err != nil { return err } - + //Close the file when the function ends defer file.Close() - + //Copy the response body to the destination file _, err = io.Copy(file, res.Body) if err != nil { return err } + //Check the tar file checksum + if source.Checksum != "" { + cmd := exec.Command( + "sha256sum", dest, + ) + checksum, err := cmd.Output() + if err != nil { + return err + } + //Compare the checksums + if strings.Split(string(checksum), " ")[0] != source.Checksum { + return fmt.Errorf("tar file checksum doesn't match") + } + + } return nil } diff --git a/core/structs.go b/core/structs.go index fab5d81..23febcb 100644 --- a/core/structs.go +++ b/core/structs.go @@ -32,6 +32,7 @@ type Module struct { type Source struct { URL string `json:"url"` + Checksum string `json:"checksum"` Type string `json:"type"` Commit string `json:"commit"` Tag string `json:"tag"` From d8948595bef5ec563f26ba5b23ad41e1c89556d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Ar=C3=A9jula=20A=C3=ADsa?= Date: Thu, 9 Nov 2023 18:38:09 +0100 Subject: [PATCH 2/5] feat: [#2] Add checksum for downloaded archives Modified the resolver to calculate the checksum of the downloaded. Instead of using the sha256sum command, the checksum is calculated in Go using the crypto/sha256 package. --- core/resolver.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/resolver.go b/core/resolver.go index 53dfe7a..b31ba99 100644 --- a/core/resolver.go +++ b/core/resolver.go @@ -1,6 +1,7 @@ package core import ( + "crypto/sha256" "fmt" "io" "net/http" @@ -176,15 +177,15 @@ func DownloadTarSource(recipe *Recipe, source Source) error { } //Check the tar file checksum if source.Checksum != "" { - cmd := exec.Command( - "sha256sum", dest, - ) - checksum, err := cmd.Output() + checksum := sha256.New() + //Calculate the checksum + _, err = io.Copy(checksum, res.Body) if err != nil { - return err + return fmt.Errorf("could not calculate tar file checksum") } + //Compare the checksums - if strings.Split(string(checksum), " ")[0] != source.Checksum { + if string(checksum.Sum(nil)) != source.Checksum { return fmt.Errorf("tar file checksum doesn't match") } From 16f38a25aa98fcb6f2943fd66f0ddd14c173bff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Ar=C3=A9jula=20A=C3=ADsa?= Date: Fri, 10 Nov 2023 22:06:27 +0100 Subject: [PATCH 3/5] feat: [#2] Add checksum for downloaded archives Add checksum validation for tar source downloads --- core/resolver.go | 51 ++++++++++++++++++++++++++------------- core/resolver_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 core/resolver_test.go diff --git a/core/resolver.go b/core/resolver.go index b31ba99..bdb84aa 100644 --- a/core/resolver.go +++ b/core/resolver.go @@ -59,7 +59,11 @@ func DownloadSource(recipe *Recipe, source Source) error { if source.Type == "git" { return DownloadGitSource(recipe, source) } else if source.Type == "tar" { - return DownloadTarSource(recipe, source) + err := DownloadTarSource(recipe, source) + if err != nil { + return err + } + return checksumValidation(source, filepath.Join(recipe.DownloadsPath, source.Module)) } else { return fmt.Errorf("unsupported source type %s", source.Type) } @@ -175,21 +179,6 @@ func DownloadTarSource(recipe *Recipe, source Source) error { if err != nil { return err } - //Check the tar file checksum - if source.Checksum != "" { - checksum := sha256.New() - //Calculate the checksum - _, err = io.Copy(checksum, res.Body) - if err != nil { - return fmt.Errorf("could not calculate tar file checksum") - } - - //Compare the checksums - if string(checksum.Sum(nil)) != source.Checksum { - return fmt.Errorf("tar file checksum doesn't match") - } - - } return nil } @@ -236,3 +225,33 @@ func MoveSource(recipe *Recipe, source Source) error { return fmt.Errorf("unsupported source type %s", source.Type) } } + +// checksumValidation validates the checksum of a file +func checksumValidation(source Source, path string) error { + //No checksum provided + if source.Checksum == "" { + return nil + } + //open and read the Readme.md file + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + //Calculate the checksum + checksum := sha256.New() + _, err = io.Copy(checksum, file) + if err != nil { + return fmt.Errorf("could not calculate tar file checksum") + } + + fmt.Printf("%x", checksum.Sum(nil)) + //Compare the checksums + fmt.Printf("%x", checksum.Sum(nil)) + if fmt.Sprintf("%x", checksum.Sum(nil)) != source.Checksum { + + return fmt.Errorf("tar file checksum doesn't match") + } + + return nil +} diff --git a/core/resolver_test.go b/core/resolver_test.go new file mode 100644 index 0000000..baf4ed9 --- /dev/null +++ b/core/resolver_test.go @@ -0,0 +1,56 @@ +package core_test + +import ( + "os" + "path/filepath" + "testing" + + "github.com/vanilla-os/vib/core" +) + +func TestDownloadSource(t *testing.T) { + recipe := &core.Recipe{ + DownloadsPath: "/tmp/", + } + source := core.Source{ + Type: "tar", + URL: "https://github.com/Vanilla-OS/Vib/archive/refs/tags/v0.3.1.tar.gz", + Module: "example", + Checksum: "d28ab888c7b30fd1cc01e0a581169ea52dfb5bfcefaca721497f82734b6a5a98", + } + err := core.DownloadSource(recipe, source) + if err != nil { + t.Errorf("DownloadSource returned an error: %v", err) + } + + // Check if the file was downloaded + dest := filepath.Join(recipe.DownloadsPath, source.Module) + if _, err := os.Stat(dest); os.IsNotExist(err) { + t.Errorf("Downloaded file does not exist: %v", err) + } + defer os.Remove("/tmp/example") // clean up +} + +func TestDownloadTarSource(t *testing.T) { + recipe := &core.Recipe{ + DownloadsPath: "/tmp/", + } + source := core.Source{ + Type: "tar", + URL: "https://github.com/Vanilla-OS/Vib/archive/refs/tags/v0.3.1.tar.gz", + Module: "example", + Checksum: "d28ab888c7b30fd1cc01e0a581169ea52dfb5bfcefaca721497f82734b6a5a98", + } + err := core.DownloadTarSource(recipe, source) + if err != nil { + t.Errorf("DownloadTarSource returned an error: %v", err) + } + + // Check if the file was downloaded + dest := filepath.Join(recipe.DownloadsPath, source.Module) + if _, err := os.Stat(dest); os.IsNotExist(err) { + t.Errorf("Downloaded file does not exist: %v", err) + } + defer os.Remove("/tmp/example") // clean up + +} From d2686f5a762df91d6706f9ec5aa9acd8719ca033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Ar=C3=A9jula=20A=C3=ADsa?= Date: Fri, 10 Nov 2023 23:23:14 +0100 Subject: [PATCH 4/5] corrections --- core/resolver.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/resolver.go b/core/resolver.go index bdb84aa..dcfd33b 100644 --- a/core/resolver.go +++ b/core/resolver.go @@ -229,7 +229,7 @@ func MoveSource(recipe *Recipe, source Source) error { // checksumValidation validates the checksum of a file func checksumValidation(source Source, path string) error { //No checksum provided - if source.Checksum == "" { + if len(strings.TrimSpace(source.Checksum)) == 0 { return nil } //open and read the Readme.md file @@ -245,9 +245,6 @@ func checksumValidation(source Source, path string) error { return fmt.Errorf("could not calculate tar file checksum") } - fmt.Printf("%x", checksum.Sum(nil)) - //Compare the checksums - fmt.Printf("%x", checksum.Sum(nil)) if fmt.Sprintf("%x", checksum.Sum(nil)) != source.Checksum { return fmt.Errorf("tar file checksum doesn't match") From bd12fd82e62fa01c58466e6da620c7c5b75b954d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Ar=C3=A9jula=20A=C3=ADsa?= Date: Fri, 10 Nov 2023 23:26:45 +0100 Subject: [PATCH 5/5] feat: [#2] Improve comments --- core/resolver.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/resolver.go b/core/resolver.go index dcfd33b..52e0d76 100644 --- a/core/resolver.go +++ b/core/resolver.go @@ -232,11 +232,12 @@ func checksumValidation(source Source, path string) error { if len(strings.TrimSpace(source.Checksum)) == 0 { return nil } - //open and read the Readme.md file + //Open the file file, err := os.Open(path) if err != nil { return err } + //Close the file when the function ends defer file.Close() //Calculate the checksum checksum := sha256.New() @@ -245,6 +246,7 @@ func checksumValidation(source Source, path string) error { return fmt.Errorf("could not calculate tar file checksum") } + //Validate the checksum if fmt.Sprintf("%x", checksum.Sum(nil)) != source.Checksum { return fmt.Errorf("tar file checksum doesn't match")