From cbeb5157d6c8a0cd9e8dcc2cd31f4510bc96471a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Wed, 6 Sep 2023 01:01:31 +0200 Subject: [PATCH] refactor: cli policy package (#8279) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Charles-Edouard Brétéché --- .../kubectl-kyverno/commands/apply/command.go | 57 +++--- .../commands/oci/push/command.go | 9 +- cmd/cli/kubectl-kyverno/commands/test/load.go | 2 +- cmd/cli/kubectl-kyverno/commands/test/test.go | 3 +- cmd/cli/kubectl-kyverno/policy/load.go | 132 +++++++++++++ cmd/cli/kubectl-kyverno/resource/resource.go | 2 +- .../kubectl-kyverno/{utils => }/source/git.go | 0 .../{utils => }/source/git_test.go | 0 .../{utils => }/source/http.go | 0 .../{utils => }/source/http_test.go | 0 .../{utils => }/source/stdin.go | 4 +- .../{utils => }/source/stdin_test.go | 4 +- .../kubectl-kyverno/utils/common/common.go | 173 +----------------- .../utils/common/common_test.go | 8 +- 14 files changed, 180 insertions(+), 214 deletions(-) create mode 100644 cmd/cli/kubectl-kyverno/policy/load.go rename cmd/cli/kubectl-kyverno/{utils => }/source/git.go (100%) rename cmd/cli/kubectl-kyverno/{utils => }/source/git_test.go (100%) rename cmd/cli/kubectl-kyverno/{utils => }/source/http.go (100%) rename cmd/cli/kubectl-kyverno/{utils => }/source/http_test.go (100%) rename cmd/cli/kubectl-kyverno/{utils => }/source/stdin.go (79%) rename cmd/cli/kubectl-kyverno/{utils => }/source/stdin_test.go (92%) diff --git a/cmd/cli/kubectl-kyverno/commands/apply/command.go b/cmd/cli/kubectl-kyverno/commands/apply/command.go index b66ed16511..c86296286a 100644 --- a/cmd/cli/kubectl-kyverno/commands/apply/command.go +++ b/cmd/cli/kubectl-kyverno/commands/apply/command.go @@ -14,12 +14,13 @@ import ( "github.com/kyverno/kyverno/api/kyverno/v1beta1" valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/color" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/policy" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/userinfo" cobrautils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/cobra" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common" reportutils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/report" sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError" - "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/source" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store" "github.com/kyverno/kyverno/pkg/autogen" "github.com/kyverno/kyverno/pkg/clients/dclient" @@ -143,8 +144,7 @@ func (c *ApplyCommandConfig) applyCommandHelper() (*common.ResultCounts, []*unst if c.UserInfoPath != "" { userInfo, err = userinfo.Load(nil, c.UserInfoPath, "") if err != nil { - fmt.Printf("Error: failed to load request info\nCause: %s\n", err) - osExit(1) + return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to load request info", err) } } variables, globalValMap, valuesMap, namespaceSelectorMap, subresources, err := common.GetVariable(c.Variables, nil, c.ValuesFile, nil, "") @@ -294,53 +294,52 @@ func (c *ApplyCommandConfig) loadResources(policies []kyvernov1.PolicyInterface, func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPolicies) (*common.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, error, []kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy) { // load policies - fs := memfs.New() var policies []kyvernov1.PolicyInterface var validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy - for _, policy := range c.PolicyPaths { - policyPaths := []string{policy} - isGit := source.IsGit(policy) + for _, path := range c.PolicyPaths { + isGit := source.IsGit(path) if isGit { - gitSourceURL, err := url.Parse(policyPaths[0]) + gitSourceURL, err := url.Parse(path) if err != nil { - fmt.Printf("Error: failed to load policies\nCause: %s\n", err) - osExit(1) + return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to load policies", err), nil, nil } pathElems := strings.Split(gitSourceURL.Path[1:], "/") if len(pathElems) <= 1 { err := fmt.Errorf("invalid URL path %s - expected https:///:owner/:repository/:branch (without --git-branch flag) OR https:///:owner/:repository/:directory (with --git-branch flag)", gitSourceURL.Path) - fmt.Printf("Error: failed to parse URL \nCause: %s\n", err) - osExit(1) + return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to parse URL", err), nil, nil } gitSourceURL.Path = strings.Join([]string{pathElems[0], pathElems[1]}, "/") repoURL := gitSourceURL.String() var gitPathToYamls string - c.GitBranch, gitPathToYamls = common.GetGitBranchOrPolicyPaths(c.GitBranch, repoURL, policyPaths) - _, cloneErr := gitutils.Clone(repoURL, fs, c.GitBranch) - if cloneErr != nil { - fmt.Printf("Error: failed to clone repository \nCause: %s\n", cloneErr) - log.Log.V(3).Info(fmt.Sprintf("failed to clone repository %v as it is not valid", repoURL), "error", cloneErr) - osExit(1) + c.GitBranch, gitPathToYamls = common.GetGitBranchOrPolicyPaths(c.GitBranch, repoURL, path) + fs := memfs.New() + if _, err := gitutils.Clone(repoURL, fs, c.GitBranch); err != nil { + log.Log.V(3).Info(fmt.Sprintf("failed to clone repository %v as it is not valid", repoURL), "error", err) + return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to clone repository", err), nil, nil } policyYamls, err := gitutils.ListYamls(fs, gitPathToYamls) if err != nil { return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("failed to list YAMLs in repository", err), nil, nil } - - policyPaths = policyYamls + for _, policyYaml := range policyYamls { + policiesFromFile, admissionPoliciesFromFile, err := policy.Load(fs, "", policyYaml) + if err != nil { + continue + } + policies = append(policies, policiesFromFile...) + validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...) + } + } else { + policiesFromFile, admissionPoliciesFromFile, err := policy.Load(nil, "", path) + if err != nil { + return nil, nil, skipInvalidPolicies, nil, sanitizederror.NewWithError("Error: failed to load policies", err), nil, nil + } + policies = append(policies, policiesFromFile...) + validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...) } - - policiesFromFile, admissionPoliciesFromFile, err := common.GetPoliciesFromPaths(fs, policyPaths, isGit, "") - if err != nil { - fmt.Printf("Error: failed to load policies\nCause: %s\n", err) - osExit(1) - } - - policies = append(policies, policiesFromFile...) - validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...) } return nil, nil, skipInvalidPolicies, nil, nil, policies, validatingAdmissionPolicies diff --git a/cmd/cli/kubectl-kyverno/commands/oci/push/command.go b/cmd/cli/kubectl-kyverno/commands/oci/push/command.go index fb3e456e23..a35b84ea8a 100644 --- a/cmd/cli/kubectl-kyverno/commands/oci/push/command.go +++ b/cmd/cli/kubectl-kyverno/commands/oci/push/command.go @@ -13,14 +13,13 @@ import ( "github.com/google/go-containerregistry/pkg/v1/static" "github.com/google/go-containerregistry/pkg/v1/types" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/commands/oci/internal" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/policy" cobrautils "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/cobra" - "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/common" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/openapi" policyutils "github.com/kyverno/kyverno/pkg/utils/policy" policyvalidation "github.com/kyverno/kyverno/pkg/validation/policy" "github.com/spf13/cobra" - "go.uber.org/multierr" "sigs.k8s.io/controller-runtime/pkg/log" ) @@ -37,9 +36,9 @@ func Command(keychain authn.Keychain) *cobra.Command { return errors.New("image reference is required") } - policies, _, errs := common.GetPolicies([]string{policyRef}) - if len(errs) != 0 { - return fmt.Errorf("unable to read policy file or directory %s: %w", policyRef, multierr.Combine(errs...)) + policies, _, err := policy.Load(nil, "", policyRef) + if err != nil { + return fmt.Errorf("unable to read policy file or directory %s: %w", policyRef, err) } openApiManager, err := openapi.NewManager(log.Log) diff --git a/cmd/cli/kubectl-kyverno/commands/test/load.go b/cmd/cli/kubectl-kyverno/commands/test/load.go index adbb8d9a4e..444073aba1 100644 --- a/cmd/cli/kubectl-kyverno/commands/test/load.go +++ b/cmd/cli/kubectl-kyverno/commands/test/load.go @@ -8,9 +8,9 @@ import ( "strings" "github.com/go-git/go-billy/v5/memfs" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test" sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError" - "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/source" gitutils "github.com/kyverno/kyverno/pkg/utils/git" ) diff --git a/cmd/cli/kubectl-kyverno/commands/test/test.go b/cmd/cli/kubectl-kyverno/commands/test/test.go index a07b5dfd13..03e13cbe1f 100644 --- a/cmd/cli/kubectl-kyverno/commands/test/test.go +++ b/cmd/cli/kubectl-kyverno/commands/test/test.go @@ -5,6 +5,7 @@ import ( "github.com/kyverno/kyverno/api/kyverno/v1beta1" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/output/pluralize" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/policy" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/test" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/userinfo" @@ -60,7 +61,7 @@ func runTest(openApiManager openapi.Manager, testCase test.TestCase, auditWarn b // policies fmt.Println(" Loading policies", "...") policyFullPath := pathutils.GetFullPaths(testCase.Test.Policies, testDir, isGit) - policies, validatingAdmissionPolicies, err := common.GetPoliciesFromPaths(testCase.Fs, policyFullPath, isGit, testDir) + policies, validatingAdmissionPolicies, err := policy.Load(testCase.Fs, testDir, policyFullPath...) if err != nil { return nil, fmt.Errorf("Error: failed to load policies (%s)", err) } diff --git a/cmd/cli/kubectl-kyverno/policy/load.go b/cmd/cli/kubectl-kyverno/policy/load.go new file mode 100644 index 0000000000..18ad6aafb8 --- /dev/null +++ b/cmd/cli/kubectl-kyverno/policy/load.go @@ -0,0 +1,132 @@ +package policy + +import ( + "bufio" + "context" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + + "github.com/go-git/go-billy/v5" + kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source" + "github.com/kyverno/kyverno/pkg/utils/git" + yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml" + "k8s.io/api/admissionregistration/v1alpha1" +) + +func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) { + var pols []kyvernov1.PolicyInterface + var vaps []v1alpha1.ValidatingAdmissionPolicy + for _, path := range paths { + if source.IsStdin(path) { + p, v, err := stdinLoad() + if err != nil { + return nil, nil, err + } + pols = append(pols, p...) + vaps = append(vaps, v...) + } else if fs != nil /* && source.IsGit(path) */ { // TODO source.IsGit(path) + p, v, err := gitLoad(fs, filepath.Join(resourcePath, path)) + if err != nil { + return nil, nil, err + } + pols = append(pols, p...) + vaps = append(vaps, v...) + } else if source.IsHttp(path) { + p, v, err := httpLoad(path) + if err != nil { + return nil, nil, err + } + pols = append(pols, p...) + vaps = append(vaps, v...) + } else { + p, v, err := fsLoad(path) + if err != nil { + return nil, nil, err + } + pols = append(pols, p...) + vaps = append(vaps, v...) + } + } + return pols, vaps, nil +} + +func fsLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) { + var pols []kyvernov1.PolicyInterface + var vaps []v1alpha1.ValidatingAdmissionPolicy + fi, err := os.Stat(filepath.Clean(path)) + if err != nil { + return nil, nil, err + } + if fi.IsDir() { + files, err := os.ReadDir(path) + if err != nil { + return nil, nil, err + } + for _, file := range files { + p, v, err := fsLoad(filepath.Join(path, file.Name())) + if err != nil { + return nil, nil, err + } + pols = append(pols, p...) + vaps = append(vaps, v...) + } + } else if git.IsYaml(fi) { + fileBytes, err := os.ReadFile(filepath.Clean(path)) // #nosec G304 + if err != nil { + return nil, nil, err + } + p, v, err := yamlutils.GetPolicy(fileBytes) + if err != nil { + return nil, nil, err + } + pols = append(pols, p...) + vaps = append(vaps, v...) + } + return pols, vaps, nil +} + +func httpLoad(path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) { + // We accept here that a random URL might be called based on user provided input. + req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, path, nil) + if err != nil { + return nil, nil, fmt.Errorf("failed to process %v: %v", path, err) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, nil, fmt.Errorf("failed to process %v: %v", path, err) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, nil, fmt.Errorf("failed to process %v: %v", path, err) + } + fileBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, nil, fmt.Errorf("failed to process %v: %v", path, err) + } + return yamlutils.GetPolicy(fileBytes) +} + +func gitLoad(fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) { + file, err := fs.Open(path) + if err != nil { + return nil, nil, err + } + fileBytes, err := io.ReadAll(file) + if err != nil { + return nil, nil, err + } + return yamlutils.GetPolicy(fileBytes) +} + +func stdinLoad() ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) { + policyStr := "" + scanner := bufio.NewScanner(os.Stdin) + for scanner.Scan() { + policyStr = policyStr + scanner.Text() + "\n" + } + return yamlutils.GetPolicy([]byte(policyStr)) +} diff --git a/cmd/cli/kubectl-kyverno/resource/resource.go b/cmd/cli/kubectl-kyverno/resource/resource.go index df92d1f6da..11b6e36bc7 100644 --- a/cmd/cli/kubectl-kyverno/resource/resource.go +++ b/cmd/cli/kubectl-kyverno/resource/resource.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/go-git/go-billy/v5" - "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/source" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source" "github.com/kyverno/kyverno/pkg/client/clientset/versioned/scheme" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml" diff --git a/cmd/cli/kubectl-kyverno/utils/source/git.go b/cmd/cli/kubectl-kyverno/source/git.go similarity index 100% rename from cmd/cli/kubectl-kyverno/utils/source/git.go rename to cmd/cli/kubectl-kyverno/source/git.go diff --git a/cmd/cli/kubectl-kyverno/utils/source/git_test.go b/cmd/cli/kubectl-kyverno/source/git_test.go similarity index 100% rename from cmd/cli/kubectl-kyverno/utils/source/git_test.go rename to cmd/cli/kubectl-kyverno/source/git_test.go diff --git a/cmd/cli/kubectl-kyverno/utils/source/http.go b/cmd/cli/kubectl-kyverno/source/http.go similarity index 100% rename from cmd/cli/kubectl-kyverno/utils/source/http.go rename to cmd/cli/kubectl-kyverno/source/http.go diff --git a/cmd/cli/kubectl-kyverno/utils/source/http_test.go b/cmd/cli/kubectl-kyverno/source/http_test.go similarity index 100% rename from cmd/cli/kubectl-kyverno/utils/source/http_test.go rename to cmd/cli/kubectl-kyverno/source/http_test.go diff --git a/cmd/cli/kubectl-kyverno/utils/source/stdin.go b/cmd/cli/kubectl-kyverno/source/stdin.go similarity index 79% rename from cmd/cli/kubectl-kyverno/utils/source/stdin.go rename to cmd/cli/kubectl-kyverno/source/stdin.go index 3858d1cbee..d38ccb02b4 100644 --- a/cmd/cli/kubectl-kyverno/utils/source/stdin.go +++ b/cmd/cli/kubectl-kyverno/source/stdin.go @@ -6,8 +6,8 @@ import ( var defaultStater = (*os.File).Stat -func IsStdin() bool { - return isStdin(defaultStater) +func IsStdin(path string) bool { + return path == "-" && isStdin(defaultStater) } func isStdin(stater func(*os.File) (os.FileInfo, error)) bool { diff --git a/cmd/cli/kubectl-kyverno/utils/source/stdin_test.go b/cmd/cli/kubectl-kyverno/source/stdin_test.go similarity index 92% rename from cmd/cli/kubectl-kyverno/utils/source/stdin_test.go rename to cmd/cli/kubectl-kyverno/source/stdin_test.go index d745906c6f..d0933f4b00 100644 --- a/cmd/cli/kubectl-kyverno/utils/source/stdin_test.go +++ b/cmd/cli/kubectl-kyverno/source/stdin_test.go @@ -9,14 +9,16 @@ import ( func TestIsStdin(t *testing.T) { tests := []struct { name string + path string want bool }{{ name: "default", + path: "-", want: false, }} for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := IsStdin(); got != tt.want { + if got := IsStdin(tt.path); got != tt.want { t.Errorf("IsInputFromPipe() = %v, want %v", got, tt.want) } }) diff --git a/cmd/cli/kubectl-kyverno/utils/common/common.go b/cmd/cli/kubectl-kyverno/utils/common/common.go index 945168dab0..9b60fed3b0 100644 --- a/cmd/cli/kubectl-kyverno/utils/common/common.go +++ b/cmd/cli/kubectl-kyverno/utils/common/common.go @@ -2,10 +2,7 @@ package common import ( "bufio" - "context" "fmt" - "io" - "net/http" "os" "path/filepath" "strings" @@ -16,8 +13,8 @@ import ( valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/policy/annotations" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource" + "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source" sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError" - "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/source" "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store" "github.com/kyverno/kyverno/pkg/autogen" "github.com/kyverno/kyverno/pkg/background/generate" @@ -30,14 +27,12 @@ import ( "github.com/kyverno/kyverno/pkg/imageverifycache" "github.com/kyverno/kyverno/pkg/logging" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" - yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml" yamlv2 "gopkg.in/yaml.v2" "k8s.io/api/admissionregistration/v1alpha1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/yaml" ) var log = logging.WithName("kubectl-kyverno") @@ -69,107 +64,6 @@ type ApplyPolicyConfig struct { Subresources []valuesapi.Subresource } -// GetPolicies - Extracting the policies from multiple YAML -func GetPolicies(paths []string) (policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, errors []error) { - for _, path := range paths { - log.V(5).Info("reading policies", "path", path) - - var ( - fileDesc os.FileInfo - err error - ) - - isHTTPPath := source.IsHttp(path) - - // path clean and retrieving file info can be possible if it's not an HTTP URL - if !isHTTPPath { - path = filepath.Clean(path) - fileDesc, err = os.Stat(path) - if err != nil { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - } - - // apply file from a directory is possible only if the path is not HTTP URL - if !isHTTPPath && fileDesc.IsDir() { - files, err := os.ReadDir(path) - if err != nil { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - - listOfFiles := make([]string, 0) - for _, file := range files { - ext := filepath.Ext(file.Name()) - if ext == "" || ext == ".yaml" || ext == ".yml" { - listOfFiles = append(listOfFiles, filepath.Join(path, file.Name())) - } - } - - policiesFromDir, admissionPoliciesFromDir, errorsFromDir := GetPolicies(listOfFiles) - errors = append(errors, errorsFromDir...) - policies = append(policies, policiesFromDir...) - validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromDir...) - } else { - var fileBytes []byte - if isHTTPPath { - // We accept here that a random URL might be called based on user provided input. - req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, path, nil) - if err != nil { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - resp, err := http.DefaultClient.Do(req) - if err != nil { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - - fileBytes, err = io.ReadAll(resp.Body) - if err != nil { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - } else { - path = filepath.Clean(path) - // We accept the risk of including a user provided file here. - fileBytes, err = os.ReadFile(path) // #nosec G304 - if err != nil { - err := fmt.Errorf("failed to process %v: %v", path, err.Error()) - errors = append(errors, err) - continue - } - } - - policiesFromFile, admissionPoliciesFromFile, errFromFile := yamlutils.GetPolicy(fileBytes) - if errFromFile != nil { - err := fmt.Errorf("failed to process %s: %v", path, errFromFile.Error()) - errors = append(errors, err) - continue - } - - policies = append(policies, policiesFromFile...) - validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...) - } - } - - log.V(3).Info("read policies", "policies", len(policies), "errors", len(errors)) - return policies, validatingAdmissionPolicies, errors -} - // RemoveDuplicateAndObjectVariables - remove duplicate variables func RemoveDuplicateAndObjectVariables(matches [][]string) string { var variableStr string @@ -217,67 +111,6 @@ func PrintMutatedOutput(mutateLogPath string, mutateLogPathIsDir bool, yaml stri return nil } -// GetPoliciesFromPaths - get policies according to the resource path -func GetPoliciesFromPaths(fs billy.Filesystem, dirPath []string, isGit bool, policyResourcePath string) (policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, err error) { - if isGit { - for _, pp := range dirPath { - filep, err := fs.Open(filepath.Join(policyResourcePath, pp)) - if err != nil { - fmt.Printf("Error: file not available with path %s: %v", filep.Name(), err.Error()) - continue - } - bytes, err := io.ReadAll(filep) - if err != nil { - fmt.Printf("Error: failed to read file %s: %v", filep.Name(), err.Error()) - continue - } - policyBytes, err := yaml.ToJSON(bytes) - if err != nil { - fmt.Printf("failed to convert to JSON: %v", err) - continue - } - policiesFromFile, admissionPoliciesFromFile, errFromFile := yamlutils.GetPolicy(policyBytes) - if errFromFile != nil { - fmt.Printf("failed to process : %v", errFromFile.Error()) - continue - } - policies = append(policies, policiesFromFile...) - validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...) - } - } else { - if len(dirPath) > 0 && dirPath[0] == "-" { - if source.IsStdin() { - policyStr := "" - scanner := bufio.NewScanner(os.Stdin) - for scanner.Scan() { - policyStr = policyStr + scanner.Text() + "\n" - } - yamlBytes := []byte(policyStr) - policies, validatingAdmissionPolicies, err = yamlutils.GetPolicy(yamlBytes) - if err != nil { - return nil, nil, sanitizederror.NewWithError("failed to extract the resources", err) - } - } - } else { - var errors []error - policies, validatingAdmissionPolicies, errors = GetPolicies(dirPath) - if len(policies) == 0 && len(validatingAdmissionPolicies) == 0 { - if len(errors) > 0 { - return nil, nil, sanitizederror.NewWithErrors("failed to read file", errors) - } - return nil, nil, sanitizederror.New(fmt.Sprintf("no file found in paths %v", dirPath)) - } - if len(errors) > 0 && log.V(1).Enabled() { - fmt.Printf("ignoring errors: \n") - for _, e := range errors { - fmt.Printf(" %v \n", e.Error()) - } - } - } - } - return -} - // GetResourceAccordingToResourcePath - get resources according to the resource path func GetResourceAccordingToResourcePath(fs billy.Filesystem, resourcePaths []string, cluster bool, policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, dClient dclient.Interface, namespace string, policyReport bool, isGit bool, policyResourcePath string, @@ -289,7 +122,7 @@ func GetResourceAccordingToResourcePath(fs billy.Filesystem, resourcePaths []str } } else { if len(resourcePaths) > 0 && resourcePaths[0] == "-" { - if source.IsStdin() { + if source.IsStdin(resourcePaths[0]) { resourceStr := "" scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { @@ -582,7 +415,7 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont return newRuleResponse, nil } -func GetGitBranchOrPolicyPaths(gitBranch, repoURL string, policyPaths []string) (string, string) { +func GetGitBranchOrPolicyPaths(gitBranch, repoURL string, policyPaths ...string) (string, string) { var gitPathToYamls string if gitBranch == "" { gitPathToYamls = "/" diff --git a/cmd/cli/kubectl-kyverno/utils/common/common_test.go b/cmd/cli/kubectl-kyverno/utils/common/common_test.go index 1016dd66c1..fc51a58dd7 100644 --- a/cmd/cli/kubectl-kyverno/utils/common/common_test.go +++ b/cmd/cli/kubectl-kyverno/utils/common/common_test.go @@ -122,7 +122,7 @@ func Test_GetGitBranchOrPolicyPaths(t *testing.T) { type TestCase struct { gitBranch string repoURL string - policyPath []string + policyPath string desiredBranch, actualBranch string desiredPathToYAMLs, actualPathToYAMLs string } @@ -130,21 +130,21 @@ func Test_GetGitBranchOrPolicyPaths(t *testing.T) { { gitBranch: "main", repoURL: "https://github.com/kyverno/policies", - policyPath: []string{"https://github.com/kyverno/policies/openshift/team-validate-ns-name/"}, + policyPath: "https://github.com/kyverno/policies/openshift/team-validate-ns-name/", desiredBranch: "main", desiredPathToYAMLs: "/openshift/team-validate-ns-name/", }, { gitBranch: "", repoURL: "https://github.com/kyverno/policies", - policyPath: []string{"https://github.com/kyverno/policies/"}, + policyPath: "https://github.com/kyverno/policies/", desiredBranch: "main", desiredPathToYAMLs: "/", }, { gitBranch: "", repoURL: "https://github.com/kyverno/policies", - policyPath: []string{"https://github.com/kyverno/policies"}, + policyPath: "https://github.com/kyverno/policies", desiredBranch: "main", desiredPathToYAMLs: "/", },