Skip to content

Commit

Permalink
feat: strict bundle yaml validation (#596)
Browse files Browse the repository at this point in the history
Co-authored-by: UncleGedd <42304551+UncleGedd@users.noreply.github.com>
  • Loading branch information
decleaver and UncleGedd authored May 21, 2024
1 parent e8abc6c commit a0ab70c
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 27 deletions.
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
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")
}

0 comments on commit a0ab70c

Please sign in to comment.