2020-05-29 15:32:29 +05:30
|
|
|
package common
|
|
|
|
|
|
|
|
import (
|
2020-09-01 09:38:49 -07:00
|
|
|
"bufio"
|
2020-05-29 15:32:29 +05:30
|
|
|
"fmt"
|
2020-10-19 12:36:55 -07:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2021-02-02 18:43:19 +05:30
|
|
|
"strings"
|
2020-08-31 19:32:00 +05:30
|
|
|
|
2021-02-07 20:26:56 -08:00
|
|
|
"github.com/go-git/go-billy/v5"
|
2022-05-17 13:12:43 +02:00
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
2023-09-05 19:50:52 +02:00
|
|
|
valuesapi "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/values"
|
2023-09-05 01:25:06 +02:00
|
|
|
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/resource"
|
2023-09-06 01:01:31 +02:00
|
|
|
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/source"
|
2022-04-14 17:50:18 +05:30
|
|
|
sanitizederror "github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/sanitizedError"
|
2022-04-25 20:20:40 +08:00
|
|
|
"github.com/kyverno/kyverno/pkg/autogen"
|
2022-08-31 14:03:47 +08:00
|
|
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
2022-12-09 22:15:23 +05:30
|
|
|
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
2023-05-10 11:12:53 +03:00
|
|
|
"k8s.io/api/admissionregistration/v1alpha1"
|
2022-12-09 22:15:23 +05:30
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
2020-11-17 13:07:30 -08:00
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
2023-03-22 11:18:11 +01:00
|
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
2020-05-29 15:32:29 +05:30
|
|
|
)
|
|
|
|
|
2021-07-24 00:02:48 +05:30
|
|
|
// RemoveDuplicateAndObjectVariables - remove duplicate variables
|
|
|
|
func RemoveDuplicateAndObjectVariables(matches [][]string) string {
|
2021-02-02 18:43:19 +05:30
|
|
|
var variableStr string
|
|
|
|
for _, m := range matches {
|
|
|
|
for _, v := range m {
|
|
|
|
foundVariable := strings.Contains(variableStr, v)
|
|
|
|
if !foundVariable {
|
2022-01-04 17:36:33 -08:00
|
|
|
if !strings.Contains(v, "request.object") && !strings.Contains(v, "element") && v == "elementIndex" {
|
2021-07-24 00:02:48 +05:30
|
|
|
variableStr = variableStr + " " + v
|
|
|
|
}
|
2021-02-02 18:43:19 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return variableStr
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetResourceAccordingToResourcePath - get resources according to the resource path
|
2021-02-07 20:26:56 -08:00
|
|
|
func GetResourceAccordingToResourcePath(fs billy.Filesystem, resourcePaths []string,
|
2023-05-10 11:12:53 +03:00
|
|
|
cluster bool, policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, dClient dclient.Interface, namespace string, policyReport bool, isGit bool, policyResourcePath string,
|
2022-05-17 08:19:03 +02:00
|
|
|
) (resources []*unstructured.Unstructured, err error) {
|
2021-02-02 18:43:19 +05:30
|
|
|
if isGit {
|
2021-06-22 18:56:44 +05:30
|
|
|
resources, err = GetResourcesWithTest(fs, policies, resourcePaths, isGit, policyResourcePath)
|
2021-02-02 18:43:19 +05:30
|
|
|
if err != nil {
|
|
|
|
return nil, sanitizederror.NewWithError("failed to extract the resources", err)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if len(resourcePaths) > 0 && resourcePaths[0] == "-" {
|
2023-09-06 01:01:31 +02:00
|
|
|
if source.IsStdin(resourcePaths[0]) {
|
2021-02-02 18:43:19 +05:30
|
|
|
resourceStr := ""
|
|
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
|
|
for scanner.Scan() {
|
|
|
|
resourceStr = resourceStr + scanner.Text() + "\n"
|
|
|
|
}
|
|
|
|
|
|
|
|
yamlBytes := []byte(resourceStr)
|
2023-09-05 01:25:06 +02:00
|
|
|
resources, err = resource.GetUnstructuredResources(yamlBytes)
|
2021-02-02 18:43:19 +05:30
|
|
|
if err != nil {
|
|
|
|
return nil, sanitizederror.NewWithError("failed to extract the resources", err)
|
|
|
|
}
|
|
|
|
}
|
2022-03-21 19:31:23 +05:30
|
|
|
} else {
|
|
|
|
if len(resourcePaths) > 0 {
|
|
|
|
fileDesc, err := os.Stat(resourcePaths[0])
|
2022-03-15 13:30:59 +05:30
|
|
|
if err != nil {
|
2022-03-21 19:31:23 +05:30
|
|
|
return nil, err
|
2022-03-15 13:30:59 +05:30
|
|
|
}
|
2022-03-21 19:31:23 +05:30
|
|
|
if fileDesc.IsDir() {
|
2022-09-30 15:25:19 +08:00
|
|
|
files, err := os.ReadDir(resourcePaths[0])
|
2022-03-21 19:31:23 +05:30
|
|
|
if err != nil {
|
|
|
|
return nil, sanitizederror.NewWithError(fmt.Sprintf("failed to parse %v", resourcePaths[0]), err)
|
|
|
|
}
|
|
|
|
listOfFiles := make([]string, 0)
|
|
|
|
for _, file := range files {
|
|
|
|
ext := filepath.Ext(file.Name())
|
|
|
|
if ext == ".yaml" || ext == ".yml" {
|
|
|
|
listOfFiles = append(listOfFiles, filepath.Join(resourcePaths[0], file.Name()))
|
|
|
|
}
|
2022-03-15 13:30:59 +05:30
|
|
|
}
|
2022-03-21 19:31:23 +05:30
|
|
|
resourcePaths = listOfFiles
|
2022-03-15 13:30:59 +05:30
|
|
|
}
|
|
|
|
}
|
2022-03-21 19:31:23 +05:30
|
|
|
|
2023-05-10 11:12:53 +03:00
|
|
|
resources, err = GetResources(policies, validatingAdmissionPolicies, resourcePaths, dClient, cluster, namespace, policyReport)
|
2021-02-02 18:43:19 +05:30
|
|
|
if err != nil {
|
|
|
|
return resources, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return resources, err
|
2021-02-07 20:26:56 -08:00
|
|
|
}
|
2021-09-02 00:02:55 +05:30
|
|
|
|
2023-09-05 19:50:52 +02:00
|
|
|
func GetKindsFromPolicy(policy kyvernov1.PolicyInterface, subresources []valuesapi.Subresource, dClient dclient.Interface) map[string]struct{} {
|
2022-05-17 08:19:03 +02:00
|
|
|
kindOnwhichPolicyIsApplied := make(map[string]struct{})
|
2022-03-28 16:01:27 +02:00
|
|
|
for _, rule := range autogen.ComputeRules(policy) {
|
2021-09-03 16:41:13 +05:30
|
|
|
for _, kind := range rule.MatchResources.ResourceDescription.Kinds {
|
2022-12-09 22:15:23 +05:30
|
|
|
k, err := getKind(kind, subresources, dClient)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error: %s", err.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
kindOnwhichPolicyIsApplied[k] = struct{}{}
|
2021-09-03 16:41:13 +05:30
|
|
|
}
|
|
|
|
for _, kind := range rule.ExcludeResources.ResourceDescription.Kinds {
|
2022-12-09 22:15:23 +05:30
|
|
|
k, err := getKind(kind, subresources, dClient)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Printf("Error: %s", err.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
kindOnwhichPolicyIsApplied[k] = struct{}{}
|
2021-09-03 16:41:13 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
return kindOnwhichPolicyIsApplied
|
|
|
|
}
|
2021-10-01 14:16:33 +05:30
|
|
|
|
2023-09-05 19:50:52 +02:00
|
|
|
func getKind(kind string, subresources []valuesapi.Subresource, dClient dclient.Interface) (string, error) {
|
2023-03-22 17:04:32 +01:00
|
|
|
group, version, kind, subresource := kubeutils.ParseKindSelector(kind)
|
|
|
|
if subresource == "" {
|
|
|
|
return kind, nil
|
|
|
|
}
|
|
|
|
if dClient == nil {
|
|
|
|
gv := schema.GroupVersion{Group: group, Version: version}
|
|
|
|
return getSubresourceKind(gv.String(), kind, subresource, subresources)
|
|
|
|
}
|
|
|
|
gvrss, err := dClient.Discovery().FindResources(group, version, kind, subresource)
|
|
|
|
if err != nil {
|
|
|
|
return kind, err
|
|
|
|
}
|
|
|
|
if len(gvrss) != 1 {
|
|
|
|
return kind, fmt.Errorf("no unique match for kind %s", kind)
|
|
|
|
}
|
|
|
|
for _, api := range gvrss {
|
|
|
|
return api.Kind, nil
|
2022-12-09 22:15:23 +05:30
|
|
|
}
|
2023-03-22 17:04:32 +01:00
|
|
|
return kind, nil
|
2022-12-09 22:15:23 +05:30
|
|
|
}
|
|
|
|
|
2023-09-05 19:50:52 +02:00
|
|
|
func getSubresourceKind(groupVersion, parentKind, subresourceName string, subresources []valuesapi.Subresource) (string, error) {
|
2022-12-09 22:15:23 +05:30
|
|
|
for _, subresource := range subresources {
|
|
|
|
parentResourceGroupVersion := metav1.GroupVersion{
|
|
|
|
Group: subresource.ParentResource.Group,
|
|
|
|
Version: subresource.ParentResource.Version,
|
|
|
|
}.String()
|
|
|
|
if groupVersion == "" || kubeutils.GroupVersionMatches(groupVersion, parentResourceGroupVersion) {
|
|
|
|
if parentKind == subresource.ParentResource.Kind {
|
|
|
|
if strings.ToLower(subresourceName) == strings.Split(subresource.APIResource.Name, "/")[1] {
|
|
|
|
return subresource.APIResource.Kind, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "", sanitizederror.NewWithError(fmt.Sprintf("subresource %s not found for parent resource %s", subresourceName, parentKind), nil)
|
|
|
|
}
|
|
|
|
|
2023-09-06 01:01:31 +02:00
|
|
|
func GetGitBranchOrPolicyPaths(gitBranch, repoURL string, policyPaths ...string) (string, string) {
|
2022-12-02 20:03:04 +05:30
|
|
|
var gitPathToYamls string
|
|
|
|
if gitBranch == "" {
|
|
|
|
gitPathToYamls = "/"
|
|
|
|
if string(policyPaths[0][len(policyPaths[0])-1]) == "/" {
|
|
|
|
gitBranch = strings.ReplaceAll(policyPaths[0], repoURL+"/", "")
|
|
|
|
} else {
|
|
|
|
gitBranch = strings.ReplaceAll(policyPaths[0], repoURL, "")
|
|
|
|
}
|
|
|
|
if gitBranch == "" {
|
|
|
|
gitBranch = "main"
|
|
|
|
} else if string(gitBranch[0]) == "/" {
|
|
|
|
gitBranch = gitBranch[1:]
|
|
|
|
}
|
|
|
|
return gitBranch, gitPathToYamls
|
|
|
|
}
|
|
|
|
if string(policyPaths[0][len(policyPaths[0])-1]) == "/" {
|
|
|
|
gitPathToYamls = strings.ReplaceAll(policyPaths[0], repoURL+"/", "/")
|
|
|
|
} else {
|
|
|
|
gitPathToYamls = strings.ReplaceAll(policyPaths[0], repoURL, "/")
|
|
|
|
}
|
|
|
|
return gitBranch, gitPathToYamls
|
|
|
|
}
|