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"
|
2023-09-14 01:55:19 +02:00
|
|
|
"io"
|
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-17 22:50:17 +02:00
|
|
|
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/apis/v1alpha1"
|
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-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-09-17 22:50:17 +02:00
|
|
|
admissionregistrationv1alpha1 "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"
|
2023-09-06 16:03:51 +02:00
|
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
2020-05-29 15:32:29 +05:30
|
|
|
)
|
|
|
|
|
2021-02-02 18:43:19 +05:30
|
|
|
// GetResourceAccordingToResourcePath - get resources according to the resource path
|
2023-09-06 16:03:51 +02:00
|
|
|
func GetResourceAccordingToResourcePath(
|
2023-09-14 01:55:19 +02:00
|
|
|
out io.Writer,
|
2023-09-06 16:03:51 +02:00
|
|
|
fs billy.Filesystem,
|
|
|
|
resourcePaths []string,
|
|
|
|
cluster bool,
|
|
|
|
policies []kyvernov1.PolicyInterface,
|
2023-09-17 22:50:17 +02:00
|
|
|
validatingAdmissionPolicies []admissionregistrationv1alpha1.ValidatingAdmissionPolicy,
|
2023-09-06 16:03:51 +02:00
|
|
|
dClient dclient.Interface,
|
|
|
|
namespace string,
|
|
|
|
policyReport bool,
|
|
|
|
policyResourcePath string,
|
2022-05-17 08:19:03 +02:00
|
|
|
) (resources []*unstructured.Unstructured, err error) {
|
2023-09-06 16:03:51 +02:00
|
|
|
if fs != nil {
|
2023-09-14 01:55:19 +02:00
|
|
|
resources, err = GetResourcesWithTest(out, fs, policies, resourcePaths, policyResourcePath)
|
2021-02-02 18:43:19 +05:30
|
|
|
if err != nil {
|
2023-09-12 18:07:06 +02:00
|
|
|
return nil, fmt.Errorf("failed to extract the resources (%w)", err)
|
2021-02-02 18:43:19 +05:30
|
|
|
}
|
|
|
|
} 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 {
|
2023-09-12 18:07:06 +02:00
|
|
|
return nil, fmt.Errorf("failed to extract the resources (%w)", err)
|
2021-02-02 18:43:19 +05:30
|
|
|
}
|
|
|
|
}
|
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 {
|
2023-09-12 18:07:06 +02:00
|
|
|
return nil, fmt.Errorf("failed to parse %v (%w)", resourcePaths[0], err)
|
2022-03-21 19:31:23 +05:30
|
|
|
}
|
|
|
|
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-09-14 01:55:19 +02:00
|
|
|
resources, err = GetResources(out, 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-17 22:50:17 +02:00
|
|
|
func GetKindsFromPolicy(out io.Writer, policy kyvernov1.PolicyInterface, subresources []v1alpha1.Subresource, dClient dclient.Interface) sets.Set[string] {
|
2023-09-06 16:03:51 +02:00
|
|
|
knownkinds := sets.New[string]()
|
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 {
|
2023-09-14 01:55:19 +02:00
|
|
|
fmt.Fprintf(out, "Error: %s", err.Error())
|
2022-12-09 22:15:23 +05:30
|
|
|
continue
|
|
|
|
}
|
2023-09-06 16:03:51 +02:00
|
|
|
knownkinds.Insert(k)
|
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 {
|
2023-09-14 01:55:19 +02:00
|
|
|
fmt.Fprintf(out, "Error: %s", err.Error())
|
2022-12-09 22:15:23 +05:30
|
|
|
continue
|
|
|
|
}
|
2023-09-06 16:03:51 +02:00
|
|
|
knownkinds.Insert(k)
|
2021-09-03 16:41:13 +05:30
|
|
|
}
|
|
|
|
}
|
2023-09-06 16:03:51 +02:00
|
|
|
return knownkinds
|
2021-09-03 16:41:13 +05:30
|
|
|
}
|
2021-10-01 14:16:33 +05:30
|
|
|
|
2023-09-17 22:50:17 +02:00
|
|
|
func getKind(kind string, subresources []v1alpha1.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-17 22:50:17 +02:00
|
|
|
func getSubresourceKind(groupVersion, parentKind, subresourceName string, subresources []v1alpha1.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 {
|
2023-09-17 22:50:17 +02:00
|
|
|
if strings.ToLower(subresourceName) == strings.Split(subresource.Subresource.Name, "/")[1] {
|
|
|
|
return subresource.Subresource.Kind, nil
|
2022-12-09 22:15:23 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-09-12 18:07:06 +02:00
|
|
|
return "", fmt.Errorf("subresource %s not found for parent resource %s", subresourceName, parentKind)
|
2022-12-09 22:15:23 +05:30
|
|
|
}
|
|
|
|
|
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
|
|
|
|
}
|