mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
refactor: reduce store dependency in engine pkg (#6260)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
fc2285caf1
commit
7367397178
19 changed files with 398 additions and 329 deletions
|
@ -215,7 +215,7 @@ func main() {
|
||||||
configuration,
|
configuration,
|
||||||
dClient,
|
dClient,
|
||||||
rclient,
|
rclient,
|
||||||
engine.LegacyContextLoaderFactory(configMapResolver),
|
engineapi.DefaultContextLoaderFactory(configMapResolver),
|
||||||
// TODO: do we need exceptions here ?
|
// TODO: do we need exceptions here ?
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
|
|
|
@ -334,14 +334,12 @@ func (c *ApplyCommandConfig) applyCommandHelper() (rc *common.ResultCounts, reso
|
||||||
|
|
||||||
// get the user info as request info from a different file
|
// get the user info as request info from a different file
|
||||||
var userInfo v1beta1.RequestInfo
|
var userInfo v1beta1.RequestInfo
|
||||||
var subjectInfo store.Subject
|
|
||||||
if c.UserInfoPath != "" {
|
if c.UserInfoPath != "" {
|
||||||
userInfo, subjectInfo, err = common.GetUserInfoFromPath(fs, c.UserInfoPath, false, "")
|
userInfo, err = common.GetUserInfoFromPath(fs, c.UserInfoPath, false, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error: failed to load request info\nCause: %s\n", err)
|
fmt.Printf("Error: failed to load request info\nCause: %s\n", err)
|
||||||
osExit(1)
|
osExit(1)
|
||||||
}
|
}
|
||||||
store.SetSubject(subjectInfo.Subject)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.VariablesString != "" {
|
if c.VariablesString != "" {
|
||||||
|
|
|
@ -770,15 +770,13 @@ func applyPoliciesFromPath(fs billy.Filesystem, policyBytes []byte, isGit bool,
|
||||||
|
|
||||||
// get the user info as request info from a different file
|
// get the user info as request info from a different file
|
||||||
var userInfo v1beta1.RequestInfo
|
var userInfo v1beta1.RequestInfo
|
||||||
var subjectInfo store.Subject
|
|
||||||
|
|
||||||
if userInfoFile != "" {
|
if userInfoFile != "" {
|
||||||
userInfo, subjectInfo, err = common.GetUserInfoFromPath(fs, userInfoFile, isGit, policyResourcePath)
|
userInfo, err = common.GetUserInfoFromPath(fs, userInfoFile, isGit, policyResourcePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error: failed to load request info\nCause: %s\n", err)
|
fmt.Printf("Error: failed to load request info\nCause: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
store.SetSubject(subjectInfo.Subject)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
policyFullPath := getFullPath(values.Policies, policyResourcePath, isGit)
|
policyFullPath := getFullPath(values.Policies, policyResourcePath, isGit)
|
||||||
|
|
|
@ -478,7 +478,7 @@ OuterLoop:
|
||||||
cfg,
|
cfg,
|
||||||
c.Client,
|
c.Client,
|
||||||
registryclient.NewOrDie(),
|
registryclient.NewOrDie(),
|
||||||
engine.LegacyContextLoaderFactory(nil),
|
store.ContextLoaderFactory(nil),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
policyContext := engine.NewPolicyContextWithJsonContext(ctx).
|
policyContext := engine.NewPolicyContextWithJsonContext(ctx).
|
||||||
|
@ -1077,7 +1077,7 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr
|
||||||
config.NewDefaultConfiguration(),
|
config.NewDefaultConfiguration(),
|
||||||
client,
|
client,
|
||||||
nil,
|
nil,
|
||||||
engine.LegacyContextLoaderFactory(nil),
|
store.ContextLoaderFactory(nil),
|
||||||
nil,
|
nil,
|
||||||
))
|
))
|
||||||
return c, nil
|
return c, nil
|
||||||
|
@ -1148,9 +1148,8 @@ func handleGeneratePolicy(generateResponse *engineapi.EngineResponse, policyCont
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserInfoFromPath - get the request info as user info from a given path
|
// GetUserInfoFromPath - get the request info as user info from a given path
|
||||||
func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyResourcePath string) (kyvernov1beta1.RequestInfo, store.Subject, error) {
|
func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyResourcePath string) (kyvernov1beta1.RequestInfo, error) {
|
||||||
userInfo := &kyvernov1beta1.RequestInfo{}
|
userInfo := &kyvernov1beta1.RequestInfo{}
|
||||||
subjectInfo := &store.Subject{}
|
|
||||||
if isGit {
|
if isGit {
|
||||||
filep, err := fs.Open(filepath.Join(policyResourcePath, path))
|
filep, err := fs.Open(filepath.Join(policyResourcePath, path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1168,14 +1167,6 @@ func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyRes
|
||||||
if err := json.Unmarshal(userInfoBytes, userInfo); err != nil {
|
if err := json.Unmarshal(userInfoBytes, userInfo); err != nil {
|
||||||
fmt.Printf("failed to decode yaml: %v", err)
|
fmt.Printf("failed to decode yaml: %v", err)
|
||||||
}
|
}
|
||||||
subjectBytes, err := yaml.ToJSON(bytes)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("failed to convert to JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(subjectBytes, subjectInfo); err != nil {
|
|
||||||
fmt.Printf("failed to decode yaml: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var errors []error
|
var errors []error
|
||||||
pathname := filepath.Clean(filepath.Join(policyResourcePath, path))
|
pathname := filepath.Clean(filepath.Join(policyResourcePath, path))
|
||||||
|
@ -1190,13 +1181,6 @@ func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyRes
|
||||||
if err := json.Unmarshal(userInfoBytes, userInfo); err != nil {
|
if err := json.Unmarshal(userInfoBytes, userInfo); err != nil {
|
||||||
errors = append(errors, sanitizederror.NewWithError("failed to decode yaml", err))
|
errors = append(errors, sanitizederror.NewWithError("failed to decode yaml", err))
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(userInfoBytes, subjectInfo); err != nil {
|
|
||||||
errors = append(errors, sanitizederror.NewWithError("failed to decode yaml", err))
|
|
||||||
}
|
|
||||||
if len(errors) > 0 {
|
|
||||||
return *userInfo, *subjectInfo, sanitizederror.NewWithErrors("failed to read file", errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errors) > 0 && log.Log.V(1).Enabled() {
|
if len(errors) > 0 && log.Log.V(1).Enabled() {
|
||||||
fmt.Printf("ignoring errors: \n")
|
fmt.Printf("ignoring errors: \n")
|
||||||
for _, e := range errors {
|
for _, e := range errors {
|
||||||
|
@ -1204,7 +1188,7 @@ func GetUserInfoFromPath(fs billy.Filesystem, path string, isGit bool, policyRes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *userInfo, *subjectInfo, nil
|
return *userInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsGitSourcePath(policyPaths []string) bool {
|
func IsGitSourcePath(policyPaths []string) bool {
|
||||||
|
|
80
cmd/cli/kubectl-kyverno/utils/store/contextloader.go
Normal file
80
cmd/cli/kubectl-kyverno/utils/store/contextloader.go
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
|
"github.com/kyverno/kyverno/pkg/logging"
|
||||||
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ContextLoaderFactory(
|
||||||
|
cmResolver engineapi.ConfigmapResolver,
|
||||||
|
) engineapi.ContextLoaderFactory {
|
||||||
|
return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader {
|
||||||
|
inner := engineapi.DefaultContextLoaderFactory(cmResolver)
|
||||||
|
if IsMock() {
|
||||||
|
return &mockContextLoader{
|
||||||
|
logger: logging.WithName("MockContextLoaderFactory"),
|
||||||
|
policyName: policy.GetName(),
|
||||||
|
ruleName: rule.Name,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return inner(policy, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockContextLoader struct {
|
||||||
|
logger logr.Logger
|
||||||
|
policyName string
|
||||||
|
ruleName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *mockContextLoader) Load(
|
||||||
|
ctx context.Context,
|
||||||
|
client dclient.Interface,
|
||||||
|
_ registryclient.Client,
|
||||||
|
contextEntries []kyvernov1.ContextEntry,
|
||||||
|
jsonContext enginecontext.Interface,
|
||||||
|
) error {
|
||||||
|
rule := GetPolicyRule(l.policyName, l.ruleName)
|
||||||
|
if rule != nil && len(rule.Values) > 0 {
|
||||||
|
variables := rule.Values
|
||||||
|
for key, value := range variables {
|
||||||
|
if err := jsonContext.AddVariable(key, value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasRegistryAccess := GetRegistryAccess()
|
||||||
|
// Context Variable should be loaded after the values loaded from values file
|
||||||
|
for _, entry := range contextEntries {
|
||||||
|
if entry.ImageRegistry != nil && hasRegistryAccess {
|
||||||
|
rclient := GetRegistryClient()
|
||||||
|
if err := engineapi.LoadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.Variable != nil {
|
||||||
|
if err := engineapi.LoadVariable(l.logger, entry, jsonContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.APICall != nil && IsApiCallAllowed() {
|
||||||
|
if err := engineapi.LoadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rule != nil && len(rule.ForEachValues) > 0 {
|
||||||
|
for key, value := range rule.ForEachValues {
|
||||||
|
if err := jsonContext.AddVariable(key, value[GetForeachElement()]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
|
@ -20,18 +19,12 @@ type Rule struct {
|
||||||
ForEachValues map[string][]interface{} `json:"foreachValues"`
|
ForEachValues map[string][]interface{} `json:"foreachValues"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Subject struct {
|
|
||||||
Subject rbacv1.Subject `json:"subject,omitempty" yaml:"subject,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mock bool
|
mock bool
|
||||||
registryClient registryclient.Client
|
registryClient registryclient.Client
|
||||||
allowApiCalls bool
|
allowApiCalls bool
|
||||||
policies []Policy
|
policies []Policy
|
||||||
// contextVar Context
|
|
||||||
foreachElement int
|
foreachElement int
|
||||||
subject rbacv1.Subject
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetMock(m bool) {
|
func SetMock(m bool) {
|
||||||
|
@ -94,14 +87,6 @@ func GetPolicyRule(policyName string, ruleName string) *Rule {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetSubject(s rbacv1.Subject) {
|
|
||||||
subject = s
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSubject() rbacv1.Subject {
|
|
||||||
return subject
|
|
||||||
}
|
|
||||||
|
|
||||||
func AllowApiCall(allow bool) {
|
func AllowApiCall(allow bool) {
|
||||||
allowApiCalls = allow
|
allowApiCalls = allow
|
||||||
}
|
}
|
||||||
|
|
|
@ -368,7 +368,7 @@ func main() {
|
||||||
configuration,
|
configuration,
|
||||||
dClient,
|
dClient,
|
||||||
rclient,
|
rclient,
|
||||||
engine.LegacyContextLoaderFactory(configMapResolver),
|
engineapi.DefaultContextLoaderFactory(configMapResolver),
|
||||||
exceptionsLister,
|
exceptionsLister,
|
||||||
)
|
)
|
||||||
// create non leader controllers
|
// create non leader controllers
|
||||||
|
|
|
@ -315,7 +315,7 @@ func main() {
|
||||||
configuration,
|
configuration,
|
||||||
dClient,
|
dClient,
|
||||||
rclient,
|
rclient,
|
||||||
engine.LegacyContextLoaderFactory(configMapResolver),
|
engineapi.DefaultContextLoaderFactory(configMapResolver),
|
||||||
exceptionsLister,
|
exceptionsLister,
|
||||||
)
|
)
|
||||||
// setup leader election
|
// setup leader election
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package engine
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -7,123 +7,15 @@ import (
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
|
||||||
"github.com/kyverno/kyverno/pkg/engine/apicall"
|
"github.com/kyverno/kyverno/pkg/engine/apicall"
|
||||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||||
"github.com/kyverno/kyverno/pkg/logging"
|
|
||||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LegacyContextLoaderFactory(
|
func LoadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx enginecontext.Interface) (err error) {
|
||||||
cmResolver engineapi.ConfigmapResolver,
|
|
||||||
) engineapi.ContextLoaderFactory {
|
|
||||||
return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader {
|
|
||||||
if store.IsMock() {
|
|
||||||
return &mockContextLoader{
|
|
||||||
logger: logging.WithName("MockContextLoaderFactory"),
|
|
||||||
policyName: policy.GetName(),
|
|
||||||
ruleName: rule.Name,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return &contextLoader{
|
|
||||||
logger: logging.WithName("LegacyContextLoaderFactory"),
|
|
||||||
cmResolver: cmResolver,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type contextLoader struct {
|
|
||||||
logger logr.Logger
|
|
||||||
cmResolver engineapi.ConfigmapResolver
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *contextLoader) Load(
|
|
||||||
ctx context.Context,
|
|
||||||
client dclient.Interface,
|
|
||||||
rclient registryclient.Client,
|
|
||||||
exceptionSelector engineapi.PolicyExceptionSelector,
|
|
||||||
contextEntries []kyvernov1.ContextEntry,
|
|
||||||
jsonContext enginecontext.Interface,
|
|
||||||
) error {
|
|
||||||
for _, entry := range contextEntries {
|
|
||||||
if entry.ConfigMap != nil {
|
|
||||||
if err := loadConfigMap(ctx, l.logger, entry, jsonContext, l.cmResolver); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if entry.APICall != nil {
|
|
||||||
if err := loadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if entry.ImageRegistry != nil {
|
|
||||||
if err := loadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if entry.Variable != nil {
|
|
||||||
if err := loadVariable(l.logger, entry, jsonContext); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockContextLoader struct {
|
|
||||||
logger logr.Logger
|
|
||||||
policyName string
|
|
||||||
ruleName string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *mockContextLoader) Load(
|
|
||||||
ctx context.Context,
|
|
||||||
client dclient.Interface,
|
|
||||||
_ registryclient.Client,
|
|
||||||
_ engineapi.PolicyExceptionSelector,
|
|
||||||
contextEntries []kyvernov1.ContextEntry,
|
|
||||||
jsonContext enginecontext.Interface,
|
|
||||||
) error {
|
|
||||||
rule := store.GetPolicyRule(l.policyName, l.ruleName)
|
|
||||||
if rule != nil && len(rule.Values) > 0 {
|
|
||||||
variables := rule.Values
|
|
||||||
for key, value := range variables {
|
|
||||||
if err := jsonContext.AddVariable(key, value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hasRegistryAccess := store.GetRegistryAccess()
|
|
||||||
// Context Variable should be loaded after the values loaded from values file
|
|
||||||
for _, entry := range contextEntries {
|
|
||||||
if entry.ImageRegistry != nil && hasRegistryAccess {
|
|
||||||
rclient := store.GetRegistryClient()
|
|
||||||
if err := loadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if entry.Variable != nil {
|
|
||||||
if err := loadVariable(l.logger, entry, jsonContext); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if entry.APICall != nil && store.IsApiCallAllowed() {
|
|
||||||
if err := loadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rule != nil && len(rule.ForEachValues) > 0 {
|
|
||||||
for key, value := range rule.ForEachValues {
|
|
||||||
if err := jsonContext.AddVariable(key, value[store.GetForeachElement()]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx enginecontext.Interface) (err error) {
|
|
||||||
path := ""
|
path := ""
|
||||||
if entry.Variable.JMESPath != "" {
|
if entry.Variable.JMESPath != "" {
|
||||||
jp, err := variables.SubstituteAll(logger, ctx, entry.Variable.JMESPath)
|
jp, err := variables.SubstituteAll(logger, ctx, entry.Variable.JMESPath)
|
||||||
|
@ -182,7 +74,7 @@ func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx engineco
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadImageData(ctx context.Context, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) error {
|
func LoadImageData(ctx context.Context, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) error {
|
||||||
imageData, err := fetchImageData(ctx, rclient, logger, entry, enginectx)
|
imageData, err := fetchImageData(ctx, rclient, logger, entry, enginectx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -197,6 +89,29 @@ func loadImageData(ctx context.Context, rclient registryclient.Client, logger lo
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadAPIData(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, client dclient.Interface) error {
|
||||||
|
executor, err := apicall.New(ctx, entry, enginectx, client, logger)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to initialize APICall: %w", err)
|
||||||
|
}
|
||||||
|
if _, err := executor.Execute(); err != nil {
|
||||||
|
return fmt.Errorf("failed to execute APICall: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver ConfigmapResolver) error {
|
||||||
|
data, err := fetchConfigMap(ctx, logger, entry, enginectx, resolver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to retrieve config map for context entry %s: %v", entry.Name, err)
|
||||||
|
}
|
||||||
|
err = enginectx.AddContextEntry(entry.Name, data)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to add config map for context entry %s: %v", entry.Name, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func fetchImageData(ctx context.Context, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) (interface{}, error) {
|
func fetchImageData(ctx context.Context, rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface) (interface{}, error) {
|
||||||
ref, err := variables.SubstituteAll(logger, enginectx, entry.ImageRegistry.Reference)
|
ref, err := variables.SubstituteAll(logger, enginectx, entry.ImageRegistry.Reference)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -278,17 +193,6 @@ func fetchImageDataMap(ctx context.Context, rclient registryclient.Client, ref s
|
||||||
return untyped, nil
|
return untyped, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadAPIData(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, client dclient.Interface) error {
|
|
||||||
executor, err := apicall.New(ctx, entry, enginectx, client, logger)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to initialize APICall: %w", err)
|
|
||||||
}
|
|
||||||
if _, err := executor.Execute(); err != nil {
|
|
||||||
return fmt.Errorf("failed to execute APICall: %w", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func applyJMESPath(jmesPath string, data interface{}) (interface{}, error) {
|
func applyJMESPath(jmesPath string, data interface{}) (interface{}, error) {
|
||||||
jp, err := jmespath.New(jmesPath)
|
jp, err := jmespath.New(jmesPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -297,40 +201,23 @@ func applyJMESPath(jmesPath string, data interface{}) (interface{}, error) {
|
||||||
return jp.Search(data)
|
return jp.Search(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver engineapi.ConfigmapResolver) error {
|
func fetchConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver ConfigmapResolver) ([]byte, error) {
|
||||||
data, err := fetchConfigMap(ctx, logger, entry, enginectx, resolver)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to retrieve config map for context entry %s: %v", entry.Name, err)
|
|
||||||
}
|
|
||||||
err = enginectx.AddContextEntry(entry.Name, data)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to add config map for context entry %s: %v", entry.Name, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, resolver engineapi.ConfigmapResolver) ([]byte, error) {
|
|
||||||
contextData := make(map[string]interface{})
|
contextData := make(map[string]interface{})
|
||||||
|
|
||||||
name, err := variables.SubstituteAll(logger, enginectx, entry.ConfigMap.Name)
|
name, err := variables.SubstituteAll(logger, enginectx, entry.ConfigMap.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to substitute variables in context %s configMap.name %s: %v", entry.Name, entry.ConfigMap.Name, err)
|
return nil, fmt.Errorf("failed to substitute variables in context %s configMap.name %s: %v", entry.Name, entry.ConfigMap.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := variables.SubstituteAll(logger, enginectx, entry.ConfigMap.Namespace)
|
namespace, err := variables.SubstituteAll(logger, enginectx, entry.ConfigMap.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to substitute variables in context %s configMap.namespace %s: %v", entry.Name, entry.ConfigMap.Namespace, err)
|
return nil, fmt.Errorf("failed to substitute variables in context %s configMap.namespace %s: %v", entry.Name, entry.ConfigMap.Namespace, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = "default"
|
namespace = "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
obj, err := resolver.Get(ctx, namespace.(string), name.(string))
|
obj, err := resolver.Get(ctx, namespace.(string), name.(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get configmap %s/%s : %v", namespace, name, err)
|
return nil, fmt.Errorf("failed to get configmap %s/%s : %v", namespace, name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract configmap data
|
// extract configmap data
|
||||||
contextData["data"] = obj.Data
|
contextData["data"] = obj.Data
|
||||||
contextData["metadata"] = obj.ObjectMeta
|
contextData["metadata"] = obj.ObjectMeta
|
||||||
|
@ -338,6 +225,5 @@ func fetchConfigMap(ctx context.Context, logger logr.Logger, entry kyvernov1.Con
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal configmap %s/%s: %v", namespace, name, err)
|
return nil, fmt.Errorf("failed to unmarshal configmap %s/%s: %v", namespace, name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
|
@ -3,9 +3,11 @@ package api
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
|
"github.com/kyverno/kyverno/pkg/logging"
|
||||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,8 +20,52 @@ type ContextLoader interface {
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
client dclient.Interface,
|
client dclient.Interface,
|
||||||
rclient registryclient.Client,
|
rclient registryclient.Client,
|
||||||
exceptionSelector PolicyExceptionSelector,
|
|
||||||
contextEntries []kyvernov1.ContextEntry,
|
contextEntries []kyvernov1.ContextEntry,
|
||||||
jsonContext enginecontext.Interface,
|
jsonContext enginecontext.Interface,
|
||||||
) error
|
) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DefaultContextLoaderFactory(
|
||||||
|
cmResolver ConfigmapResolver,
|
||||||
|
) ContextLoaderFactory {
|
||||||
|
return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) ContextLoader {
|
||||||
|
return &contextLoader{
|
||||||
|
logger: logging.WithName("DefaultContextLoaderFactory"),
|
||||||
|
cmResolver: cmResolver,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type contextLoader struct {
|
||||||
|
logger logr.Logger
|
||||||
|
cmResolver ConfigmapResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *contextLoader) Load(
|
||||||
|
ctx context.Context,
|
||||||
|
client dclient.Interface,
|
||||||
|
rclient registryclient.Client,
|
||||||
|
contextEntries []kyvernov1.ContextEntry,
|
||||||
|
jsonContext enginecontext.Interface,
|
||||||
|
) error {
|
||||||
|
for _, entry := range contextEntries {
|
||||||
|
if entry.ConfigMap != nil {
|
||||||
|
if err := LoadConfigMap(ctx, l.logger, entry, jsonContext, l.cmResolver); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.APICall != nil {
|
||||||
|
if err := LoadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.ImageRegistry != nil {
|
||||||
|
if err := LoadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.Variable != nil {
|
||||||
|
if err := LoadVariable(l.logger, entry, jsonContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -82,7 +82,6 @@ func (e *engine) ContextLoader(
|
||||||
ctx,
|
ctx,
|
||||||
e.client,
|
e.client,
|
||||||
e.rclient,
|
e.rclient,
|
||||||
e.exceptionSelector,
|
|
||||||
contextEntries,
|
contextEntries,
|
||||||
jsonContext,
|
jsonContext,
|
||||||
)
|
)
|
||||||
|
|
|
@ -172,7 +172,7 @@ func testVerifyAndPatchImages(
|
||||||
cfg,
|
cfg,
|
||||||
nil,
|
nil,
|
||||||
rclient,
|
rclient,
|
||||||
LegacyContextLoaderFactory(cmResolver),
|
engineapi.DefaultContextLoaderFactory(cmResolver),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
return e.VerifyAndPatchImages(
|
return e.VerifyAndPatchImages(
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
client "github.com/kyverno/kyverno/pkg/clients/dclient"
|
client "github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
|
enginetest "github.com/kyverno/kyverno/pkg/engine/test"
|
||||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
|
@ -26,12 +26,16 @@ func testMutate(
|
||||||
client dclient.Interface,
|
client dclient.Interface,
|
||||||
rclient registryclient.Client,
|
rclient registryclient.Client,
|
||||||
pContext *PolicyContext,
|
pContext *PolicyContext,
|
||||||
|
contextLoader engineapi.ContextLoaderFactory,
|
||||||
) *engineapi.EngineResponse {
|
) *engineapi.EngineResponse {
|
||||||
|
if contextLoader == nil {
|
||||||
|
contextLoader = engineapi.DefaultContextLoaderFactory(nil)
|
||||||
|
}
|
||||||
e := NewEngine(
|
e := NewEngine(
|
||||||
cfg,
|
cfg,
|
||||||
client,
|
client,
|
||||||
rclient,
|
rclient,
|
||||||
LegacyContextLoaderFactory(nil),
|
contextLoader,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
return e.Mutate(
|
return e.Mutate(
|
||||||
|
@ -115,7 +119,7 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
t.Log(string(expectedPatch))
|
t.Log(string(expectedPatch))
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
|
@ -189,7 +193,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||||
}
|
}
|
||||||
|
@ -252,20 +256,6 @@ func Test_variableSubstitutionCLI(t *testing.T) {
|
||||||
|
|
||||||
expectedPatch := []byte(`{"op":"add","path":"/metadata/labels","value":{"my-environment-name":"dev1"}}`)
|
expectedPatch := []byte(`{"op":"add","path":"/metadata/labels","value":{"my-environment-name":"dev1"}}`)
|
||||||
|
|
||||||
store.SetPolicies(
|
|
||||||
store.Policy{
|
|
||||||
Name: "cm-variable-example",
|
|
||||||
Rules: []store.Rule{
|
|
||||||
{
|
|
||||||
Name: "example-configmap-lookup",
|
|
||||||
Values: map[string]interface{}{
|
|
||||||
"dictionary.data.env": "dev1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
store.SetMock(true)
|
|
||||||
var policy kyverno.ClusterPolicy
|
var policy kyverno.ClusterPolicy
|
||||||
err := json.Unmarshal(policyRaw, &policy)
|
err := json.Unmarshal(policyRaw, &policy)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -282,7 +272,26 @@ func Test_variableSubstitutionCLI(t *testing.T) {
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(
|
||||||
|
context.TODO(),
|
||||||
|
nil,
|
||||||
|
registryclient.NewOrDie(),
|
||||||
|
policyContext,
|
||||||
|
enginetest.ContextLoaderFactory(
|
||||||
|
nil,
|
||||||
|
map[string]enginetest.Policy{
|
||||||
|
"cm-variable-example": {
|
||||||
|
Rules: map[string]enginetest.Rule{
|
||||||
|
"example-configmap-lookup": {
|
||||||
|
Values: map[string]interface{}{
|
||||||
|
"dictionary.data.env": "dev1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||||
t.Log(string(expectedPatch))
|
t.Log(string(expectedPatch))
|
||||||
|
@ -391,7 +400,7 @@ func Test_chained_rules(t *testing.T) {
|
||||||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, containers[0].(map[string]interface{})["image"], "otherregistry.corp.com/foo/bash:5.0")
|
assert.Equal(t, containers[0].(map[string]interface{})["image"], "otherregistry.corp.com/foo/bash:5.0")
|
||||||
|
@ -462,7 +471,6 @@ func Test_precondition(t *testing.T) {
|
||||||
}`)
|
}`)
|
||||||
expectedPatch := []byte(`{"op":"add","path":"/metadata/labels/my-added-label","value":"test"}`)
|
expectedPatch := []byte(`{"op":"add","path":"/metadata/labels/my-added-label","value":"test"}`)
|
||||||
|
|
||||||
store.SetMock(true)
|
|
||||||
var policy kyverno.ClusterPolicy
|
var policy kyverno.ClusterPolicy
|
||||||
err := json.Unmarshal(policyRaw, &policy)
|
err := json.Unmarshal(policyRaw, &policy)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -479,7 +487,7 @@ func Test_precondition(t *testing.T) {
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, enginetest.ContextLoaderFactory(nil, nil))
|
||||||
t.Log(string(expectedPatch))
|
t.Log(string(expectedPatch))
|
||||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||||
|
@ -559,7 +567,6 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
||||||
|
|
||||||
expectedPatch := []byte(`{"op":"add","path":"/subsets/0/addresses/1","value":{"ip":"192.168.42.172"}}`)
|
expectedPatch := []byte(`{"op":"add","path":"/subsets/0/addresses/1","value":{"ip":"192.168.42.172"}}`)
|
||||||
|
|
||||||
store.SetMock(true)
|
|
||||||
var policy kyverno.ClusterPolicy
|
var policy kyverno.ClusterPolicy
|
||||||
err := json.Unmarshal(policyraw, &policy)
|
err := json.Unmarshal(policyraw, &policy)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -576,7 +583,7 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, enginetest.ContextLoaderFactory(nil, nil))
|
||||||
t.Log(string(expectedPatch))
|
t.Log(string(expectedPatch))
|
||||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||||
|
@ -670,7 +677,7 @@ func Test_foreach(t *testing.T) {
|
||||||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||||
|
@ -777,7 +784,7 @@ func Test_foreach_element_mutation(t *testing.T) {
|
||||||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||||
|
@ -903,7 +910,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
|
||||||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusPass)
|
||||||
|
@ -1053,7 +1060,7 @@ func testApplyPolicyToResource(t *testing.T, policyRaw, resourceRaw []byte) *eng
|
||||||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
return er
|
return er
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1603,7 +1610,7 @@ func Test_mutate_existing_resources(t *testing.T) {
|
||||||
newResource: *trigger,
|
newResource: *trigger,
|
||||||
}
|
}
|
||||||
|
|
||||||
er := testMutate(context.TODO(), dclient, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), dclient, registryclient.NewOrDie(), policyContext, nil)
|
||||||
|
|
||||||
for _, rr := range er.PolicyResponse.Rules {
|
for _, rr := range er.PolicyResponse.Rules {
|
||||||
for i, p := range rr.Patches {
|
for i, p := range rr.Patches {
|
||||||
|
@ -1712,7 +1719,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
|
|
||||||
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 2)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 2)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules[1].Patches), 1)
|
||||||
|
@ -1727,7 +1734,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
||||||
applyOne := kyverno.ApplyOne
|
applyOne := kyverno.ApplyOne
|
||||||
policyContext.policy.GetSpec().ApplyRules = &applyOne
|
policyContext.policy.GetSpec().ApplyRules = &applyOne
|
||||||
|
|
||||||
er = testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext)
|
er = testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||||
|
|
||||||
|
@ -2094,7 +2101,7 @@ func Test_SpecialCharacters(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutate and make sure that we got the expected amount of rules.
|
// Mutate and make sure that we got the expected amount of rules.
|
||||||
patches := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext).GetPatches()
|
patches := testMutate(context.TODO(), nil, registryclient.NewOrDie(), policyContext, nil).GetPatches()
|
||||||
if !reflect.DeepEqual(patches, tt.want) {
|
if !reflect.DeepEqual(patches, tt.want) {
|
||||||
t.Errorf("Mutate() got patches %s, expected %s", patches, tt.want)
|
t.Errorf("Mutate() got patches %s, expected %s", patches, tt.want)
|
||||||
}
|
}
|
||||||
|
|
80
pkg/engine/test/contextloader.go
Normal file
80
pkg/engine/test/contextloader.go
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
|
"github.com/kyverno/kyverno/pkg/logging"
|
||||||
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Policy struct {
|
||||||
|
Rules map[string]Rule
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rule struct {
|
||||||
|
Values map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextLoaderFactory(
|
||||||
|
cmResolver engineapi.ConfigmapResolver,
|
||||||
|
values map[string]Policy,
|
||||||
|
) engineapi.ContextLoaderFactory {
|
||||||
|
return func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.ContextLoader {
|
||||||
|
return &mockContextLoader{
|
||||||
|
logger: logging.WithName("MockContextLoaderFactory"),
|
||||||
|
policyName: policy.GetName(),
|
||||||
|
ruleName: rule.Name,
|
||||||
|
values: values,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockContextLoader struct {
|
||||||
|
logger logr.Logger
|
||||||
|
policyName string
|
||||||
|
ruleName string
|
||||||
|
values map[string]Policy
|
||||||
|
allowApiCall bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *mockContextLoader) Load(
|
||||||
|
ctx context.Context,
|
||||||
|
client dclient.Interface,
|
||||||
|
rclient registryclient.Client,
|
||||||
|
contextEntries []kyvernov1.ContextEntry,
|
||||||
|
jsonContext enginecontext.Interface,
|
||||||
|
) error {
|
||||||
|
if l.values != nil {
|
||||||
|
policy := l.values[l.policyName]
|
||||||
|
if policy.Rules != nil {
|
||||||
|
rule := policy.Rules[l.ruleName]
|
||||||
|
for key, value := range rule.Values {
|
||||||
|
if err := jsonContext.AddVariable(key, value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Context Variable should be loaded after the values loaded from values file
|
||||||
|
for _, entry := range contextEntries {
|
||||||
|
if entry.ImageRegistry != nil && rclient != nil {
|
||||||
|
if err := engineapi.LoadImageData(ctx, rclient, l.logger, entry, jsonContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.Variable != nil {
|
||||||
|
if err := engineapi.LoadVariable(l.logger, entry, jsonContext); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if entry.APICall != nil && l.allowApiCall {
|
||||||
|
if err := engineapi.LoadAPIData(ctx, l.logger, entry, jsonContext, client); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ import (
|
||||||
|
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
|
||||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
datautils "github.com/kyverno/kyverno/pkg/utils/data"
|
||||||
matchutils "github.com/kyverno/kyverno/pkg/utils/match"
|
matchutils "github.com/kyverno/kyverno/pkg/utils/match"
|
||||||
|
@ -155,24 +154,7 @@ func doesResourceMatchConditionBlock(subresourceGVKToAPIResource map[string]*met
|
||||||
|
|
||||||
// matchSubjects return true if one of ruleSubjects exist in userInfo
|
// matchSubjects return true if one of ruleSubjects exist in userInfo
|
||||||
func matchSubjects(ruleSubjects []rbacv1.Subject, userInfo authenticationv1.UserInfo, dynamicConfig []string) bool {
|
func matchSubjects(ruleSubjects []rbacv1.Subject, userInfo authenticationv1.UserInfo, dynamicConfig []string) bool {
|
||||||
if store.IsMock() {
|
return matchutils.CheckSubjects(ruleSubjects, userInfo, dynamicConfig)
|
||||||
mockSubject := store.GetSubject()
|
|
||||||
for _, subject := range ruleSubjects {
|
|
||||||
switch subject.Kind {
|
|
||||||
case "ServiceAccount":
|
|
||||||
if subject.Name == mockSubject.Name && subject.Namespace == mockSubject.Namespace {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
case "User", "Group":
|
|
||||||
if mockSubject.Name == subject.Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return matchutils.CheckSubjects(ruleSubjects, userInfo, dynamicConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchesResourceDescription checks if the resource matches resource description of the rule or not
|
// MatchesResourceDescription checks if the resource matches resource description of the rule or not
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
|
|
||||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
urkyverno "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
||||||
"github.com/kyverno/kyverno/cmd/cli/kubectl-kyverno/utils/store"
|
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||||
|
enginetest "github.com/kyverno/kyverno/pkg/engine/test"
|
||||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||||
|
@ -19,12 +19,21 @@ import (
|
||||||
admissionv1 "k8s.io/api/admission/v1"
|
admissionv1 "k8s.io/api/admission/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testValidate(ctx context.Context, rclient registryclient.Client, pContext *PolicyContext, cfg config.Configuration) *engineapi.EngineResponse {
|
func testValidate(
|
||||||
|
ctx context.Context,
|
||||||
|
rclient registryclient.Client,
|
||||||
|
pContext *PolicyContext,
|
||||||
|
cfg config.Configuration,
|
||||||
|
contextLoader engineapi.ContextLoaderFactory,
|
||||||
|
) *engineapi.EngineResponse {
|
||||||
|
if contextLoader == nil {
|
||||||
|
contextLoader = engineapi.DefaultContextLoaderFactory(nil)
|
||||||
|
}
|
||||||
e := NewEngine(
|
e := NewEngine(
|
||||||
cfg,
|
cfg,
|
||||||
nil,
|
nil,
|
||||||
rclient,
|
rclient,
|
||||||
LegacyContextLoaderFactory(nil),
|
contextLoader,
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
return e.Validate(
|
return e.Validate(
|
||||||
|
@ -126,7 +135,7 @@ func TestValidate_image_tag_fail(t *testing.T) {
|
||||||
"validation error: imagePullPolicy 'Always' required with tag 'latest'. rule validate-latest failed at path /spec/containers/0/imagePullPolicy/",
|
"validation error: imagePullPolicy 'Always' required with tag 'latest'. rule validate-latest failed at path /spec/containers/0/imagePullPolicy/",
|
||||||
}
|
}
|
||||||
|
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
assert.Equal(t, r.Message, msgs[index])
|
assert.Equal(t, r.Message, msgs[index])
|
||||||
}
|
}
|
||||||
|
@ -226,7 +235,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
|
||||||
"validation rule 'validate-tag' passed.",
|
"validation rule 'validate-tag' passed.",
|
||||||
"validation rule 'validate-latest' passed.",
|
"validation rule 'validate-latest' passed.",
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
assert.Equal(t, r.Message, msgs[index])
|
assert.Equal(t, r.Message, msgs[index])
|
||||||
}
|
}
|
||||||
|
@ -300,7 +309,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
assert.Assert(t, !er.IsSuccessful())
|
assert.Assert(t, !er.IsSuccessful())
|
||||||
|
|
||||||
msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"}
|
msgs := []string{"validation error: A namespace is required. rule check-default-namespace[0] failed at path /metadata/namespace/ rule check-default-namespace[1] failed at path /metadata/namespace/"}
|
||||||
|
@ -383,7 +392,7 @@ func TestValidate_host_network_port(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"}
|
msgs := []string{"validation error: Host network and port are not allowed. rule validate-host-network-port failed at path /spec/containers/0/ports/0/hostPort/"}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -473,7 +482,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -561,7 +570,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"}
|
msgs := []string{"validation error: Host path '/var/lib/' is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/path/"}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -631,7 +640,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -704,7 +713,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -778,7 +787,7 @@ func TestValidate_inequality_List_Processing(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -858,7 +867,7 @@ func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -932,7 +941,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"}
|
msgs := []string{"validation error: pod: validate run as non root user. rule pod rule 2 failed at path /spec/securityContext/runAsNonRoot/"}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -1007,7 +1016,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'pod image rule' passed."}
|
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -1082,7 +1091,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
assert.Assert(t, !er.IsSuccessful())
|
assert.Assert(t, !er.IsSuccessful())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,7 +1161,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
assert.Assert(t, !er.IsSuccessful())
|
assert.Assert(t, !er.IsSuccessful())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1222,7 +1231,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'pod image rule' passed."}
|
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -1310,7 +1319,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"}
|
msgs := []string{"validation error: Host path is not allowed. rule validate-host-path failed at path /spec/volumes/0/hostPath/"}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -1397,7 +1406,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
|
||||||
|
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||||
|
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
|
@ -1474,7 +1483,7 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
||||||
|
@ -1568,7 +1577,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
||||||
|
@ -1630,7 +1639,7 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "validation error: rule not-operator-with-variable-should-alway-fail-validation failed at path /spec/content/")
|
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "validation error: rule not-operator-with-variable-should-alway-fail-validation failed at path /spec/content/")
|
||||||
}
|
}
|
||||||
|
@ -1722,7 +1731,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
|
|
||||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusError)
|
||||||
|
@ -1816,7 +1825,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
|
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message,
|
assert.Equal(t, er.PolicyResponse.Rules[0].Message,
|
||||||
|
@ -1922,7 +1931,7 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "The animal cow is not in the allowed list of animals.")
|
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "The animal cow is not in the allowed list of animals.")
|
||||||
}
|
}
|
||||||
|
@ -1976,7 +1985,7 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, nil)
|
||||||
|
|
||||||
for i, rule := range er.PolicyResponse.Rules {
|
for i, rule := range er.PolicyResponse.Rules {
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[i].Status, test.expectedResults[i], "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedResults[i], er.PolicyResponse.Rules[i].Status)
|
assert.Equal(t, er.PolicyResponse.Rules[i].Status, test.expectedResults[i], "\ntest %s failed\nexpected: %s\nactual: %s", test.name, test.expectedResults[i], er.PolicyResponse.Rules[i].Status)
|
||||||
|
@ -2142,7 +2151,7 @@ func executeTest(t *testing.T, test testCase) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := testValidate(context.TODO(), registryclient.NewOrDie(), pc, cfg)
|
resp := testValidate(context.TODO(), registryclient.NewOrDie(), pc, cfg, nil)
|
||||||
if resp.IsSuccessful() && test.requestDenied {
|
if resp.IsSuccessful() && test.requestDenied {
|
||||||
t.Errorf("Testcase has failed, policy: %v", policy.Name)
|
t.Errorf("Testcase has failed, policy: %v", policy.Name)
|
||||||
}
|
}
|
||||||
|
@ -2213,21 +2222,6 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
store.SetPolicies(
|
|
||||||
store.Policy{
|
|
||||||
Name: "restrict-pod-count",
|
|
||||||
Rules: []store.Rule{
|
|
||||||
{
|
|
||||||
Name: "restrict-pod-count",
|
|
||||||
Values: map[string]interface{}{
|
|
||||||
"podcounts": "12",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
store.SetMock(true)
|
|
||||||
|
|
||||||
var policy kyverno.ClusterPolicy
|
var policy kyverno.ClusterPolicy
|
||||||
err := json.Unmarshal(rawPolicy, &policy)
|
err := json.Unmarshal(rawPolicy, &policy)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
@ -2237,7 +2231,26 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
|
||||||
msgs := []string{
|
msgs := []string{
|
||||||
"restrict pod counts to be no more than 10 on node minikube",
|
"restrict pod counts to be no more than 10 on node minikube",
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(
|
||||||
|
context.TODO(),
|
||||||
|
registryclient.NewOrDie(),
|
||||||
|
&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()},
|
||||||
|
cfg,
|
||||||
|
enginetest.ContextLoaderFactory(
|
||||||
|
nil,
|
||||||
|
map[string]enginetest.Policy{
|
||||||
|
"restrict-pod-count": {
|
||||||
|
Rules: map[string]enginetest.Rule{
|
||||||
|
"restrict-pod-count": {
|
||||||
|
Values: map[string]interface{}{
|
||||||
|
"podcounts": "12",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
for index, r := range er.PolicyResponse.Rules {
|
for index, r := range er.PolicyResponse.Rules {
|
||||||
assert.Equal(t, r.Message, msgs[index])
|
assert.Equal(t, r.Message, msgs[index])
|
||||||
}
|
}
|
||||||
|
@ -2326,7 +2339,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx}, cfg, nil)
|
||||||
assert.Assert(t, !er.IsSuccessful())
|
assert.Assert(t, !er.IsSuccessful())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2415,7 +2428,7 @@ func Test_StringInDenyCondition(t *testing.T) {
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx}, cfg, nil)
|
||||||
assert.Assert(t, er.IsSuccessful())
|
assert.Assert(t, er.IsSuccessful())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2464,7 +2477,7 @@ func Test_foreach_container_pass(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_container_fail(t *testing.T) {
|
func Test_foreach_container_fail(t *testing.T) {
|
||||||
|
@ -2500,7 +2513,7 @@ func Test_foreach_container_fail(t *testing.T) {
|
||||||
]
|
]
|
||||||
}}]}}`)
|
}}]}}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_container_deny_fail(t *testing.T) {
|
func Test_foreach_container_deny_fail(t *testing.T) {
|
||||||
|
@ -2554,7 +2567,7 @@ func Test_foreach_container_deny_fail(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_container_deny_success(t *testing.T) {
|
func Test_foreach_container_deny_success(t *testing.T) {
|
||||||
|
@ -2596,7 +2609,7 @@ func Test_foreach_container_deny_success(t *testing.T) {
|
||||||
]
|
]
|
||||||
}}]}}`)
|
}}]}}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_container_deny_error(t *testing.T) {
|
func Test_foreach_container_deny_error(t *testing.T) {
|
||||||
|
@ -2650,7 +2663,7 @@ func Test_foreach_container_deny_error(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusError)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_context_preconditions(t *testing.T) {
|
func Test_foreach_context_preconditions(t *testing.T) {
|
||||||
|
@ -2723,23 +2736,28 @@ func Test_foreach_context_preconditions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
store.SetPolicies(
|
testForEach(
|
||||||
store.Policy{
|
t,
|
||||||
Name: "test",
|
policyraw,
|
||||||
Rules: []store.Rule{
|
resourceRaw,
|
||||||
{
|
"",
|
||||||
Name: "test",
|
engineapi.RuleStatusPass,
|
||||||
Values: map[string]interface{}{
|
enginetest.ContextLoaderFactory(
|
||||||
"img.data.podvalid": "nginx/nginx:v1",
|
nil,
|
||||||
"img.data.podinvalid": "nginx/nginx:v2",
|
map[string]enginetest.Policy{
|
||||||
|
"test": {
|
||||||
|
Rules: map[string]enginetest.Rule{
|
||||||
|
"test": {
|
||||||
|
Values: map[string]interface{}{
|
||||||
|
"img.data.podvalid": "nginx/nginx:v1",
|
||||||
|
"img.data.podinvalid": "nginx/nginx:v2",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
)
|
)
|
||||||
store.SetMock(true)
|
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_context_preconditions_fail(t *testing.T) {
|
func Test_foreach_context_preconditions_fail(t *testing.T) {
|
||||||
|
@ -2813,23 +2831,28 @@ func Test_foreach_context_preconditions_fail(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
store.SetPolicies(
|
testForEach(
|
||||||
store.Policy{
|
t,
|
||||||
Name: "test",
|
policyraw,
|
||||||
Rules: []store.Rule{
|
resourceRaw,
|
||||||
{
|
"",
|
||||||
Name: "test",
|
engineapi.RuleStatusFail,
|
||||||
Values: map[string]interface{}{
|
enginetest.ContextLoaderFactory(
|
||||||
"img.data.podvalid": "nginx/nginx:v1",
|
nil,
|
||||||
"img.data.podinvalid": "nginx/nginx:v1",
|
map[string]enginetest.Policy{
|
||||||
|
"test": {
|
||||||
|
Rules: map[string]enginetest.Rule{
|
||||||
|
"test": {
|
||||||
|
Values: map[string]interface{}{
|
||||||
|
"img.data.podvalid": "nginx/nginx:v1",
|
||||||
|
"img.data.podinvalid": "nginx/nginx:v1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
)
|
)
|
||||||
store.SetMock(true)
|
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusFail)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_element_validation(t *testing.T) {
|
func Test_foreach_element_validation(t *testing.T) {
|
||||||
|
@ -2876,7 +2899,7 @@ func Test_foreach_element_validation(t *testing.T) {
|
||||||
]
|
]
|
||||||
}}]}}`)
|
}}]}}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_outof_foreach_element_validation(t *testing.T) {
|
func Test_outof_foreach_element_validation(t *testing.T) {
|
||||||
|
@ -2918,7 +2941,7 @@ func Test_outof_foreach_element_validation(t *testing.T) {
|
||||||
}
|
}
|
||||||
}}]}}`)
|
}}]}}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusError)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusError, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_skip_initContainer_pass(t *testing.T) {
|
func Test_foreach_skip_initContainer_pass(t *testing.T) {
|
||||||
|
@ -2972,7 +2995,7 @@ func Test_foreach_skip_initContainer_pass(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_foreach_validate_nested(t *testing.T) {
|
func Test_foreach_validate_nested(t *testing.T) {
|
||||||
|
@ -3068,10 +3091,10 @@ func Test_foreach_validate_nested(t *testing.T) {
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass)
|
testForEach(t, policyraw, resourceRaw, "", engineapi.RuleStatusPass, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string, status engineapi.RuleStatus) {
|
func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string, status engineapi.RuleStatus, contextLoader engineapi.ContextLoaderFactory) {
|
||||||
var policy kyverno.ClusterPolicy
|
var policy kyverno.ClusterPolicy
|
||||||
assert.NilError(t, json.Unmarshal(policyraw, &policy))
|
assert.NilError(t, json.Unmarshal(policyraw, &policy))
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(resourceRaw)
|
||||||
|
@ -3086,7 +3109,7 @@ func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string,
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), policyContext, cfg, contextLoader)
|
||||||
|
|
||||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, status)
|
assert.Equal(t, er.PolicyResponse.Rules[0].Status, status)
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
|
@ -3150,7 +3173,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
newResource: *resourceUnstructured,
|
newResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
engineResponseCreate := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextCreate, cfg)
|
engineResponseCreate := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextCreate, cfg, nil)
|
||||||
assert.Equal(t, len(engineResponseCreate.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(engineResponseCreate.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status, engineapi.RuleStatusFail)
|
||||||
|
|
||||||
|
@ -3159,7 +3182,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
|
||||||
jsonContext: ctx,
|
jsonContext: ctx,
|
||||||
oldResource: *resourceUnstructured,
|
oldResource: *resourceUnstructured,
|
||||||
}
|
}
|
||||||
engineResponseDelete := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextDelete, cfg)
|
engineResponseDelete := testValidate(context.TODO(), registryclient.NewOrDie(), policyContextDelete, cfg, nil)
|
||||||
assert.Equal(t, len(engineResponseDelete.PolicyResponse.Rules), 0)
|
assert.Equal(t, len(engineResponseDelete.PolicyResponse.Rules), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3218,7 +3241,7 @@ func Test_ValidatePattern_anyPattern(t *testing.T) {
|
||||||
resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource)
|
resourceUnstructured, err := kubeutils.BytesToUnstructured(tc.rawResource)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg)
|
er := testValidate(context.TODO(), registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: enginecontext.NewContext()}, cfg, nil)
|
||||||
if tc.expectedFailed {
|
if tc.expectedFailed {
|
||||||
assert.Assert(t, er.IsFailed())
|
assert.Assert(t, er.IsFailed())
|
||||||
} else if tc.expectedSkipped {
|
} else if tc.expectedSkipped {
|
||||||
|
|
|
@ -150,7 +150,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
||||||
config.NewDefaultConfiguration(),
|
config.NewDefaultConfiguration(),
|
||||||
nil,
|
nil,
|
||||||
registryclient.NewOrDie(),
|
registryclient.NewOrDie(),
|
||||||
engine.LegacyContextLoaderFactory(nil),
|
engineapi.DefaultContextLoaderFactory(nil),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
er := eng.Mutate(
|
er := eng.Mutate(
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
"github.com/kyverno/kyverno/pkg/engine"
|
"github.com/kyverno/kyverno/pkg/engine"
|
||||||
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/context/resolvers"
|
"github.com/kyverno/kyverno/pkg/engine/context/resolvers"
|
||||||
"github.com/kyverno/kyverno/pkg/event"
|
"github.com/kyverno/kyverno/pkg/event"
|
||||||
"github.com/kyverno/kyverno/pkg/metrics"
|
"github.com/kyverno/kyverno/pkg/metrics"
|
||||||
|
@ -60,7 +61,7 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
|
||||||
configuration,
|
configuration,
|
||||||
dclient,
|
dclient,
|
||||||
rclient,
|
rclient,
|
||||||
engine.LegacyContextLoaderFactory(configMapResolver),
|
engineapi.DefaultContextLoaderFactory(configMapResolver),
|
||||||
peLister,
|
peLister,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1053,7 +1053,7 @@ func TestValidate_failure_action_overrides(t *testing.T) {
|
||||||
config.NewDefaultConfiguration(),
|
config.NewDefaultConfiguration(),
|
||||||
nil,
|
nil,
|
||||||
registryclient.NewOrDie(),
|
registryclient.NewOrDie(),
|
||||||
engine.LegacyContextLoaderFactory(nil),
|
engineapi.DefaultContextLoaderFactory(nil),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
for i, tc := range testcases {
|
for i, tc := range testcases {
|
||||||
|
@ -1132,7 +1132,7 @@ func Test_RuleSelector(t *testing.T) {
|
||||||
config.NewDefaultConfiguration(),
|
config.NewDefaultConfiguration(),
|
||||||
nil,
|
nil,
|
||||||
registryclient.NewOrDie(),
|
registryclient.NewOrDie(),
|
||||||
engine.LegacyContextLoaderFactory(nil),
|
engineapi.DefaultContextLoaderFactory(nil),
|
||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
resp := eng.Validate(
|
resp := eng.Validate(
|
||||||
|
|
Loading…
Reference in a new issue