1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00

adding policyexceptions in Load function

Signed-off-by: Sanskarzz <sanskar.gur@gmail.com>
This commit is contained in:
Sanskarzz 2024-01-26 14:25:20 +05:30
parent 2a622b769f
commit 7377923a60
3 changed files with 61 additions and 43 deletions

View file

@ -11,6 +11,7 @@ import (
"github.com/go-git/go-billy/v5"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/data"
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/experimental"
@ -39,9 +40,11 @@ var (
vapV1Beta1 = v1beta1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicy")
vapBidningV1alpha1 = v1alpha1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicyBinding")
vapBidningV1beta1 = v1beta1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicyBinding")
exceptionV2beta1 = schema.GroupVersion(kyvernov2beta1.GroupVersion).WithKind("PolicyException")
exceptionV2 = schema.GroupVersion(kyvernov2.GroupVersion).WithKind("PolicyException")
LegacyLoader = yamlutils.GetPolicy
KubectlValidateLoader = kubectlValidateLoader
defaultLoader = func(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
defaultLoader = func(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
if experimental.UseKubectlValidate() {
return KubectlValidateLoader(bytes)
} else {
@ -50,174 +53,189 @@ var (
}
)
type loader = func([]byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error)
type loader = func([]byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error)
func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
return LoadWithLoader(nil, fs, resourcePath, paths...)
}
func LoadWithLoader(loader loader, fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func LoadWithLoader(loader loader, fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
if loader == nil {
loader = defaultLoader
}
var pols []kyvernov1.PolicyInterface
var vaps []v1alpha1.ValidatingAdmissionPolicy
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
var polex []kyvernov2beta1.PolicyException
for _, path := range paths {
if source.IsStdin(path) {
p, v, b, err := stdinLoad(loader)
p, v, b, pe, err := stdinLoad(loader)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
pols = append(pols, p...)
vaps = append(vaps, v...)
vapBindings = append(vapBindings, b...)
polex = append(polex, pe...)
} else if fs != nil {
p, v, b, err := gitLoad(loader, fs, filepath.Join(resourcePath, path))
p, v, b, pe, err := gitLoad(loader, fs, filepath.Join(resourcePath, path))
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
pols = append(pols, p...)
vaps = append(vaps, v...)
vapBindings = append(vapBindings, b...)
polex = append(polex, pe...)
} else if source.IsHttp(path) {
p, v, b, err := httpLoad(loader, path)
p, v, b, pe, err := httpLoad(loader, path)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
pols = append(pols, p...)
vaps = append(vaps, v...)
vapBindings = append(vapBindings, b...)
polex = append(polex, pe...)
} else {
p, v, b, err := fsLoad(loader, path)
p, v, b, pe, err := fsLoad(loader, path)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
pols = append(pols, p...)
vaps = append(vaps, v...)
vapBindings = append(vapBindings, b...)
polex = append(polex, pe...)
}
}
return pols, vaps, vapBindings, nil
return pols, vaps, vapBindings, polex, nil
}
func kubectlValidateLoader(content []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func kubectlValidateLoader(content []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
documents, err := extyaml.SplitDocuments(content)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
var policies []kyvernov1.PolicyInterface
var vaps []v1alpha1.ValidatingAdmissionPolicy
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
var exceptions []kyvernov2beta1.PolicyException
for _, document := range documents {
gvk, untyped, err := factory.Load(document)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
switch gvk {
case policyV1, policyV2:
typed, err := convert.To[kyvernov1.Policy](untyped)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
policies = append(policies, typed)
case clusterPolicyV1, clusterPolicyV2:
typed, err := convert.To[kyvernov1.ClusterPolicy](untyped)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
policies = append(policies, typed)
case vapV1alpha1, vapV1Beta1:
typed, err := convert.To[v1alpha1.ValidatingAdmissionPolicy](untyped)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
vaps = append(vaps, *typed)
case vapBidningV1alpha1, vapBidningV1beta1:
typed, err := convert.To[v1alpha1.ValidatingAdmissionPolicyBinding](untyped)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
vapBindings = append(vapBindings, *typed)
case exceptionV2beta1, exceptionV2:
typed, err := convert.To[kyvernov2beta1.PolicyException](untyped)
if err != nil {
return nil, nil, nil, nil, err
}
exceptions = append(exceptions, *typed)
default:
return nil, nil, nil, fmt.Errorf("policy type not supported %s", gvk)
return nil, nil, nil, nil, fmt.Errorf("policy type not supported %s", gvk)
}
}
return policies, vaps, vapBindings, nil
return policies, vaps, vapBindings, exceptions, err
}
func fsLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func fsLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
var pols []kyvernov1.PolicyInterface
var vaps []v1alpha1.ValidatingAdmissionPolicy
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
var polex []kyvernov2beta1.PolicyException
fi, err := os.Stat(filepath.Clean(path))
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
if fi.IsDir() {
files, err := os.ReadDir(path)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
for _, file := range files {
p, v, b, err := fsLoad(loader, filepath.Join(path, file.Name()))
p, v, b, pe, err := fsLoad(loader, filepath.Join(path, file.Name()))
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
pols = append(pols, p...)
vaps = append(vaps, v...)
vapBindings = append(vapBindings, b...)
polex = append(polex, pe...)
}
} else if git.IsYaml(fi) {
fileBytes, err := os.ReadFile(filepath.Clean(path)) // #nosec G304
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
p, v, b, err := loader(fileBytes)
p, v, b, pe, err := loader(fileBytes)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
pols = append(pols, p...)
vaps = append(vaps, v...)
vapBindings = append(vapBindings, b...)
polex = append(polex, pe...)
}
return pols, vaps, vapBindings, nil
return pols, vaps, vapBindings, polex, nil
}
func httpLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func httpLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, 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, nil, fmt.Errorf("failed to process %v: %v", path, err)
return nil, nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
return nil, nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
return nil, nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
}
fileBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
return nil, nil, nil, nil, fmt.Errorf("failed to process %v: %v", path, err)
}
return loader(fileBytes)
}
func gitLoad(loader loader, fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func gitLoad(loader loader, fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
file, err := fs.Open(path)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
fileBytes, err := io.ReadAll(file)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
return loader(fileBytes)
}
func stdinLoad(loader loader) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
func stdinLoad(loader loader) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, []kyvernov2beta1.PolicyException, error) {
policyStr := ""
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {

View file

@ -31,7 +31,7 @@ func TestLoad(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, _, _, err := Load(tt.fs, tt.resourcePath, tt.paths...)
_, _, _, _, err := Load(tt.fs, tt.resourcePath, tt.paths...)
if (err != nil) != tt.wantErr {
t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr)
return
@ -87,7 +87,7 @@ func TestLoadWithKubectlValidate(t *testing.T) {
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
policies, vaps, _, err := LoadWithLoader(KubectlValidateLoader, tt.fs, tt.resourcePath, tt.paths...)
policies, vaps, _, _, err := LoadWithLoader(KubectlValidateLoader, tt.fs, tt.resourcePath, tt.paths...)
if (err != nil) != tt.wantErr {
t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr)
return

View file

@ -11,7 +11,7 @@ import (
func TestExtractVariables(t *testing.T) {
loadPolicy := func(path string) kyvernov1.PolicyInterface {
t.Helper()
policies, _, _, err := Load(nil, "", path)
policies, _, _, _, err := Load(nil, "", path)
assert.NoError(t, err)
assert.Equal(t, len(policies), 1)
return policies[0]