From 7ab4398aa212142c79f56ff7587fae888c0b33bd Mon Sep 17 00:00:00 2001 From: Austin Abro <37223396+AustinAbro321@users.noreply.github.com> Date: Wed, 18 Dec 2024 15:13:22 -0500 Subject: [PATCH] fix: check public key for signed packages during zarf package pull (#3347) Signed-off-by: Austin Abro --- src/cmd/package.go | 2 +- src/internal/packager2/pull.go | 15 ++++++- src/internal/packager2/pull_test.go | 2 +- src/test/e2e/11_oci_pull_inspect_test.go | 41 +++++++++++-------- src/test/packages/11-simple-package/test.txt | 0 src/test/packages/11-simple-package/zarf.yaml | 12 ++++++ 6 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 src/test/packages/11-simple-package/test.txt create mode 100644 src/test/packages/11-simple-package/zarf.yaml diff --git a/src/cmd/package.go b/src/cmd/package.go index 5d52b8bbec..a3667a1cb6 100644 --- a/src/cmd/package.go +++ b/src/cmd/package.go @@ -628,7 +628,7 @@ func (o *PackagePullOptions) Run(cmd *cobra.Command, args []string) error { } outputDir = wd } - err := packager2.Pull(cmd.Context(), args[0], outputDir, pkgConfig.PkgOpts.Shasum, filters.Empty()) + err := packager2.Pull(cmd.Context(), args[0], outputDir, pkgConfig.PkgOpts.Shasum, filters.Empty(), pkgConfig.PkgOpts.PublicKeyPath) if err != nil { return err } diff --git a/src/internal/packager2/pull.go b/src/internal/packager2/pull.go index 5f9dc2b5b7..a8426857fc 100644 --- a/src/internal/packager2/pull.go +++ b/src/internal/packager2/pull.go @@ -22,14 +22,14 @@ import ( "github.com/zarf-dev/zarf/src/api/v1alpha1" "github.com/zarf-dev/zarf/src/config" - "github.com/zarf-dev/zarf/src/pkg/layout" + "github.com/zarf-dev/zarf/src/internal/packager2/layout" "github.com/zarf-dev/zarf/src/pkg/packager/filters" "github.com/zarf-dev/zarf/src/pkg/utils" "github.com/zarf-dev/zarf/src/pkg/zoci" ) // Pull fetches the Zarf package from the given sources. -func Pull(ctx context.Context, src, dir, shasum string, filter filters.ComponentFilterStrategy) error { +func Pull(ctx context.Context, src, dir, shasum string, filter filters.ComponentFilterStrategy, publicKeyPath string) error { u, err := url.Parse(src) if err != nil { return err @@ -63,6 +63,17 @@ func Pull(ctx context.Context, src, dir, shasum string, filter filters.Component return fmt.Errorf("unknown scheme %s", u.Scheme) } + // This loadFromTar is done so that validatePackageIntegrtiy and validatePackageSignature are called + layoutOpt := layout.PackageLayoutOptions{ + PublicKeyPath: publicKeyPath, + SkipSignatureValidation: false, + IsPartial: false, + } + _, err = layout.LoadFromTar(ctx, tmpPath, layoutOpt) + if err != nil { + return err + } + name, err := nameFromMetadata(tmpPath) if err != nil { return err diff --git a/src/internal/packager2/pull_test.go b/src/internal/packager2/pull_test.go index 3d8d46b2ce..da649d71e5 100644 --- a/src/internal/packager2/pull_test.go +++ b/src/internal/packager2/pull_test.go @@ -39,7 +39,7 @@ func TestPull(t *testing.T) { dir := t.TempDir() shasum := "bef73d652f004d214d5cf9e00195293f7ae8390b8ff6ed45e39c2c9eb622b873" - err := Pull(ctx, srv.URL, dir, shasum, filters.Empty()) + err := Pull(ctx, srv.URL, dir, shasum, filters.Empty(), "") require.NoError(t, err) packageData, err := os.ReadFile(packagePath) diff --git a/src/test/e2e/11_oci_pull_inspect_test.go b/src/test/e2e/11_oci_pull_inspect_test.go index 356c5be99a..f3525c8109 100644 --- a/src/test/e2e/11_oci_pull_inspect_test.go +++ b/src/test/e2e/11_oci_pull_inspect_test.go @@ -6,18 +6,19 @@ package test import ( "fmt" + "path/filepath" "testing" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" + "github.com/zarf-dev/zarf/src/test/testutil" "oras.land/oras-go/v2/registry" ) type PullInspectTestSuite struct { suite.Suite *require.Assertions - Reference registry.Reference - PackagesDir string + Reference registry.Reference } var badPullInspectRef = registry.Reference{ @@ -28,34 +29,38 @@ var badPullInspectRef = registry.Reference{ func (suite *PullInspectTestSuite) SetupSuite() { suite.Assertions = require.New(suite.T()) - suite.PackagesDir = "build" -} - -func (suite *PullInspectTestSuite) TearDownSuite() { - local := fmt.Sprintf("zarf-package-dos-games-%s-1.0.0.tar.zst", e2e.Arch) - e2e.CleanFiles(suite.T(), local) + suite.Reference.Registry = testutil.SetupInMemoryRegistry(testutil.TestContext(suite.T()), suite.T(), 31888) } func (suite *PullInspectTestSuite) Test_0_Pull() { suite.T().Log("E2E: Package Pull oci://") - out := fmt.Sprintf("zarf-package-dos-games-%s-1.0.0.tar.zst", e2e.Arch) + privateKeyFlag := "--signing-key=src/test/packages/zarf-test.prv-key" + publicKeyFlag := "--key=src/test/packages/zarf-test.pub" - // Build the fully qualified reference. - ref := fmt.Sprintf("oci://ghcr.io/zarf-dev/packages/dos-games:1.0.0-%s", e2e.Arch) + outputPath := suite.T().TempDir() + stdOut, stdErr, err := e2e.Zarf(suite.T(), "package", "create", "src/test/packages/11-simple-package", "-o", outputPath, privateKeyFlag, "--confirm") + suite.NoError(err, stdOut, stdErr) - // Pull the package via OCI. - stdOut, stdErr, err := e2e.Zarf(suite.T(), "package", "pull", ref) + out := filepath.Join(outputPath, fmt.Sprintf("zarf-package-simple-package-%s-0.0.1.tar.zst", e2e.Arch)) + ref := suite.Reference.String() + stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "publish", out, "oci://"+ref, "--plain-http", publicKeyFlag) suite.NoError(err, stdOut, stdErr) - sbomTmp := suite.T().TempDir() + simplePackageRef := fmt.Sprintf("oci://%s/simple-package:0.0.1", ref) + // fail to pull the package without providing the public key + stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "pull", simplePackageRef, "--plain-http") + suite.Error(err, stdOut, stdErr) + + stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "pull", simplePackageRef, "--plain-http", publicKeyFlag) + suite.NoError(err, stdOut, stdErr) + + stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "inspect", simplePackageRef, "--plain-http") + suite.Error(err, stdOut, stdErr) - // Verify the package was pulled correctly. - suite.FileExists(out) - stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "inspect", out, "--key", "https://raw.githubusercontent.com/zarf-dev/zarf/v0.38.2/cosign.pub", "--sbom-out", sbomTmp) + stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "inspect", simplePackageRef, "--plain-http", publicKeyFlag, "--sbom-out", suite.T().TempDir()) suite.NoError(err, stdOut, stdErr) - // Test pull w/ bad ref. stdOut, stdErr, err = e2e.Zarf(suite.T(), "package", "pull", "oci://"+badPullInspectRef.String(), "--plain-http") suite.Error(err, stdOut, stdErr) } diff --git a/src/test/packages/11-simple-package/test.txt b/src/test/packages/11-simple-package/test.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/packages/11-simple-package/zarf.yaml b/src/test/packages/11-simple-package/zarf.yaml new file mode 100644 index 0000000000..86038ec3df --- /dev/null +++ b/src/test/packages/11-simple-package/zarf.yaml @@ -0,0 +1,12 @@ +kind: ZarfPackageConfig +metadata: + name: simple-package + description: simple small package to test pullling, publishing, and inspecting + version: 0.0.1 + +components: + - name: on-deploy-with-template-use-of-variable + required: true + files: + - source: test.txt + target: test.txt