diff --git a/test/acceptance/client_server_test.go b/test/acceptance/client_server_test.go index c86fa9f..ada89c2 100644 --- a/test/acceptance/client_server_test.go +++ b/test/acceptance/client_server_test.go @@ -2,12 +2,16 @@ package acceptance import ( "context" + "crypto/sha256" "debug/elf" "debug/macho" "debug/pe" "fmt" + "io" + "log" "os" "path/filepath" + "strings" "time" . "github.com/onsi/ginkgo/v2" @@ -15,16 +19,24 @@ import ( "github.com/securesign/structural-tests/test/support" ) -const cliServerPathMask = "/var/www/html/clients/%s/%s-%s.gz" +const ( + cliServerFileMask = "%s-%s.gz" + cliServerPathMask = "/var/www/html/clients/%s/" + cliServerFileMask + + cliImageBasePath = "/usr/local/bin" + cliImageFileMask = "%s_cli_%s_%s.gz" +) var _ = Describe("Client server", Ordered, func() { var clientServerImage string + var snapshotImages support.SnapshotMap var tmpDir string Describe("client-server image", func() { It("snapshot.json", func() { - snapshotImages, err := support.ParseSnapshotImages() + var err error + snapshotImages, err = support.ParseSnapshotImages() Expect(err).NotTo(HaveOccurred()) clientServerImage = snapshotImages["client-server-image"] @@ -35,6 +47,7 @@ var _ = Describe("Client server", Ordered, func() { var err error tmpDir, err = os.MkdirTemp("", "client-server") Expect(err).NotTo(HaveOccurred()) + log.Printf("TEMP directory: %s", tmpDir) }) }) @@ -49,6 +62,22 @@ var _ = Describe("Client server", Ordered, func() { func(cli string, matrix support.OSArchMatrix) { for osName, archs := range matrix { for _, arch := range archs { + var image string + var gzipServerSHA []byte + + It("init", func() { + switch cli { + case "createtree", "updatetree": + image = snapshotImages[cli+"-image"] + case "tuftool": + image = snapshotImages["tuf-tool-image"] + case "rekor-cli": + image = snapshotImages["rekor-cli-image"] + default: + image = snapshotImages[cli+"-cli-image"] + } + }) + It(fmt.Sprintf("verify %s-%s executable", osName, arch), func() { osPath := filepath.Join(tmpDir, osName) Expect(os.MkdirAll(osPath, 0755)).To(Succeed()) @@ -59,13 +88,66 @@ var _ = Describe("Client server", Ordered, func() { Expect(support.FileFromImage(ctx, clientServerImage, fmt.Sprintf(cliServerPathMask, osName, cli, arch), osPath)).To(Succeed()) By("decompress gzip") - gzipPath := filepath.Join(osPath, cli+"-"+arch+".gz") + gzipPath := filepath.Join(osPath, fmt.Sprintf(cliServerFileMask, cli, arch)) targetPath := filepath.Join(osPath, cli+"-"+arch) Expect(support.DecompressGzipFile(gzipPath, targetPath)).To(Succeed()) By("verify executable OS and arch") executable := filepath.Join(tmpDir, osName, cli+"-"+arch) Expect(verifyExecutable(executable, osName, arch)).To(Succeed()) + + By("checksums of gzip file") + var err error + gzipServerSHA, err = checksumFile(filepath.Join(osPath, fmt.Sprintf(cliServerFileMask, cli, arch))) + Expect(err).NotTo(HaveOccurred()) + }) + + It(fmt.Sprintf("compare checkum of %s-%s with source image", osName, arch), func() { + var ( + targetPath = tmpDir + fileName string + filePath string + ) + + switch cli { + case "tuftool": + Skip("`tuftool` do not have gzip in source image") + case "ec": + Skip("`ec` source image is not part of handover") + case "cosign", "updatetree", "createtree": + if osName == "windows" { //nolint:goconst + fileName = fmt.Sprintf("%s-%s-%s.exe.gz", cli, osName, arch) + } else { + fileName = fmt.Sprintf("%s-%s-%s.gz", cli, osName, arch) + } + case "rekor-cli", "fetch-tsa-certs": + ncli := strings.ReplaceAll(cli, "-", "_") + if osName == "windows" { + fileName = fmt.Sprintf("%s_%s_%s.exe.gz", ncli, osName, arch) + } else { + fileName = fmt.Sprintf("%s_%s_%s.gz", ncli, osName, arch) + } + default: + if osName == "windows" { + fileName = fmt.Sprintf(cliImageFileMask, cli, osName, arch+".exe") + } else { + fileName = fmt.Sprintf(cliImageFileMask, cli, osName, arch) + } + } + filePath = filepath.Join(cliImageBasePath, fileName) + + By("get gzip file from container image") + ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5) + defer cancel() + + Expect(support.FileFromImage(ctx, image, filePath, targetPath)).To(Succeed()) + + By("checksums of gzip file") + gzipImageSHA, err := checksumFile(filepath.Join(targetPath, fileName)) + Expect(err).NotTo(HaveOccurred()) + + By("compare checksum with client server file") + Expect(gzipImageSHA).To(Equal(gzipServerSHA)) }) } } @@ -165,3 +247,19 @@ func getMachOCpuType(arch string) macho.Cpu { return 0 // Unsupported architecture } } + +// checksumFile computes the SHA256 checksum of a given file. +func checksumFile(filePath string) ([]byte, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, fmt.Errorf("failed to open file %s: %w", filePath, err) + } + defer func() { _ = file.Close() }() + + hasher := sha256.New() + if _, err := io.Copy(hasher, file); err != nil { + return nil, fmt.Errorf("failed to hash file %s: %w", filePath, err) + } + + return hasher.Sum(nil), nil +}