Skip to content

Commit

Permalink
Added a default gatecheck configuration and added merge capabilities
Browse files Browse the repository at this point in the history
Previously if an explicit gatecheck configuration was not provided the
default behavior was essentially to validate nothing. Now there is a
reasonable default that can be overriden by user specified config.
  • Loading branch information
sflanker committed Oct 24, 2024
1 parent 995c1c1 commit d247327
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 10 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.22.2
require (
github.com/dustin/go-humanize v1.0.1
github.com/fatih/color v1.17.0
github.com/jarxorg/tree v0.8.1-0.20240322031358-8fd86e9e2a13
github.com/lmittmann/tint v1.0.4
github.com/pelletier/go-toml/v2 v2.2.2
github.com/spf13/cobra v1.8.0
Expand Down Expand Up @@ -39,6 +40,7 @@ require (
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/text v0.15.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

require (
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jarxorg/tree v0.8.1-0.20230804020847-bcbae2a4f938 h1:vP2rzNgpwEvBDRabXx/yYGMgXtyKqXJNsHb3ye/0iQo=
github.com/jarxorg/tree v0.8.1-0.20230804020847-bcbae2a4f938/go.mod h1:2fRvw2OxLn0EKxhJaJQQM+4Wn0JG4yiveADJQ72Bqm8=
github.com/jarxorg/tree v0.8.1-0.20240322031358-8fd86e9e2a13 h1:CMUIKnUpTG9zOjpOaLGy9f1R8bnxtJBKXUjA03rHCSA=
github.com/jarxorg/tree v0.8.1-0.20240322031358-8fd86e9e2a13/go.mod h1:2fRvw2OxLn0EKxhJaJQQM+4Wn0JG4yiveADJQ72Bqm8=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
Expand Down Expand Up @@ -194,6 +198,7 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
68 changes: 65 additions & 3 deletions pkg/pipelines/deploy.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package pipelines

import (
_ "embed"
"errors"
"fmt"
"github.com/jarxorg/tree"
"gopkg.in/yaml.v3"
"io"
"log/slog"
"os"
"path"
"portage/pkg/shell"
)
Expand Down Expand Up @@ -37,6 +41,13 @@ func (p *Deploy) preRun() error {
return nil
}

//go:embed gatecheck.defaults.yml
var gatecheckDefaultConfig string

func mkDeploymentError(cause error) error {
return fmt.Errorf("deployment Validation failed: %w", cause)
}

func (p *Deploy) Run() error {
if !p.config.Deploy.Enabled {
slog.Warn("deployment pipeline disabled, skip.")
Expand All @@ -48,15 +59,66 @@ func (p *Deploy) Run() error {

slog.Warn("deployment pipeline is a beta feature. Only gatecheck validation will be conducted.")

err := shell.GatecheckValidate(
gatecheckConfigPath := path.Join(p.config.ArtifactDir, "gatecheck-config.yml")
gatecheckConfig, err := os.OpenFile(gatecheckConfigPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
defer gatecheckConfig.Close()

if err != nil {
return mkDeploymentError(err)
}

if p.config.Deploy.GatecheckConfigFilename != "" {
customConfigFile, err := os.ReadFile(p.config.Deploy.GatecheckConfigFilename)
if err != nil {
return mkDeploymentError(err)
}

// Unmarshal the YAML into a map
var customConfig tree.Map
err = yaml.Unmarshal(customConfigFile, &customConfig)
if err != nil {
return mkDeploymentError(err)
}

var baseConfig tree.Map
err = yaml.Unmarshal([]byte(gatecheckDefaultConfig), &baseConfig)
if err != nil {
return mkDeploymentError(err)
}

// Merge the trees and write the result to gatecheckConfig os.File
mergedConfig := tree.Merge(baseConfig, customConfig, tree.MergeOptionReplaceArray|tree.MergeOptionOverrideMap)

b, err := yaml.Marshal(mergedConfig)
if err != nil {
return mkDeploymentError(err)
}
_, err = gatecheckConfig.Write(b)
if err != nil {
return mkDeploymentError(err)
}
} else {
_, err = gatecheckConfig.Write([]byte(gatecheckDefaultConfig))
if err != nil {
return mkDeploymentError(err)
}
gatecheckConfig.Close()
}

err = AddBundleFile(p.DryRunEnabled, p.runtime.bundleFilename, gatecheckConfigPath, p.Stderr)
if err != nil {
return mkDeploymentError(err)
}

err = shell.GatecheckValidate(
shell.WithDryRun(p.DryRunEnabled),
shell.WithStderr(p.Stderr),
shell.WithStdout(p.Stdout),
shell.WithTargetFile(p.runtime.bundleFilename),
shell.WithConfigFile(p.config.Deploy.GatecheckConfigFilename),
shell.WithConfigFile(gatecheckConfigPath),
)
if err != nil {
return fmt.Errorf("Deployment Validation failed: %w", err)
return mkDeploymentError(err)
}

return nil
Expand Down
25 changes: 25 additions & 0 deletions pkg/pipelines/gatecheck.defaults.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
version: "1"
grype:
# Block deployments with High or Critical vulnerabilities
severityLimit:
critical:
enabled: true
limit: 0
high:
enabled: true
limit: 0
# Ignore vulnerabilities with very low Exploit Probability Scores
epssRiskAcceptance:
enabled: true
score: 0.001
semgrep:
severityLimit:
error:
enabled: true
limit: 0
# Ignore low impact errors
impactRiskAcceptance:
enabled: true
low: true
gitleaks:
limitEnabled: true
16 changes: 9 additions & 7 deletions pkg/pipelines/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,21 +60,23 @@ func InitGatecheckBundle(config *Config, stderr io.Writer, dryRunEnabled bool) e
}

bundleFilename := path.Join(config.ArtifactDir, config.GatecheckBundleFilename)

return AddBundleFile(dryRunEnabled, bundleFilename, tempConfigFilename, stderr)
}

func AddBundleFile(dryRunEnabled bool, bundleFilename string, filename string, stderr io.Writer) error {
opts := []shell.OptionFunc{
shell.WithDryRun(dryRunEnabled),
shell.WithBundleFile(bundleFilename, tempConfigFilename),
shell.WithBundleFile(bundleFilename, filename),
shell.WithErrorOnly(stderr),
}
if _, err = os.Stat(bundleFilename); err != nil {
if _, err := os.Stat(bundleFilename); err != nil {
// The bundle file does not exist
if errors.Is(err, os.ErrNotExist) {
exitCode := shell.GatecheckBundleCreate(opts...)
return exitCode
return shell.GatecheckBundleCreate(opts...)
}
return err
}

exitCode := shell.GatecheckBundleAdd(opts...)

return exitCode
return shell.GatecheckBundleAdd(opts...)
}

0 comments on commit d247327

Please sign in to comment.