mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 10:28:36 +00:00
feat: support validatingadmissionpolicybindings in CLI apply command (#9468)
* feat: support validatingadmissionpolicybindings in CLI apply command Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com> * fix linter issue Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com> --------- Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
parent
91a7a9d7e5
commit
d47684c0d9
22 changed files with 516 additions and 167 deletions
|
@ -148,11 +148,11 @@ func (c *ApplyCommandConfig) applyCommandHelper(out io.Writer) (*processor.Resul
|
|||
if err != nil {
|
||||
return rc, resources1, skipInvalidPolicies, responses1, err
|
||||
}
|
||||
rc, resources1, skipInvalidPolicies, responses1, policies, validatingAdmissionPolicies, err := c.loadPolicies(skipInvalidPolicies)
|
||||
rc, resources1, skipInvalidPolicies, responses1, policies, vaps, vapBindings, err := c.loadPolicies(skipInvalidPolicies)
|
||||
if err != nil {
|
||||
return rc, resources1, skipInvalidPolicies, responses1, err
|
||||
}
|
||||
resources, err := c.loadResources(out, policies, validatingAdmissionPolicies, dClient)
|
||||
resources, err := c.loadResources(out, policies, vaps, dClient)
|
||||
if err != nil {
|
||||
return rc, resources1, skipInvalidPolicies, responses1, err
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ func (c *ApplyCommandConfig) applyCommandHelper(out io.Writer) (*processor.Resul
|
|||
for _, policy := range policies {
|
||||
policyRulesCount += len(autogen.ComputeRules(policy))
|
||||
}
|
||||
policyRulesCount += len(validatingAdmissionPolicies)
|
||||
policyRulesCount += len(vaps)
|
||||
fmt.Fprintf(out, "\nApplying %d policy rule(s) to %d resource(s)...\n", policyRulesCount, len(resources))
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ func (c *ApplyCommandConfig) applyCommandHelper(out io.Writer) (*processor.Resul
|
|||
if err != nil {
|
||||
return rc, resources1, skipInvalidPolicies, responses1, err
|
||||
}
|
||||
responses2, err := c.applyValidatingAdmissionPolicytoResource(variables, validatingAdmissionPolicies, resources1, rc, dClient, &skipInvalidPolicies)
|
||||
responses2, err := c.applyValidatingAdmissionPolicytoResource(vaps, vapBindings, resources1, rc, dClient)
|
||||
if err != nil {
|
||||
return rc, resources1, skipInvalidPolicies, responses1, err
|
||||
}
|
||||
|
@ -198,20 +198,21 @@ func (c *ApplyCommandConfig) getMutateLogPathIsDir(skipInvalidPolicies SkippedIn
|
|||
}
|
||||
|
||||
func (c *ApplyCommandConfig) applyValidatingAdmissionPolicytoResource(
|
||||
variables *variables.Variables,
|
||||
validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy,
|
||||
vaps []v1alpha1.ValidatingAdmissionPolicy,
|
||||
vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding,
|
||||
resources []*unstructured.Unstructured,
|
||||
rc *processor.ResultCounts,
|
||||
dClient dclient.Interface,
|
||||
skipInvalidPolicies *SkippedInvalidPolicies,
|
||||
) ([]engineapi.EngineResponse, error) {
|
||||
var responses []engineapi.EngineResponse
|
||||
for _, resource := range resources {
|
||||
processor := processor.ValidatingAdmissionPolicyProcessor{
|
||||
Policies: validatingAdmissionPolicies,
|
||||
Policies: vaps,
|
||||
Bindings: vapBindings,
|
||||
Resource: resource,
|
||||
PolicyReport: c.PolicyReport,
|
||||
Rc: rc,
|
||||
Client: dClient,
|
||||
}
|
||||
ers, err := processor.ApplyPolicyOnResource()
|
||||
if err != nil {
|
||||
|
@ -283,18 +284,19 @@ func (c *ApplyCommandConfig) applyPolicytoResource(
|
|||
return &rc, resources, responses, nil
|
||||
}
|
||||
|
||||
func (c *ApplyCommandConfig) loadResources(out io.Writer, policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, dClient dclient.Interface) ([]*unstructured.Unstructured, error) {
|
||||
resources, err := common.GetResourceAccordingToResourcePath(out, nil, c.ResourcePaths, c.Cluster, policies, validatingAdmissionPolicies, dClient, c.Namespace, c.PolicyReport, "")
|
||||
func (c *ApplyCommandConfig) loadResources(out io.Writer, policies []kyvernov1.PolicyInterface, vap []v1alpha1.ValidatingAdmissionPolicy, dClient dclient.Interface) ([]*unstructured.Unstructured, error) {
|
||||
resources, err := common.GetResourceAccordingToResourcePath(out, nil, c.ResourcePaths, c.Cluster, policies, vap, dClient, c.Namespace, c.PolicyReport, "")
|
||||
if err != nil {
|
||||
return resources, fmt.Errorf("failed to load resources (%w)", err)
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPolicies) (*processor.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, []kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPolicies) (*processor.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, []kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
// load policies
|
||||
var policies []kyvernov1.PolicyInterface
|
||||
var validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
|
||||
|
||||
for _, path := range c.PolicyPaths {
|
||||
isGit := source.IsGit(path)
|
||||
|
@ -302,13 +304,13 @@ func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPoli
|
|||
if isGit {
|
||||
gitSourceURL, err := url.Parse(path)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, fmt.Errorf("failed to load policies (%w)", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, nil, fmt.Errorf("failed to load policies (%w)", err)
|
||||
}
|
||||
|
||||
pathElems := strings.Split(gitSourceURL.Path[1:], "/")
|
||||
if len(pathElems) <= 1 {
|
||||
err := fmt.Errorf("invalid URL path %s - expected https://<any_git_source_domain>/:owner/:repository/:branch (without --git-branch flag) OR https://<any_git_source_domain>/:owner/:repository/:directory (with --git-branch flag)", gitSourceURL.Path)
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, fmt.Errorf("failed to parse URL (%w)", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, nil, fmt.Errorf("failed to parse URL (%w)", err)
|
||||
}
|
||||
gitSourceURL.Path = strings.Join([]string{pathElems[0], pathElems[1]}, "/")
|
||||
repoURL := gitSourceURL.String()
|
||||
|
@ -317,31 +319,33 @@ func (c *ApplyCommandConfig) loadPolicies(skipInvalidPolicies SkippedInvalidPoli
|
|||
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, nil, nil, fmt.Errorf("failed to clone repository (%w)", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, nil, fmt.Errorf("failed to clone repository (%w)", err)
|
||||
}
|
||||
policyYamls, err := gitutils.ListYamls(fs, gitPathToYamls)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, fmt.Errorf("failed to list YAMLs in repository (%w)", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, nil, fmt.Errorf("failed to list YAMLs in repository (%w)", err)
|
||||
}
|
||||
for _, policyYaml := range policyYamls {
|
||||
policiesFromFile, admissionPoliciesFromFile, err := policy.Load(fs, "", policyYaml)
|
||||
policiesFromFile, vapsFromFile, vapBindingsFromFile, err := policy.Load(fs, "", policyYaml)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
policies = append(policies, policiesFromFile...)
|
||||
validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...)
|
||||
vaps = append(vaps, vapsFromFile...)
|
||||
vapBindings = append(vapBindings, vapBindingsFromFile...)
|
||||
}
|
||||
} else {
|
||||
policiesFromFile, admissionPoliciesFromFile, err := policy.Load(nil, "", path)
|
||||
policiesFromFile, vapsFromFile, vapBindingsFromFile, err := policy.Load(nil, "", path)
|
||||
if err != nil {
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, fmt.Errorf("failed to load policies (%w)", err)
|
||||
return nil, nil, skipInvalidPolicies, nil, nil, nil, nil, fmt.Errorf("failed to load policies (%w)", err)
|
||||
}
|
||||
policies = append(policies, policiesFromFile...)
|
||||
validatingAdmissionPolicies = append(validatingAdmissionPolicies, admissionPoliciesFromFile...)
|
||||
vaps = append(vaps, vapsFromFile...)
|
||||
vapBindings = append(vapBindings, vapBindingsFromFile...)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil, skipInvalidPolicies, nil, policies, validatingAdmissionPolicies, nil
|
||||
return nil, nil, skipInvalidPolicies, nil, policies, vaps, vapBindings, nil
|
||||
}
|
||||
|
||||
func (c *ApplyCommandConfig) initStoreAndClusterClient(store *store.Store, skipInvalidPolicies SkippedInvalidPolicies) (*processor.ResultCounts, []*unstructured.Unstructured, SkippedInvalidPolicies, []engineapi.EngineResponse, error, dclient.Interface) {
|
||||
|
|
|
@ -61,7 +61,7 @@ func (o options) execute(out io.Writer, dirs ...string) error {
|
|||
}
|
||||
|
||||
func (o options) processFile(out io.Writer, path string) {
|
||||
policies, vaps, err := policy.LoadWithLoader(policy.KubectlValidateLoader, nil, "", path)
|
||||
policies, vaps, vapBindings, err := policy.LoadWithLoader(policy.KubectlValidateLoader, nil, "", path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -169,6 +169,16 @@ func (o options) processFile(out io.Writer, path string) {
|
|||
yamlBytes = append(yamlBytes, []byte("---\n")...)
|
||||
yamlBytes = append(yamlBytes, finalBytes...)
|
||||
}
|
||||
for _, vapBinding := range vapBindings {
|
||||
finalBytes, err := yaml.Marshal(vapBinding)
|
||||
if err != nil {
|
||||
fmt.Fprintf(out, " ERROR: converting to yaml: %s", err)
|
||||
fmt.Fprintln(out)
|
||||
return
|
||||
}
|
||||
yamlBytes = append(yamlBytes, []byte("---\n")...)
|
||||
yamlBytes = append(yamlBytes, finalBytes...)
|
||||
}
|
||||
if err := os.WriteFile(path, yamlBytes, os.ModePerm); err != nil {
|
||||
fmt.Fprintf(out, " ERROR: saving file (%s): %s", path, err)
|
||||
fmt.Fprintln(out)
|
||||
|
|
|
@ -86,7 +86,7 @@ func (o options) execute(ctx context.Context, dir string, keychain authn.Keychai
|
|||
if err != nil {
|
||||
return fmt.Errorf("reading layer blob: %v", err)
|
||||
}
|
||||
policies, _, err := yamlutils.GetPolicy(layerBytes)
|
||||
policies, _, _, err := yamlutils.GetPolicy(layerBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unmarshaling layer blob: %v", err)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func (o options) validate(policy string) error {
|
|||
}
|
||||
|
||||
func (o options) execute(ctx context.Context, dir string, keychain authn.Keychain) error {
|
||||
policies, _, err := policy.Load(nil, "", dir)
|
||||
policies, _, _, err := policy.Load(nil, "", dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read policy file or directory %s (%w)", dir, err)
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ func runTest(out io.Writer, testCase test.TestCase, registryAccess bool, auditWa
|
|||
// policies
|
||||
fmt.Fprintln(out, " Loading policies", "...")
|
||||
policyFullPath := path.GetFullPaths(testCase.Test.Policies, testDir, isGit)
|
||||
policies, validatingAdmissionPolicies, err := policy.Load(testCase.Fs, testDir, policyFullPath...)
|
||||
policies, validatingAdmissionPolicies, _, err := policy.Load(testCase.Fs, testDir, policyFullPath...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error: failed to load policies (%s)", err)
|
||||
}
|
||||
|
|
|
@ -35,11 +35,13 @@ var (
|
|||
policyV2 = schema.GroupVersion(kyvernov2beta1.GroupVersion).WithKind("Policy")
|
||||
clusterPolicyV1 = schema.GroupVersion(kyvernov1.GroupVersion).WithKind("ClusterPolicy")
|
||||
clusterPolicyV2 = schema.GroupVersion(kyvernov2beta1.GroupVersion).WithKind("ClusterPolicy")
|
||||
vapV1Alpha1 = v1alpha1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicy")
|
||||
vapV1alpha1 = v1alpha1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicy")
|
||||
vapV1Beta1 = v1beta1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicy")
|
||||
vapBidningV1alpha1 = v1alpha1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicyBinding")
|
||||
vapBidningV1beta1 = v1beta1.SchemeGroupVersion.WithKind("ValidatingAdmissionPolicyBinding")
|
||||
LegacyLoader = yamlutils.GetPolicy
|
||||
KubectlValidateLoader = kubectlValidateLoader
|
||||
defaultLoader = func(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
defaultLoader = func(bytes []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
if experimental.UseKubectlValidate() {
|
||||
return KubectlValidateLoader(bytes)
|
||||
} else {
|
||||
|
@ -48,159 +50,174 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
type loader = func([]byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error)
|
||||
type loader = func([]byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error)
|
||||
|
||||
func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func Load(fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
return LoadWithLoader(nil, fs, resourcePath, paths...)
|
||||
}
|
||||
|
||||
func LoadWithLoader(loader loader, fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func LoadWithLoader(loader loader, fs billy.Filesystem, resourcePath string, paths ...string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
if loader == nil {
|
||||
loader = defaultLoader
|
||||
}
|
||||
var pols []kyvernov1.PolicyInterface
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
|
||||
for _, path := range paths {
|
||||
if source.IsStdin(path) {
|
||||
p, v, err := stdinLoad(loader)
|
||||
p, v, b, err := stdinLoad(loader)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
vapBindings = append(vapBindings, b...)
|
||||
} else if fs != nil {
|
||||
p, v, err := gitLoad(loader, fs, filepath.Join(resourcePath, path))
|
||||
p, v, b, err := gitLoad(loader, fs, filepath.Join(resourcePath, path))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
vapBindings = append(vapBindings, b...)
|
||||
} else if source.IsHttp(path) {
|
||||
p, v, err := httpLoad(loader, path)
|
||||
p, v, b, err := httpLoad(loader, path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
vapBindings = append(vapBindings, b...)
|
||||
} else {
|
||||
p, v, err := fsLoad(loader, path)
|
||||
p, v, b, err := fsLoad(loader, path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
vapBindings = append(vapBindings, b...)
|
||||
}
|
||||
}
|
||||
return pols, vaps, nil
|
||||
return pols, vaps, vapBindings, nil
|
||||
}
|
||||
|
||||
func kubectlValidateLoader(content []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func kubectlValidateLoader(content []byte) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
documents, err := extyaml.SplitDocuments(content)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
var policies []kyvernov1.PolicyInterface
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
|
||||
for _, document := range documents {
|
||||
gvk, untyped, err := factory.Load(document)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
switch gvk {
|
||||
case policyV1, policyV2:
|
||||
typed, err := convert.To[kyvernov1.Policy](untyped)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
policies = append(policies, typed)
|
||||
case clusterPolicyV1, clusterPolicyV2:
|
||||
typed, err := convert.To[kyvernov1.ClusterPolicy](untyped)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
policies = append(policies, typed)
|
||||
case vapV1Alpha1, vapV1Beta1:
|
||||
case vapV1alpha1, vapV1Beta1:
|
||||
typed, err := convert.To[v1alpha1.ValidatingAdmissionPolicy](untyped)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return 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
|
||||
}
|
||||
vapBindings = append(vapBindings, *typed)
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("policy type not supported %s", gvk)
|
||||
return nil, nil, nil, fmt.Errorf("policy type not supported %s", gvk)
|
||||
}
|
||||
}
|
||||
return policies, vaps, nil
|
||||
return policies, vaps, vapBindings, nil
|
||||
}
|
||||
|
||||
func fsLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func fsLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
var pols []kyvernov1.PolicyInterface
|
||||
var vaps []v1alpha1.ValidatingAdmissionPolicy
|
||||
var vapBindings []v1alpha1.ValidatingAdmissionPolicyBinding
|
||||
fi, err := os.Stat(filepath.Clean(path))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if fi.IsDir() {
|
||||
files, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
for _, file := range files {
|
||||
p, v, err := fsLoad(loader, filepath.Join(path, file.Name()))
|
||||
p, v, b, err := fsLoad(loader, filepath.Join(path, file.Name()))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
vapBindings = append(vapBindings, b...)
|
||||
}
|
||||
} else if git.IsYaml(fi) {
|
||||
fileBytes, err := os.ReadFile(filepath.Clean(path)) // #nosec G304
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
p, v, err := loader(fileBytes)
|
||||
p, v, b, err := loader(fileBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
pols = append(pols, p...)
|
||||
vaps = append(vaps, v...)
|
||||
vapBindings = append(vapBindings, b...)
|
||||
}
|
||||
return pols, vaps, nil
|
||||
return pols, vaps, vapBindings, nil
|
||||
}
|
||||
|
||||
func httpLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func httpLoad(loader loader, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, 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)
|
||||
return nil, 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)
|
||||
return nil, 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)
|
||||
return nil, 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 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, error) {
|
||||
func gitLoad(loader loader, fs billy.Filesystem, path string) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
file, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
fileBytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
return loader(fileBytes)
|
||||
}
|
||||
|
||||
func stdinLoad(loader loader) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func stdinLoad(loader loader) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
policyStr := ""
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -105,7 +105,7 @@ func Test_NamespaceSelector(t *testing.T) {
|
|||
}
|
||||
rc := &ResultCounts{}
|
||||
for _, tc := range testcases {
|
||||
policyArray, _, _ := yamlutils.GetPolicy(tc.policy)
|
||||
policyArray, _, _, _ := yamlutils.GetPolicy(tc.policy)
|
||||
resourceArray, _ := resource.GetUnstructuredResources(tc.resource)
|
||||
processor := PolicyProcessor{
|
||||
Store: &store.Store{},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package processor
|
||||
|
||||
import (
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
"github.com/kyverno/kyverno/pkg/validatingadmissionpolicy"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
|
@ -9,15 +10,23 @@ import (
|
|||
|
||||
type ValidatingAdmissionPolicyProcessor struct {
|
||||
Policies []v1alpha1.ValidatingAdmissionPolicy
|
||||
Bindings []v1alpha1.ValidatingAdmissionPolicyBinding
|
||||
Resource *unstructured.Unstructured
|
||||
PolicyReport bool
|
||||
Rc *ResultCounts
|
||||
Client dclient.Interface
|
||||
}
|
||||
|
||||
func (p *ValidatingAdmissionPolicyProcessor) ApplyPolicyOnResource() ([]engineapi.EngineResponse, error) {
|
||||
var responses []engineapi.EngineResponse
|
||||
for _, policy := range p.Policies {
|
||||
response := validatingadmissionpolicy.Validate(policy, *p.Resource)
|
||||
policyData := validatingadmissionpolicy.NewPolicyData(policy)
|
||||
for _, binding := range p.Bindings {
|
||||
if binding.Spec.PolicyName == policy.Name {
|
||||
policyData.AddBinding(binding)
|
||||
}
|
||||
}
|
||||
response, _ := validatingadmissionpolicy.Validate(policyData, *p.Resource, p.Client)
|
||||
responses = append(responses, response)
|
||||
p.Rc.addValidatingAdmissionResponse(policy, response)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
func TestComputeClusterPolicyReports(t *testing.T) {
|
||||
policies, _, err := policy.Load(nil, "", "../_testdata/policies/cpol-pod-requirements.yaml")
|
||||
policies, _, _, err := policy.Load(nil, "", "../_testdata/policies/cpol-pod-requirements.yaml")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(policies), 1)
|
||||
policy := policies[0]
|
||||
|
@ -49,7 +49,7 @@ func TestComputeClusterPolicyReports(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestComputePolicyReports(t *testing.T) {
|
||||
policies, _, err := policy.Load(nil, "", "../_testdata/policies/pol-pod-requirements.yaml")
|
||||
policies, _, _, err := policy.Load(nil, "", "../_testdata/policies/pol-pod-requirements.yaml")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(policies), 1)
|
||||
policy := policies[0]
|
||||
|
@ -84,7 +84,7 @@ func TestComputePolicyReports(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestComputePolicyReportResultsPerPolicyOld(t *testing.T) {
|
||||
policies, _, err := policy.Load(nil, "", "../_testdata/policies/cpol-pod-requirements.yaml")
|
||||
policies, _, _, err := policy.Load(nil, "", "../_testdata/policies/cpol-pod-requirements.yaml")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(policies), 1)
|
||||
policy := policies[0]
|
||||
|
@ -162,7 +162,7 @@ func TestMergeClusterReport(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestComputePolicyReportResult(t *testing.T) {
|
||||
policies, _, err := policy.Load(nil, "", "../_testdata/policies/cpol-pod-requirements.yaml")
|
||||
policies, _, _, err := policy.Load(nil, "", "../_testdata/policies/cpol-pod-requirements.yaml")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(policies), 1)
|
||||
policy := policies[0]
|
||||
|
|
|
@ -569,7 +569,7 @@ kA==
|
|||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
policies, _, err := yamlutils.GetPolicy([]byte(test.policy))
|
||||
policies, _, _, err := yamlutils.GetPolicy([]byte(test.policy))
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 1, len(policies))
|
||||
rules := computeRules(policies[0])
|
||||
|
@ -580,7 +580,7 @@ kA==
|
|||
|
||||
func Test_PodSecurityWithNoExceptions(t *testing.T) {
|
||||
policy := []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"pod-security"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"restricted","match":{"all":[{"resources":{"kinds":["Pod"]}}]},"validate":{"podSecurity":{"level":"restricted","version":"v1.24"}}}]}}`)
|
||||
policies, _, err := yamlutils.GetPolicy([]byte(policy))
|
||||
policies, _, _, err := yamlutils.GetPolicy([]byte(policy))
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 1, len(policies))
|
||||
|
||||
|
@ -628,7 +628,7 @@ func Test_ValidateWithCELExpressions(t *testing.T) {
|
|||
}
|
||||
}
|
||||
`)
|
||||
policies, _, err := yamlutils.GetPolicy([]byte(policy))
|
||||
policies, _, _, err := yamlutils.GetPolicy([]byte(policy))
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 1, len(policies))
|
||||
|
||||
|
|
|
@ -361,7 +361,7 @@ func (c *controller) reconcileReport(
|
|||
}
|
||||
}
|
||||
if full || reevaluate || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() {
|
||||
scanner := utils.NewScanner(logger, c.engine, c.config, c.jp)
|
||||
scanner := utils.NewScanner(logger, c.engine, c.config, c.jp, c.client)
|
||||
for _, result := range scanner.ScanResource(ctx, *target, nsLabels, policy) {
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/api/kyverno"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
|
@ -20,6 +21,7 @@ type scanner struct {
|
|||
engine engineapi.Engine
|
||||
config config.Configuration
|
||||
jp jmespath.Interface
|
||||
client dclient.Interface
|
||||
}
|
||||
|
||||
type ScanResult struct {
|
||||
|
@ -36,12 +38,14 @@ func NewScanner(
|
|||
engine engineapi.Engine,
|
||||
config config.Configuration,
|
||||
jp jmespath.Interface,
|
||||
client dclient.Interface,
|
||||
) Scanner {
|
||||
return &scanner{
|
||||
logger: logger,
|
||||
engine: engine,
|
||||
config: config,
|
||||
jp: jp,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,7 +78,11 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
|
|||
}
|
||||
} else {
|
||||
pol := policy.AsValidatingAdmissionPolicy()
|
||||
res := validatingadmissionpolicy.Validate(*pol, resource)
|
||||
policyData := validatingadmissionpolicy.NewPolicyData(*pol)
|
||||
res, err := validatingadmissionpolicy.Validate(policyData, resource, s.client)
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
response = &res
|
||||
}
|
||||
results[&policies[i]] = ScanResult{response, multierr.Combine(errors...)}
|
||||
|
|
|
@ -477,7 +477,7 @@ func Test_Can_Generate_ValidatingAdmissionPolicy(t *testing.T) {
|
|||
|
||||
for _, test := range testCases {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
policies, _, err := yamlutils.GetPolicy([]byte(test.policy))
|
||||
policies, _, _, err := yamlutils.GetPolicy([]byte(test.policy))
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, 1, len(policies))
|
||||
out, _ := canGenerateVAP(policies[0].GetSpec())
|
||||
|
|
|
@ -15,58 +15,71 @@ import (
|
|||
)
|
||||
|
||||
// GetPolicy extracts policies from YAML bytes
|
||||
func GetPolicy(bytes []byte) (policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, err error) {
|
||||
func GetPolicy(bytes []byte) (policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, validatingAdmissionPolicyBindings []v1alpha1.ValidatingAdmissionPolicyBinding, err error) {
|
||||
documents, err := extyaml.SplitDocuments(bytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
for _, thisPolicyBytes := range documents {
|
||||
policyBytes, err := yaml.ToJSON(thisPolicyBytes)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to convert to JSON: %v", err)
|
||||
return nil, nil, nil, fmt.Errorf("failed to convert to JSON: %v", err)
|
||||
}
|
||||
us := &unstructured.Unstructured{}
|
||||
|
||||
if err := json.Unmarshal(policyBytes, us); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to decode policy: %v", err)
|
||||
return nil, nil, nil, fmt.Errorf("failed to decode policy: %v", err)
|
||||
}
|
||||
if us.IsList() {
|
||||
list, err := us.ToList()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to decode policy list: %v", err)
|
||||
return nil, nil, nil, fmt.Errorf("failed to decode policy list: %v", err)
|
||||
}
|
||||
|
||||
for i := range list.Items {
|
||||
item := list.Items[i]
|
||||
if policies, validatingAdmissionPolicies, err = addPolicy(policies, validatingAdmissionPolicies, &item); err != nil {
|
||||
return nil, nil, err
|
||||
if policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, err = addPolicy(policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, &item); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if policies, validatingAdmissionPolicies, err = addPolicy(policies, validatingAdmissionPolicies, us); err != nil {
|
||||
return nil, nil, err
|
||||
if policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, err = addPolicy(policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, us); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return policies, validatingAdmissionPolicies, nil
|
||||
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, err
|
||||
}
|
||||
|
||||
func addPolicy(policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, us *unstructured.Unstructured) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, error) {
|
||||
func addPolicy(policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies []v1alpha1.ValidatingAdmissionPolicy, validatingAdmissionPolicyBindings []v1alpha1.ValidatingAdmissionPolicyBinding, us *unstructured.Unstructured) ([]kyvernov1.PolicyInterface, []v1alpha1.ValidatingAdmissionPolicy, []v1alpha1.ValidatingAdmissionPolicyBinding, error) {
|
||||
kind := us.GetKind()
|
||||
|
||||
if strings.Compare(kind, "ValidatingAdmissionPolicy") == 0 {
|
||||
validatingAdmissionPolicy := v1alpha1.ValidatingAdmissionPolicy{}
|
||||
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(us.Object, &validatingAdmissionPolicy, true); err != nil {
|
||||
return policies, nil, fmt.Errorf("failed to decode policy: %v", err)
|
||||
return policies, nil, validatingAdmissionPolicyBindings, fmt.Errorf("failed to decode policy: %v", err)
|
||||
}
|
||||
|
||||
if validatingAdmissionPolicy.Kind == "" {
|
||||
log.V(3).Info("skipping file as ValidatingAdmissionPolicy.Kind not found")
|
||||
return policies, validatingAdmissionPolicies, nil
|
||||
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, nil
|
||||
}
|
||||
|
||||
validatingAdmissionPolicies = append(validatingAdmissionPolicies, validatingAdmissionPolicy)
|
||||
} else if strings.Compare(kind, "ValidatingAdmissionPolicyBinding") == 0 {
|
||||
validatingAdmissionPolicyBinding := v1alpha1.ValidatingAdmissionPolicyBinding{}
|
||||
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(us.Object, &validatingAdmissionPolicyBinding, true); err != nil {
|
||||
return policies, validatingAdmissionPolicies, nil, fmt.Errorf("failed to decode policy: %v", err)
|
||||
}
|
||||
|
||||
if validatingAdmissionPolicyBinding.Kind == "" {
|
||||
log.V(3).Info("skipping file as ValidatingAdmissionPolicyBinding.Kind not found")
|
||||
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, nil
|
||||
}
|
||||
|
||||
validatingAdmissionPolicyBindings = append(validatingAdmissionPolicyBindings, validatingAdmissionPolicyBinding)
|
||||
} else {
|
||||
var policy kyvernov1.PolicyInterface
|
||||
if us.GetKind() == "ClusterPolicy" {
|
||||
|
@ -74,19 +87,19 @@ func addPolicy(policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies
|
|||
} else if us.GetKind() == "Policy" {
|
||||
policy = &kyvernov1.Policy{}
|
||||
} else {
|
||||
return policies, validatingAdmissionPolicies, nil
|
||||
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, nil
|
||||
}
|
||||
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructuredWithValidation(us.Object, policy, true); err != nil {
|
||||
return nil, validatingAdmissionPolicies, fmt.Errorf("failed to decode policy: %v", err)
|
||||
return nil, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, fmt.Errorf("failed to decode policy: %v", err)
|
||||
}
|
||||
|
||||
if policy.GetKind() == "" {
|
||||
log.V(3).Info("skipping file as policy.TypeMeta.Kind not found")
|
||||
return policies, validatingAdmissionPolicies, nil
|
||||
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, nil
|
||||
}
|
||||
if policy.GetKind() != "ClusterPolicy" && policy.GetKind() != "Policy" {
|
||||
return nil, validatingAdmissionPolicies, fmt.Errorf("resource %s/%s is not a Policy or a ClusterPolicy", policy.GetKind(), policy.GetName())
|
||||
return nil, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, fmt.Errorf("resource %s/%s is not a Policy or a ClusterPolicy", policy.GetKind(), policy.GetName())
|
||||
}
|
||||
|
||||
if policy.GetKind() == "Policy" {
|
||||
|
@ -99,5 +112,5 @@ func addPolicy(policies []kyvernov1.PolicyInterface, validatingAdmissionPolicies
|
|||
policies = append(policies, policy)
|
||||
}
|
||||
|
||||
return policies, validatingAdmissionPolicies, nil
|
||||
return policies, validatingAdmissionPolicies, validatingAdmissionPolicyBindings, nil
|
||||
}
|
||||
|
|
|
@ -15,11 +15,12 @@ func TestGetPolicy(t *testing.T) {
|
|||
namespace string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantPolicies []policy
|
||||
validatingAdmissionPolicies []policy
|
||||
wantErr bool
|
||||
name string
|
||||
args args
|
||||
wantPolicies []policy
|
||||
vaps []policy
|
||||
vapBindings []policy
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "policy",
|
||||
args: args{
|
||||
|
@ -317,7 +318,7 @@ spec:
|
|||
validations:
|
||||
- expression: "object.spec.replicas <= 5"
|
||||
`),
|
||||
}, validatingAdmissionPolicies: []policy{
|
||||
}, vaps: []policy{
|
||||
{"ValidatingAdmissionPolicy", ""},
|
||||
},
|
||||
wantErr: false,
|
||||
|
@ -371,7 +372,7 @@ spec:
|
|||
}, wantPolicies: []policy{
|
||||
{"Policy", "ns-1"},
|
||||
},
|
||||
validatingAdmissionPolicies: []policy{
|
||||
vaps: []policy{
|
||||
{"ValidatingAdmissionPolicy", ""},
|
||||
},
|
||||
wantErr: false,
|
||||
|
@ -424,14 +425,71 @@ spec:
|
|||
}, wantPolicies: []policy{
|
||||
{"ClusterPolicy", ""},
|
||||
},
|
||||
validatingAdmissionPolicies: []policy{
|
||||
vaps: []policy{
|
||||
{"ValidatingAdmissionPolicy", ""},
|
||||
},
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "ValidatingAdmissionPolicyBinding",
|
||||
args: args{
|
||||
[]byte(`
|
||||
apiVersion: admissionregistration.k8s.io/v1alpha1
|
||||
kind: ValidatingAdmissionPolicyBinding
|
||||
metadata:
|
||||
name: "demo-binding-test.example.com"
|
||||
spec:
|
||||
policyName: "demo-policy.example.com"
|
||||
validationActions: [Deny]
|
||||
matchResources:
|
||||
namespaceSelector:
|
||||
matchLabels:
|
||||
environment: test
|
||||
`),
|
||||
}, vapBindings: []policy{
|
||||
{"ValidatingAdmissionPolicyBinding", ""},
|
||||
},
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "ValidatingAdmissionPolicy and its binding",
|
||||
args: args{
|
||||
[]byte(`
|
||||
apiVersion: admissionregistration.k8s.io/v1alpha1
|
||||
kind: ValidatingAdmissionPolicy
|
||||
metadata:
|
||||
name: "demo-policy.example.com"
|
||||
spec:
|
||||
failurePolicy: Fail
|
||||
matchConstraints:
|
||||
resourceRules:
|
||||
- apiGroups: ["apps"]
|
||||
apiVersions: ["v1"]
|
||||
operations: ["CREATE", "UPDATE"]
|
||||
resources: ["deployments"]
|
||||
validations:
|
||||
- expression: "object.spec.replicas <= 5"
|
||||
---
|
||||
apiVersion: admissionregistration.k8s.io/v1alpha1
|
||||
kind: ValidatingAdmissionPolicyBinding
|
||||
metadata:
|
||||
name: "demo-binding-test.example.com"
|
||||
spec:
|
||||
policyName: "demo-policy.example.com"
|
||||
validationActions: [Deny]
|
||||
matchResources:
|
||||
namespaceSelector:
|
||||
matchLabels:
|
||||
environment: test
|
||||
`),
|
||||
}, vaps: []policy{
|
||||
{"ValidatingAdmissionPolicy", ""},
|
||||
}, vapBindings: []policy{
|
||||
{"ValidatingAdmissionPolicyBinding", ""},
|
||||
},
|
||||
wantErr: false,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotPolicies, gotValidatingAdmissionPolicies, err := GetPolicy(tt.args.bytes)
|
||||
gotPolicies, gotValidatingAdmissionPolicies, gotBindings, err := GetPolicy(tt.args.bytes)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
|
@ -443,12 +501,17 @@ spec:
|
|||
}
|
||||
}
|
||||
|
||||
if assert.Equal(t, len(tt.validatingAdmissionPolicies), len(gotValidatingAdmissionPolicies)) {
|
||||
for i := range tt.validatingAdmissionPolicies {
|
||||
assert.Equal(t, tt.validatingAdmissionPolicies[i].kind, gotValidatingAdmissionPolicies[i].Kind)
|
||||
if assert.Equal(t, len(tt.vaps), len(gotValidatingAdmissionPolicies)) {
|
||||
for i := range tt.vaps {
|
||||
assert.Equal(t, tt.vaps[i].kind, gotValidatingAdmissionPolicies[i].Kind)
|
||||
}
|
||||
}
|
||||
|
||||
if assert.Equal(t, len(tt.vapBindings), len(gotBindings)) {
|
||||
for i := range tt.vapBindings {
|
||||
assert.Equal(t, tt.vapBindings[i].kind, gotBindings[i].Kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
68
pkg/validatingadmissionpolicy/api.go
Normal file
68
pkg/validatingadmissionpolicy/api.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package validatingadmissionpolicy
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
)
|
||||
|
||||
// Everything someone might need to validate a single ValidatingPolicyDefinition
|
||||
// against all of its registered bindings.
|
||||
type PolicyData struct {
|
||||
definition v1alpha1.ValidatingAdmissionPolicy
|
||||
bindings []v1alpha1.ValidatingAdmissionPolicyBinding
|
||||
}
|
||||
|
||||
func (p *PolicyData) AddBinding(binding v1alpha1.ValidatingAdmissionPolicyBinding) {
|
||||
p.bindings = append(p.bindings, binding)
|
||||
}
|
||||
|
||||
func (p *PolicyData) GetDefinition() v1alpha1.ValidatingAdmissionPolicy {
|
||||
return p.definition
|
||||
}
|
||||
|
||||
func (p *PolicyData) GetBindings() []v1alpha1.ValidatingAdmissionPolicyBinding {
|
||||
return p.bindings
|
||||
}
|
||||
|
||||
func NewPolicyData(policy v1alpha1.ValidatingAdmissionPolicy) PolicyData {
|
||||
return PolicyData{
|
||||
definition: policy,
|
||||
}
|
||||
}
|
||||
|
||||
type CustomNamespaceLister struct {
|
||||
dClient dclient.Interface
|
||||
}
|
||||
|
||||
func (c *CustomNamespaceLister) List(selector labels.Selector) (ret []*corev1.Namespace, err error) {
|
||||
var namespaces []*corev1.Namespace
|
||||
namespace, err := c.dClient.GetKubeClient().CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, ns := range namespace.Items {
|
||||
nsCopy := ns
|
||||
namespaces = append(namespaces, &nsCopy)
|
||||
}
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func (c *CustomNamespaceLister) Get(name string) (*corev1.Namespace, error) {
|
||||
namespace, err := c.dClient.GetKubeClient().CoreV1().Namespaces().Get(context.Background(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return namespace, nil
|
||||
}
|
||||
|
||||
func NewCustomNamespaceLister(dClient dclient.Interface) corev1listers.NamespaceLister {
|
||||
return &CustomNamespaceLister{
|
||||
dClient: dClient,
|
||||
}
|
||||
}
|
54
pkg/validatingadmissionpolicy/utils.go
Normal file
54
pkg/validatingadmissionpolicy/utils.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
package validatingadmissionpolicy
|
||||
|
||||
import (
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
)
|
||||
|
||||
func convertRules(v1alpha1rules []v1alpha1.NamedRuleWithOperations) []v1beta1.NamedRuleWithOperations {
|
||||
var v1beta1rules []v1beta1.NamedRuleWithOperations
|
||||
for _, r := range v1alpha1rules {
|
||||
v1beta1rules = append(v1beta1rules, v1beta1.NamedRuleWithOperations(r))
|
||||
}
|
||||
return v1beta1rules
|
||||
}
|
||||
|
||||
func convertValidations(v1alpha1validations []v1alpha1.Validation) []v1beta1.Validation {
|
||||
var v1beta1validations []v1beta1.Validation
|
||||
for _, v := range v1alpha1validations {
|
||||
v1beta1validations = append(v1beta1validations, v1beta1.Validation(v))
|
||||
}
|
||||
return v1beta1validations
|
||||
}
|
||||
|
||||
func convertAuditAnnotations(v1alpha1auditanns []v1alpha1.AuditAnnotation) []v1beta1.AuditAnnotation {
|
||||
var v1beta1auditanns []v1beta1.AuditAnnotation
|
||||
for _, a := range v1alpha1auditanns {
|
||||
v1beta1auditanns = append(v1beta1auditanns, v1beta1.AuditAnnotation(a))
|
||||
}
|
||||
return v1beta1auditanns
|
||||
}
|
||||
|
||||
func convertMatchConditions(v1alpha1conditions []v1alpha1.MatchCondition) []v1beta1.MatchCondition {
|
||||
var v1beta1conditions []v1beta1.MatchCondition
|
||||
for _, m := range v1alpha1conditions {
|
||||
v1beta1conditions = append(v1beta1conditions, v1beta1.MatchCondition(m))
|
||||
}
|
||||
return v1beta1conditions
|
||||
}
|
||||
|
||||
func convertVariables(v1alpha1variables []v1alpha1.Variable) []v1beta1.Variable {
|
||||
var v1beta1variables []v1beta1.Variable
|
||||
for _, v := range v1alpha1variables {
|
||||
v1beta1variables = append(v1beta1variables, v1beta1.Variable(v))
|
||||
}
|
||||
return v1beta1variables
|
||||
}
|
||||
|
||||
func convertValidationActions(v1alpha1actions []v1alpha1.ValidationAction) []v1beta1.ValidationAction {
|
||||
var v1beta1actions []v1beta1.ValidationAction
|
||||
for _, a := range v1alpha1actions {
|
||||
v1beta1actions = append(v1beta1actions, v1beta1.ValidationAction(a))
|
||||
}
|
||||
return v1beta1actions
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
celutils "github.com/kyverno/kyverno/pkg/utils/cel"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
|
@ -13,11 +14,15 @@ import (
|
|||
"golang.org/x/text/language"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
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/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/cel"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/validatingadmissionpolicy/matching"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/matchconditions"
|
||||
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
||||
)
|
||||
|
@ -60,18 +65,143 @@ func GetKinds(policy v1alpha1.ValidatingAdmissionPolicy) []string {
|
|||
return kindList
|
||||
}
|
||||
|
||||
func Validate(policy v1alpha1.ValidatingAdmissionPolicy, resource unstructured.Unstructured) engineapi.EngineResponse {
|
||||
resPath := fmt.Sprintf("%s/%s/%s", resource.GetNamespace(), resource.GetKind(), resource.GetName())
|
||||
logger.V(3).Info("applying policy on resource", "policy", policy.GetName(), "resource", resPath)
|
||||
func Validate(policyData PolicyData, resource unstructured.Unstructured, client dclient.Interface) (engineapi.EngineResponse, error) {
|
||||
var (
|
||||
gvr schema.GroupVersionResource
|
||||
a admission.Attributes
|
||||
err error
|
||||
)
|
||||
|
||||
policy := policyData.definition
|
||||
bindings := policyData.bindings
|
||||
engineResponse := engineapi.NewEngineResponse(resource, engineapi.NewValidatingAdmissionPolicy(policy), nil)
|
||||
if client != nil {
|
||||
nsLister := NewCustomNamespaceLister(client)
|
||||
matcher := validatingadmissionpolicy.NewMatcher(matching.NewMatcher(nsLister, client.GetKubeClient()))
|
||||
|
||||
// convert policy from v1alpha1 to v1beta1
|
||||
var namespaceSelector, objectSelector metav1.LabelSelector
|
||||
if policy.Spec.MatchConstraints.NamespaceSelector != nil {
|
||||
namespaceSelector = *policy.Spec.MatchConstraints.NamespaceSelector
|
||||
}
|
||||
if policy.Spec.MatchConstraints.ObjectSelector != nil {
|
||||
objectSelector = *policy.Spec.MatchConstraints.ObjectSelector
|
||||
}
|
||||
v1beta1policy := &v1beta1.ValidatingAdmissionPolicy{
|
||||
Spec: v1beta1.ValidatingAdmissionPolicySpec{
|
||||
FailurePolicy: (*v1beta1.FailurePolicyType)(policy.Spec.FailurePolicy),
|
||||
ParamKind: (*v1beta1.ParamKind)(policy.Spec.ParamKind),
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
NamespaceSelector: &namespaceSelector,
|
||||
ObjectSelector: &objectSelector,
|
||||
ResourceRules: convertRules(policy.Spec.MatchConstraints.ResourceRules),
|
||||
ExcludeResourceRules: convertRules(policy.Spec.MatchConstraints.ExcludeResourceRules),
|
||||
MatchPolicy: (*v1beta1.MatchPolicyType)(policy.Spec.MatchConstraints.MatchPolicy),
|
||||
},
|
||||
Validations: convertValidations(policy.Spec.Validations),
|
||||
AuditAnnotations: convertAuditAnnotations(policy.Spec.AuditAnnotations),
|
||||
MatchConditions: convertMatchConditions(policy.Spec.MatchConditions),
|
||||
Variables: convertVariables(policy.Spec.Variables),
|
||||
},
|
||||
}
|
||||
|
||||
// construct admission attributes
|
||||
gvr, err = client.Discovery().GetGVRFromGVK(resource.GroupVersionKind())
|
||||
if err != nil {
|
||||
return engineResponse, err
|
||||
}
|
||||
a = admission.NewAttributesRecord(resource.DeepCopyObject(), nil, resource.GroupVersionKind(), resource.GetNamespace(), resource.GetName(), gvr, "", admission.Create, nil, false, nil)
|
||||
|
||||
// check if policy matches the incoming resource
|
||||
o := admission.NewObjectInterfacesFromScheme(runtime.NewScheme())
|
||||
isMatch, _, _, err := matcher.DefinitionMatches(a, o, v1beta1policy)
|
||||
if err != nil {
|
||||
return engineResponse, err
|
||||
}
|
||||
if !isMatch {
|
||||
return engineResponse, nil
|
||||
}
|
||||
|
||||
if len(bindings) == 0 {
|
||||
a = admission.NewAttributesRecord(resource.DeepCopyObject(), nil, resource.GroupVersionKind(), resource.GetNamespace(), resource.GetName(), gvr, "", admission.Create, nil, false, nil)
|
||||
resPath := fmt.Sprintf("%s/%s/%s", a.GetNamespace(), a.GetKind().Kind, a.GetName())
|
||||
logger.V(3).Info("validate resource %s against policy %s", resPath, policy.GetName())
|
||||
return validateResource(policy, resource, a)
|
||||
} else {
|
||||
for _, binding := range bindings {
|
||||
// convert policy binding from v1alpha1 to v1beta1
|
||||
var namespaceSelector, objectSelector, paramSelector metav1.LabelSelector
|
||||
if binding.Spec.MatchResources.NamespaceSelector != nil {
|
||||
namespaceSelector = *binding.Spec.MatchResources.NamespaceSelector
|
||||
}
|
||||
if binding.Spec.MatchResources.ObjectSelector != nil {
|
||||
objectSelector = *binding.Spec.MatchResources.ObjectSelector
|
||||
}
|
||||
|
||||
var paramRef v1beta1.ParamRef
|
||||
if binding.Spec.ParamRef != nil {
|
||||
paramRef.Name = binding.Spec.ParamRef.Name
|
||||
paramRef.Namespace = binding.Spec.ParamRef.Namespace
|
||||
if binding.Spec.ParamRef.Selector != nil {
|
||||
paramRef.Selector = binding.Spec.ParamRef.Selector
|
||||
} else {
|
||||
paramRef.Selector = ¶mSelector
|
||||
}
|
||||
paramRef.ParameterNotFoundAction = (*v1beta1.ParameterNotFoundActionType)(binding.Spec.ParamRef.ParameterNotFoundAction)
|
||||
}
|
||||
|
||||
v1beta1binding := &v1beta1.ValidatingAdmissionPolicyBinding{
|
||||
Spec: v1beta1.ValidatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: binding.Spec.PolicyName,
|
||||
ParamRef: ¶mRef,
|
||||
MatchResources: &v1beta1.MatchResources{
|
||||
NamespaceSelector: &namespaceSelector,
|
||||
ObjectSelector: &objectSelector,
|
||||
ResourceRules: convertRules(binding.Spec.MatchResources.ResourceRules),
|
||||
ExcludeResourceRules: convertRules(binding.Spec.MatchResources.ExcludeResourceRules),
|
||||
MatchPolicy: (*v1beta1.MatchPolicyType)(binding.Spec.MatchResources.MatchPolicy),
|
||||
},
|
||||
ValidationActions: convertValidationActions(binding.Spec.ValidationActions),
|
||||
},
|
||||
}
|
||||
isMatch, err := matcher.BindingMatches(a, o, v1beta1binding)
|
||||
if err != nil {
|
||||
return engineResponse, err
|
||||
}
|
||||
if !isMatch {
|
||||
continue
|
||||
}
|
||||
|
||||
resPath := fmt.Sprintf("%s/%s/%s", a.GetNamespace(), a.GetKind().Kind, a.GetName())
|
||||
logger.V(3).Info("validate resource %s against policy %s with binding %s", resPath, policy.GetName(), binding.GetName())
|
||||
return validateResource(policy, resource, a)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
a = admission.NewAttributesRecord(resource.DeepCopyObject(), nil, resource.GroupVersionKind(), resource.GetNamespace(), resource.GetName(), gvr, "", admission.Create, nil, false, nil)
|
||||
resPath := fmt.Sprintf("%s/%s/%s", a.GetNamespace(), a.GetKind().Kind, a.GetName())
|
||||
logger.V(3).Info("validate resource %s against policy %s", resPath, policy.GetName())
|
||||
return validateResource(policy, resource, a)
|
||||
}
|
||||
|
||||
return engineResponse, nil
|
||||
}
|
||||
|
||||
func validateResource(policy v1alpha1.ValidatingAdmissionPolicy, resource unstructured.Unstructured, a admission.Attributes) (engineapi.EngineResponse, error) {
|
||||
startTime := time.Now()
|
||||
|
||||
validations := policy.Spec.Validations
|
||||
auditAnnotations := policy.Spec.AuditAnnotations
|
||||
matchConditions := policy.Spec.MatchConditions
|
||||
variables := policy.Spec.Variables
|
||||
engineResponse := engineapi.NewEngineResponse(resource, engineapi.NewValidatingAdmissionPolicy(policy), nil)
|
||||
policyResp := engineapi.NewPolicyResponse()
|
||||
var ruleResp *engineapi.RuleResponse
|
||||
|
||||
// compile CEL expressions
|
||||
compiler, err := celutils.NewCompiler(policy.Spec.Validations, policy.Spec.AuditAnnotations, policy.Spec.MatchConditions, policy.Spec.Variables)
|
||||
if err != nil {
|
||||
return engineResponse, err
|
||||
}
|
||||
hasParam := policy.Spec.ParamKind != nil
|
||||
optionalVars := cel.OptionalVariableDeclarations{HasParams: hasParam, HasAuthorizer: false}
|
||||
compiler.CompileVariables(optionalVars)
|
||||
|
||||
var failPolicy admissionregistrationv1.FailurePolicyType
|
||||
if policy.Spec.FailurePolicy == nil {
|
||||
|
@ -87,43 +217,16 @@ func Validate(policy v1alpha1.ValidatingAdmissionPolicy, resource unstructured.U
|
|||
matchPolicy = *policy.Spec.MatchConstraints.MatchPolicy
|
||||
}
|
||||
|
||||
engineResponse := engineapi.NewEngineResponse(resource, engineapi.NewValidatingAdmissionPolicy(policy), nil)
|
||||
policyResp := engineapi.NewPolicyResponse()
|
||||
var ruleResp *engineapi.RuleResponse
|
||||
|
||||
optionalVars := cel.OptionalVariableDeclarations{HasParams: hasParam, HasAuthorizer: false}
|
||||
|
||||
// compile CEL expressions
|
||||
compiler, err := celutils.NewCompiler(validations, auditAnnotations, matchConditions, variables)
|
||||
if err != nil {
|
||||
ruleResp = engineapi.RuleError(policy.GetName(), engineapi.Validation, "Error creating composited compiler", err)
|
||||
policyResp.Add(engineapi.NewExecutionStats(startTime, time.Now()), *ruleResp)
|
||||
engineResponse = engineResponse.WithPolicyResponse(policyResp)
|
||||
return engineResponse
|
||||
}
|
||||
compiler.CompileVariables(optionalVars)
|
||||
filter := compiler.CompileValidateExpressions(optionalVars)
|
||||
messageExpressionfilter := compiler.CompileMessageExpressions(optionalVars)
|
||||
auditAnnotationFilter := compiler.CompileAuditAnnotationsExpressions(optionalVars)
|
||||
matchConditionFilter := compiler.CompileMatchExpressions(optionalVars)
|
||||
|
||||
newMatcher := matchconditions.NewMatcher(matchConditionFilter, &failPolicy, "", string(matchPolicy), "")
|
||||
validator := validatingadmissionpolicy.NewValidator(filter, newMatcher, auditAnnotationFilter, messageExpressionfilter, nil)
|
||||
|
||||
admissionAttributes := admission.NewAttributesRecord(
|
||||
resource.DeepCopyObject(),
|
||||
nil, resource.GroupVersionKind(),
|
||||
resource.GetNamespace(),
|
||||
resource.GetName(),
|
||||
schema.GroupVersionResource{},
|
||||
"",
|
||||
admission.Create,
|
||||
nil,
|
||||
false,
|
||||
nil,
|
||||
newMatcher := matchconditions.NewMatcher(compiler.CompileMatchExpressions(optionalVars), &failPolicy, "", string(matchPolicy), "")
|
||||
validator := validatingadmissionpolicy.NewValidator(
|
||||
compiler.CompileValidateExpressions(optionalVars),
|
||||
newMatcher,
|
||||
compiler.CompileAuditAnnotationsExpressions(optionalVars),
|
||||
compiler.CompileMessageExpressions(optionalVars),
|
||||
&failPolicy,
|
||||
)
|
||||
versionedAttr, _ := admission.NewVersionedAttributes(admissionAttributes, admissionAttributes.GetKind(), nil)
|
||||
validateResult := validator.Validate(context.TODO(), schema.GroupVersionResource{}, versionedAttr, nil, nil, celconfig.RuntimeCELCostBudget, nil)
|
||||
versionedAttr, _ := admission.NewVersionedAttributes(a, a.GetKind(), nil)
|
||||
validateResult := validator.Validate(context.TODO(), a.GetResource(), versionedAttr, nil, nil, celconfig.RuntimeCELCostBudget, nil)
|
||||
|
||||
isPass := true
|
||||
for _, policyDecision := range validateResult.Decisions {
|
||||
|
@ -144,5 +247,5 @@ func Validate(policy v1alpha1.ValidatingAdmissionPolicy, resource unstructured.U
|
|||
policyResp.Add(engineapi.NewExecutionStats(startTime, time.Now()), *ruleResp)
|
||||
engineResponse = engineResponse.WithPolicyResponse(policyResp)
|
||||
|
||||
return engineResponse
|
||||
return engineResponse, nil
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ spec:
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, policy, _ := yamlutils.GetPolicy(tt.policy)
|
||||
_, policy, _, _ := yamlutils.GetPolicy(tt.policy)
|
||||
kinds := GetKinds(policy[0])
|
||||
if !reflect.DeepEqual(kinds, tt.wantKinds) {
|
||||
t.Errorf("Expected %v, got %v", tt.wantKinds, kinds)
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestNotAllowedVars_MatchSection(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyWithVarInMatch)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyWithVarInMatch)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -106,7 +106,7 @@ func TestNotAllowedVars_ExcludeSection(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -159,7 +159,7 @@ func TestNotAllowedVars_ExcludeSection_PositiveCase(t *testing.T) {
|
|||
}
|
||||
`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -193,7 +193,7 @@ func TestNotAllowedVars_JSONPatchPath(t *testing.T) {
|
|||
}
|
||||
}`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -238,7 +238,7 @@ func TestNotAllowedVars_JSONPatchPath_ContextRootPositive(t *testing.T) {
|
|||
}
|
||||
}`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyManifest)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyManifest)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -281,7 +281,7 @@ func TestNotAllowedVars_JSONPatchPath_ContextSubPositive(t *testing.T) {
|
|||
}
|
||||
}`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyManifest)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyManifest)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -315,7 +315,7 @@ func TestNotAllowedVars_JSONPatchPath_PositiveCase(t *testing.T) {
|
|||
}
|
||||
}`)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyWithVarInExclude)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -347,7 +347,7 @@ spec:
|
|||
policyJSON, err := yaml.ToJSON(policyYAML)
|
||||
assert.NilError(t, err)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyJSON)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyJSON)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -435,7 +435,7 @@ func TestNotAllowedVars_VariableFormats(t *testing.T) {
|
|||
value: "foo.com"
|
||||
`, tc.input))
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyYAML)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyYAML)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
@ -481,7 +481,7 @@ spec:
|
|||
policyJSON, err := yaml.ToJSON(policyYAML)
|
||||
assert.NilError(t, err)
|
||||
|
||||
policy, _, err := yamlutils.GetPolicy(policyJSON)
|
||||
policy, _, _, err := yamlutils.GetPolicy(policyJSON)
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = hasInvalidVariables(policy[0], false)
|
||||
|
|
Loading…
Add table
Reference in a new issue