Skip to content

Commit

Permalink
sign
Browse files Browse the repository at this point in the history
  • Loading branch information
David Gamero committed May 20, 2024
1 parent 755e4a5 commit a974ef7
Show file tree
Hide file tree
Showing 50 changed files with 2,784 additions and 222 deletions.
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ For more information, please visit the Draft Github page: https://github.com/Azu
logrus.SetOutput(&logger.OutputSplitter{})
logrus.SetFormatter(new(logger.CustomFormatter))
},
SilenceErrors: true,
}

// Execute adds all child commands to the root command and sets flags appropriately.
Expand Down
111 changes: 111 additions & 0 deletions cmd/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package cmd

import (
"context"
"fmt"
"path"

"github.com/Azure/draft/pkg/safeguards"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

type validateCmd struct {
manifestPath string
imagePullSecret bool
}

func init() {
rootCmd.AddCommand(newValidateCmd())
}

func newValidateCmd() *cobra.Command {
vc := &validateCmd{}

var cmd = &cobra.Command{
Use: "validate",
Short: "Validates manifests against AKS best practices",
Long: `This command validates manifests against several AKS best practices.`,
RunE: func(cmd *cobra.Command, args []string) error {
if err := vc.run(cmd); err != nil {
return err
}
return nil
},
}

f := cmd.Flags()

f.StringVarP(&vc.manifestPath, "manifest", "m", "", "'manifest' asks for the path to the manifest")
f.BoolVarP(&vc.imagePullSecret, "imagePullSecret", "s", false, "'imagePullSecret' enables the Safeguard that checks for usage of an image pull secret within the manifest(s)")

return cmd
}

// run is our entry point to GetManifestResults
func (vc *validateCmd) run(c *cobra.Command) error {
if vc.manifestPath == "" {
return fmt.Errorf("path to the manifests cannot be empty")
}

// AddSafeguardCRIP just adds Container Restricted Image Pulls to the list of safeguards the client will review
// against the given manifest
if vc.imagePullSecret {
safeguards.AddSafeguardCRIP()
}

ctx := context.Background()
isDir, err := safeguards.IsDirectory(vc.manifestPath)
if err != nil {
return fmt.Errorf("not a valid file or directory: %w", err)
}

var manifestFiles []safeguards.ManifestFile
if isDir {
manifestFiles, err = safeguards.GetManifestFiles(vc.manifestPath)
if err != nil {
return err
}
} else if safeguards.IsYAML(vc.manifestPath) {
manifestFiles = append(manifestFiles, safeguards.ManifestFile{
Name: path.Base(vc.manifestPath),
Path: vc.manifestPath,
})
} else {
return fmt.Errorf("expected at least one .yaml or .yml file within given path")
}

log.Debugf("validating manifests")
manifestViolations, err := safeguards.GetManifestResults(ctx, manifestFiles)
if err != nil {
log.Errorf("validating safeguards: %s", err.Error())
return err
}

anyViolationsFound := false
for _, v := range manifestViolations {
log.Printf("Analyzing %s for violations", v.Name)
manifestHasViolations := false
// returning the full list of violations after each manifest is checked
for file, violations := range v.ObjectViolations {
log.Printf(" %s:", file)
for _, violation := range violations {
log.Printf(" ❌ %s", violation)
anyViolationsFound = true
manifestHasViolations = true
}
}
if !manifestHasViolations {
log.Printf(" ✅ no violations found.")
}
}

if anyViolationsFound {
c.SilenceUsage = true // suppress default Cobra behaviour of printing usage on all errors
return fmt.Errorf("violations found")
} else {
log.Printf("✅ No violations found in \"%s\".", vc.manifestPath)
}

return nil
}
97 changes: 97 additions & 0 deletions cmd/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package cmd

import (
"context"
"os"
"path"
"path/filepath"

"testing"

"github.com/Azure/draft/pkg/safeguards"
"github.com/stretchr/testify/assert"
)

// TestIsDirectory tests the isDirectory function for proper returns
func TestIsDirectory(t *testing.T) {
testWd, _ := os.Getwd()
pathTrue := testWd
pathFalse := path.Join(testWd, "validate.go")
pathError := ""

isDir, err := safeguards.IsDirectory(pathTrue)
assert.True(t, isDir)
assert.Nil(t, err)

isDir, err = safeguards.IsDirectory(pathFalse)
assert.False(t, isDir)
assert.Nil(t, err)

isDir, err = safeguards.IsDirectory(pathError)
assert.False(t, isDir)
assert.NotNil(t, err)
}

// TestIsYAML tests the isYAML function for proper returns
func TestIsYAML(t *testing.T) {
dirNotYaml, _ := filepath.Abs("../pkg/safeguards/tests/not-yaml")
dirYaml, _ := filepath.Abs("../pkg/safeguards/tests/all/success")
fileNotYaml, _ := filepath.Abs("../pkg/safeguards/tests/not-yaml/readme.md")
fileYaml, _ := filepath.Abs("../pkg/safeguards/tests/all/success/all-success-manifest-1.yaml")

assert.False(t, safeguards.IsYAML(fileNotYaml))
assert.True(t, safeguards.IsYAML(fileYaml))

manifestFiles, err := safeguards.GetManifestFiles(dirNotYaml)
assert.Nil(t, manifestFiles)
assert.NotNil(t, err)

manifestFiles, err = safeguards.GetManifestFiles(dirYaml)
assert.NotNil(t, manifestFiles)
assert.Nil(t, err)
}

// TestRunValidate tests the run command for `draft validate` for proper returns
func TestRunValidate(t *testing.T) {
ctx := context.TODO()
manifestFilesEmpty := []safeguards.ManifestFile{}
manifestPathDirectorySuccess, _ := filepath.Abs("../pkg/safeguards/tests/all/success")
manifestPathDirectoryError, _ := filepath.Abs("../pkg/safeguards/tests/all/error")
manifestPathFileSuccess, _ := filepath.Abs("../pkg/safeguards/tests/all/success/all-success-manifest-1.yaml")
manifestPathFileError, _ := filepath.Abs("../pkg/safeguards/tests/all/error/all-error-manifest-1.yaml")
var manifestFiles []safeguards.ManifestFile

// Scenario 1: empty manifest path should error
_, err := safeguards.GetManifestResults(ctx, manifestFilesEmpty)
assert.NotNil(t, err)

// Scenario 2a: manifest path leads to a directory of manifestFiles - expect success
manifestFiles, err = safeguards.GetManifestFiles(manifestPathDirectorySuccess)
assert.Nil(t, err)
v, err := safeguards.GetManifestResults(ctx, manifestFiles)
assert.Nil(t, err)
numViolations := countTestViolations(v)
assert.Equal(t, numViolations, 0)

// Scenario 2b: manifest path leads to a directory of manifestFiles - expect failure
manifestFiles, err = safeguards.GetManifestFiles(manifestPathDirectoryError)
assert.Nil(t, err)
v, err = safeguards.GetManifestResults(ctx, manifestFiles)
assert.Nil(t, err)
numViolations = countTestViolations(v)
assert.Greater(t, numViolations, 0)

// Scenario 3a: manifest path leads to one manifest file - expect success
manifestFiles, err = safeguards.GetManifestFiles(manifestPathFileSuccess)
v, err = safeguards.GetManifestResults(ctx, manifestFiles)
assert.Nil(t, err)
numViolations = countTestViolations(v)
assert.Equal(t, numViolations, 0)

// Scenario 3b: manifest path leads to one manifest file - expect failure
manifestFiles, err = safeguards.GetManifestFiles(manifestPathFileError)
v, err = safeguards.GetManifestResults(ctx, manifestFiles)
assert.Nil(t, err)
numViolations = countTestViolations(v)
assert.Greater(t, numViolations, 0)
}
12 changes: 12 additions & 0 deletions cmd/validate_test_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package cmd

import "github.com/Azure/draft/pkg/safeguards"

func countTestViolations(results []safeguards.ManifestResult) int {
numViolations := 0
for _, r := range results {
numViolations += len(r.ObjectViolations)
}

return numViolations
}
85 changes: 75 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,52 +12,86 @@ require (
github.com/fatih/color v1.16.0
github.com/ghodss/yaml v1.0.0
github.com/hashicorp/go-version v1.6.0
github.com/instrumenta/kubeval v0.16.1
github.com/instrumenta/kubeval v0.16.0
github.com/ivanpirog/coloredcobra v1.0.1
github.com/jbrukh/bayesian v0.0.0-20231117143245-13ae6f916c7a
github.com/manifoldco/promptui v0.9.0
github.com/microsoftgraph/msgraph-sdk-go v1.38.0
github.com/open-policy-agent/frameworks/constraint v0.0.0-20240516222118-7d1bd0255f52
github.com/open-policy-agent/gatekeeper/v3 v3.16.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
go.uber.org/mock v0.4.0
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
golang.org/x/mod v0.17.0
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.14.4
k8s.io/api v0.30.0
k8s.io/cli-runtime v0.30.0
k8s.io/client-go v0.30.0
k8s.io/api v0.29.3
k8s.io/apimachinery v0.29.3
k8s.io/cli-runtime v0.29.0
k8s.io/client-go v0.29.3
sigs.k8s.io/kustomize/api v0.17.1
sigs.k8s.io/kustomize/kyaml v0.17.0
)

require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/cjlapao/common-go v0.0.39 // indirect
github.com/containerd/containerd v1.7.14 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/cli v25.0.1+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v25.0.5+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch/v5 v5.8.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/glog v1.2.1 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/cel-go v0.17.7 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.7 // indirect
Expand All @@ -71,36 +105,67 @@ require (
github.com/microsoft/kiota-serialization-multipart-go v1.0.0 // indirect
github.com/microsoft/kiota-serialization-text-go v1.0.0 // indirect
github.com/microsoftgraph/msgraph-sdk-go-core v1.1.0 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/open-policy-agent/opa v0.63.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc6 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/std-uritemplate/std-uritemplate/go v0.0.55 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
github.com/yashtewari/glob-intersection v0.2.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.17.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240311132316-a219d84964c2 // indirect
google.golang.org/grpc v1.62.1 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apimachinery v0.30.0 // indirect
k8s.io/apiextensions-apiserver v0.29.3 // indirect
k8s.io/apiserver v0.29.3 // indirect
k8s.io/component-base v0.29.3 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
oras.land/oras-go v1.2.5 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 // indirect
sigs.k8s.io/controller-runtime v0.17.3 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
Expand Down
Loading

0 comments on commit a974ef7

Please sign in to comment.