Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: strict bundle yaml validation #596

Merged
merged 9 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions src/pkg/bundle/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import (
"github.com/AlecAivazis/survey/v2"
"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/pkg/bundler"
"github.com/defenseunicorns/uds-cli/src/pkg/utils"
"github.com/defenseunicorns/uds-cli/src/types"
zarfConfig "github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/interactive"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/utils"
zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/pterm/pterm"
"helm.sh/helm/v3/pkg/chartutil"
)
Expand All @@ -24,7 +25,12 @@ import (
func (b *Bundle) Create() error {

// read the bundle's metadata into memory
if err := utils.ReadYaml(filepath.Join(b.cfg.CreateOpts.SourceDirectory, b.cfg.CreateOpts.BundleFile), &b.bundle); err != nil {
if err := utils.ReadYAMLStrict(filepath.Join(b.cfg.CreateOpts.SourceDirectory, b.cfg.CreateOpts.BundleFile), &b.bundle); err != nil {
return err
}

// Populate values from valuesFiles if provided
if err := b.processValuesFiles(); err != nil {
return err
}

Expand Down Expand Up @@ -62,7 +68,7 @@ func (b *Bundle) Create() error {
if b.cfg.CreateOpts.SigningKeyPath != "" {
// write the bundle to disk so we can sign it
bundlePath := filepath.Join(b.tmp, config.BundleYAML)
if err := utils.WriteYaml(bundlePath, &b.bundle, 0600); err != nil {
if err := zarfUtils.WriteYaml(bundlePath, &b.bundle, 0600); err != nil {
return err
}

Expand All @@ -74,7 +80,7 @@ func (b *Bundle) Create() error {
}
// sign the bundle
signaturePath := filepath.Join(b.tmp, config.BundleYAMLSignature)
_, err := utils.CosignSignBlob(bundlePath, signaturePath, b.cfg.CreateOpts.SigningKeyPath, getSigCreatePassword)
_, err := zarfUtils.CosignSignBlob(bundlePath, signaturePath, b.cfg.CreateOpts.SigningKeyPath, getSigCreatePassword)
if err != nil {
return err
}
Expand All @@ -94,7 +100,7 @@ func (b *Bundle) Create() error {
func (b *Bundle) confirmBundleCreation() (confirm bool) {

message.HeaderInfof("🎁 BUNDLE DEFINITION")
utils.ColorPrintYAML(b.bundle, nil, false)
zarfUtils.ColorPrintYAML(b.bundle, nil, false)

message.HorizontalRule()
pterm.Println()
Expand Down
6 changes: 3 additions & 3 deletions src/pkg/bundle/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ import (
"regexp"

"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/pkg/utils"

zarfCLI "github.com/defenseunicorns/zarf/src/cmd"
"github.com/defenseunicorns/zarf/src/pkg/message"
zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils"
)

// CreateZarfPkgs creates a zarf package if its missing when in dev mode
func (b *Bundle) CreateZarfPkgs() {
srcDir := b.cfg.CreateOpts.SourceDirectory
bundleYAMLPath := filepath.Join(srcDir, b.cfg.CreateOpts.BundleFile)
if err := zarfUtils.ReadYaml(bundleYAMLPath, &b.bundle); err != nil {
message.Fatalf(err, "Failed to read bundle.yaml: %s", err.Error())
if err := utils.ReadYAMLStrict(bundleYAMLPath, &b.bundle); err != nil {
message.Fatalf(err, "Failed to read %s, error in YAML: %s", b.cfg.CreateOpts.BundleFile, err.Error())
}

zarfPackagePattern := `^zarf-.*\.tar\.zst$`
Expand Down
7 changes: 4 additions & 3 deletions src/pkg/bundle/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ package bundle

import (
"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/uds-cli/src/pkg/utils"
zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils"
)

// Inspect pulls/unpacks a bundle's metadata and shows it
Expand Down Expand Up @@ -44,12 +45,12 @@ func (b *Bundle) Inspect() error {
}
}
// read the bundle's metadata into memory
if err := utils.ReadYaml(loaded[config.BundleYAML], &b.bundle); err != nil {
if err := utils.ReadYAMLStrict(loaded[config.BundleYAML], &b.bundle); err != nil {
return err
}

// show the bundle's metadata
utils.ColorPrintYAML(b.bundle, nil, false)
zarfUtils.ColorPrintYAML(b.bundle, nil, false)

// TODO: showing package metadata?
// TODO: could be cool to have an interactive mode that lets you select a package and show its metadata
Expand Down
3 changes: 1 addition & 2 deletions src/pkg/bundle/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/defenseunicorns/pkg/oci"
"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/pkg/utils"
zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/pkg/zoci"
av3 "github.com/mholt/archiver/v3"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand All @@ -32,7 +31,7 @@ func (b *Bundle) Publish() error {
if err != nil {
return err
}
if err := zarfUtils.ReadYaml(loaded[config.BundleYAML], &b.bundle); err != nil {
if err := utils.ReadYAMLStrict(loaded[config.BundleYAML], &b.bundle); err != nil {
return err
}
err = os.RemoveAll(filepath.Join(b.tmp, "blobs")) // clear tmp dir
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/bundle/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func (op *ociProvider) LoadBundle(opts types.BundlePullOptions, _ int) (*types.U
if err != nil {
return nil, nil, err
}
if err := zarfUtils.ReadYaml(loaded[config.BundleYAML], &bundle); err != nil {
if err := utils.ReadYAMLStrict(loaded[config.BundleYAML], &bundle); err != nil {
return nil, nil, err
}

Expand Down
14 changes: 7 additions & 7 deletions src/pkg/bundle/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (
"fmt"
"strings"

"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/pkg/sources"
"github.com/defenseunicorns/uds-cli/src/pkg/utils"
"github.com/defenseunicorns/uds-cli/src/types"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager"
"github.com/defenseunicorns/zarf/src/pkg/utils"
zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils"
zarfTypes "github.com/defenseunicorns/zarf/src/types"
"golang.org/x/exp/slices"

"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/pkg/sources"
"github.com/defenseunicorns/uds-cli/src/types"
)

// Remove removes packages deployed from a bundle
Expand Down Expand Up @@ -48,7 +48,7 @@ func (b *Bundle) Remove() error {
}

// read the bundle's metadata into memory
if err := utils.ReadYaml(loaded[config.BundleYAML], &b.bundle); err != nil {
if err := utils.ReadYAMLStrict(loaded[config.BundleYAML], &b.bundle); err != nil {
return err
}

Expand Down Expand Up @@ -87,7 +87,7 @@ func removePackages(packagesToRemove []types.Package, b *Bundle) error {
pkgCfg := zarfTypes.PackagerConfig{
PkgOpts: opts,
}
pkgTmp, err := utils.MakeTempDir(config.CommonOptions.TempDirectory)
pkgTmp, err := zarfUtils.MakeTempDir(config.CommonOptions.TempDirectory)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/bundler/fetcher/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func (f *localFetcher) GetPkgMetadata() (zarfTypes.ZarfPackage, error) {
}
zarfYAML := zarfTypes.ZarfPackage{}
zarfYAMLPath := filepath.Join(tmpDir, config.ZarfYAML)
err = zarfUtils.ReadYaml(zarfYAMLPath, &zarfYAML)
err = utils.ReadYAMLStrict(zarfYAMLPath, &zarfYAML)
if err != nil {
return zarfTypes.ZarfPackage{}, err
}
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/bundler/fetcher/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (f *remoteFetcher) GetPkgMetadata() (zarfTypes.ZarfPackage, error) {
}
zarfYAML := zarfTypes.ZarfPackage{}
zarfYAMLPath := filepath.Join(tmpDir, config.ZarfYAML)
err = zarfUtils.ReadYaml(zarfYAMLPath, &zarfYAML)
err = utils.ReadYAMLStrict(zarfYAMLPath, &zarfYAML)
if err != nil {
return zarfTypes.ZarfPackage{}, err
}
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/sources/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (r *RemoteBundle) LoadPackage(dst *layout.PackagePaths, filter filters.Comp
}

var pkg zarfTypes.ZarfPackage
if err = zarfUtils.ReadYaml(dst.ZarfYAML, &pkg); err != nil {
if err = utils.ReadYAMLStrict(dst.ZarfYAML, &pkg); err != nil {
return zarfTypes.ZarfPackage{}, nil, err
}

Expand Down
5 changes: 2 additions & 3 deletions src/pkg/sources/tarball.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager/filters"
"github.com/defenseunicorns/zarf/src/pkg/packager/sources"
zarfUtils "github.com/defenseunicorns/zarf/src/pkg/utils"
zarfTypes "github.com/defenseunicorns/zarf/src/types"
av4 "github.com/mholt/archiver/v4"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -53,7 +52,7 @@ func (t *TarballBundle) LoadPackage(dst *layout.PackagePaths, filter filters.Com
}

var pkg zarfTypes.ZarfPackage
if err = zarfUtils.ReadYaml(dst.ZarfYAML, &pkg); err != nil {
if err = utils.ReadYAMLStrict(dst.ZarfYAML, &pkg); err != nil {
return zarfTypes.ZarfPackage{}, nil, err
}

Expand Down Expand Up @@ -189,7 +188,7 @@ func (t *TarballBundle) LoadPackageMetadata(dst *layout.PackagePaths, _ bool, _

// deserialize zarf.yaml to grab checksum for validating pkg integrity
var pkg zarfTypes.ZarfPackage
err = zarfUtils.ReadYaml(dst.ZarfYAML, &pkg)
err = utils.ReadYAMLStrict(dst.ZarfYAML, &pkg)
if err != nil {
return zarfTypes.ZarfPackage{}, nil, err
}
Expand Down
18 changes: 18 additions & 0 deletions src/pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"strconv"
"strings"

goyaml "github.com/goccy/go-yaml"

"github.com/defenseunicorns/pkg/helpers"
"github.com/defenseunicorns/uds-cli/src/config"
"github.com/defenseunicorns/uds-cli/src/types"
Expand Down Expand Up @@ -156,3 +158,19 @@ func IsRegistryURL(s string) bool {

return false
}

// ReadYAMLStrict reads a YAML file into a struct, with strict parsing
func ReadYAMLStrict(path string, destConfig any) error {
message.Debugf("Reading YAML at %s", path)

file, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("failed to read file at %s: %v", path, err)
}

err = goyaml.UnmarshalWithOptions(file, destConfig, goyaml.Strict())
if err != nil {
return fmt.Errorf("failed to unmarshal YAML at %s: %v", path, err)
}
return nil
}
22 changes: 22 additions & 0 deletions src/test/bundles/07-helm-overrides/invalid/uds-bundle.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
kind: UDSBundle
decleaver marked this conversation as resolved.
Show resolved Hide resolved
metadata:
name: helm-overrides
description: testing a bundle with Helm overrides
version: 0.0.1

packages:
- name: helm-overrides
path: "../../../packages/helm"
ref: 0.0.1

overrides:
podinfo-component:
unicorn-podinfo:
values:
- path: "podinfo.replicaCount"
value: 2
# missing `variables:` key here should throw an error
- name: log_level
path: "podinfo.logLevel"
description: "Set the log level for podinfo"
default: "debug" # not overwritten!
10 changes: 10 additions & 0 deletions src/test/e2e/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,3 +601,13 @@ func TestBundleTmpDir(t *testing.T) {
err = os.RemoveAll("./customtmp")
require.NoError(t, err)
}

func TestInvalidBundle(t *testing.T) {
deployZarfInit(t)
zarfPkgPath := "src/test/packages/helm"
e2e.HelmDepUpdate(t, fmt.Sprintf("%s/unicorn-podinfo", zarfPkgPath))
e2e.CreateZarfPkg(t, zarfPkgPath, false)
bundleDir := "src/test/bundles/07-helm-overrides/invalid"
stderr := createLocalError(bundleDir, e2e.Arch)
require.Contains(t, stderr, "unknown field")
}
Loading