mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
refactor: registry client (#5596)
* refactor: registry client Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> * fix Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com> Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
616d0d3981
commit
7219b4f8a3
35 changed files with 389 additions and 299 deletions
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
ut "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
yamlutils "github.com/kyverno/kyverno/pkg/utils/yaml"
|
||||
yamlv2 "gopkg.in/yaml.v2"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -457,7 +458,7 @@ OuterLoop:
|
|||
WithAdmissionInfo(c.UserInfo).
|
||||
WithClient(c.Client)
|
||||
|
||||
mutateResponse := engine.Mutate(policyContext)
|
||||
mutateResponse := engine.Mutate(registryclient.NewOrDie(), policyContext)
|
||||
if mutateResponse != nil {
|
||||
engineResponses = append(engineResponses, mutateResponse)
|
||||
}
|
||||
|
@ -481,7 +482,7 @@ OuterLoop:
|
|||
var info Info
|
||||
var validateResponse *response.EngineResponse
|
||||
if policyHasValidate {
|
||||
validateResponse = engine.Validate(policyContext)
|
||||
validateResponse = engine.Validate(registryclient.NewOrDie(), policyContext)
|
||||
info = ProcessValidateEngineResponse(c.Policy, validateResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
|
||||
}
|
||||
|
||||
|
@ -489,7 +490,7 @@ OuterLoop:
|
|||
engineResponses = append(engineResponses, validateResponse)
|
||||
}
|
||||
|
||||
verifyImageResponse, _ := engine.VerifyAndPatchImages(policyContext)
|
||||
verifyImageResponse, _ := engine.VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
if verifyImageResponse != nil && !verifyImageResponse.IsEmpty() {
|
||||
engineResponses = append(engineResponses, verifyImageResponse)
|
||||
info = ProcessValidateEngineResponse(c.Policy, verifyImageResponse, resPath, c.Rc, c.PolicyReport, c.AuditWarn)
|
||||
|
@ -503,7 +504,7 @@ OuterLoop:
|
|||
}
|
||||
|
||||
if policyHasGenerate {
|
||||
generateResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
generateResponse := engine.ApplyBackgroundChecks(registryclient.NewOrDie(), policyContext)
|
||||
if generateResponse != nil && !generateResponse.IsEmpty() {
|
||||
newRuleResponse, err := handleGeneratePolicy(generateResponse, *policyContext, c.RuleToCloneSourceResource)
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
var (
|
||||
Mock bool
|
||||
RegistryAccess bool
|
||||
registryClient registryclient.Client
|
||||
AllowApiCalls bool
|
||||
ContextVar Context
|
||||
ForeachElement int
|
||||
|
@ -32,13 +32,16 @@ func GetForeachElement() int {
|
|||
|
||||
func SetRegistryAccess(access bool) {
|
||||
if access {
|
||||
registryclient.DefaultClient.UseLocalKeychain()
|
||||
registryClient = registryclient.NewOrDie(registryclient.WithLocalKeychain())
|
||||
}
|
||||
RegistryAccess = access
|
||||
}
|
||||
|
||||
func GetRegistryAccess() bool {
|
||||
return RegistryAccess
|
||||
return registryClient != nil
|
||||
}
|
||||
|
||||
func GetRegistryClient() registryclient.Client {
|
||||
return registryClient
|
||||
}
|
||||
|
||||
func SetContext(context Context) {
|
||||
|
|
|
@ -61,23 +61,24 @@ const (
|
|||
resyncPeriod = 15 * time.Minute
|
||||
)
|
||||
|
||||
func setupRegistryClient(logger logr.Logger, kubeClient kubernetes.Interface, imagePullSecrets string, allowInsecureRegistry bool) error {
|
||||
func setupRegistryClient(logger logr.Logger, kubeClient kubernetes.Interface, imagePullSecrets string, allowInsecureRegistry bool) (registryclient.Client, error) {
|
||||
logger = logger.WithName("registry-client")
|
||||
logger.Info("setup registry client...", "secrets", imagePullSecrets, "insecure", allowInsecureRegistry)
|
||||
var registryOptions []registryclient.Option
|
||||
secrets := strings.Split(imagePullSecrets, ",")
|
||||
if imagePullSecrets != "" && len(secrets) > 0 {
|
||||
registryOptions = append(registryOptions, registryclient.WithKeychainPullSecrets(kubeClient, config.KyvernoNamespace(), "", secrets))
|
||||
registryOptions = append(registryOptions, registryclient.WithKeychainPullSecrets(
|
||||
context.TODO(),
|
||||
kubeClient,
|
||||
config.KyvernoNamespace(),
|
||||
"",
|
||||
secrets...,
|
||||
))
|
||||
}
|
||||
if allowInsecureRegistry {
|
||||
registryOptions = append(registryOptions, registryclient.WithAllowInsecureRegistry())
|
||||
}
|
||||
client, err := registryclient.InitClient(registryOptions...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
registryclient.DefaultClient = client
|
||||
return nil
|
||||
return registryclient.New(registryOptions...)
|
||||
}
|
||||
|
||||
func setupCosign(logger logr.Logger, imageSignatureRepository string) {
|
||||
|
@ -115,6 +116,7 @@ func createNonLeaderControllers(
|
|||
kubeClient kubernetes.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
dynamicClient dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
configuration config.Configuration,
|
||||
policyCache policycache.Cache,
|
||||
eventGenerator event.Interface,
|
||||
|
@ -136,6 +138,7 @@ func createNonLeaderControllers(
|
|||
updateRequestController := background.NewController(
|
||||
kyvernoClient,
|
||||
dynamicClient,
|
||||
rclient,
|
||||
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kyvernoInformer.Kyverno().V1().Policies(),
|
||||
kyvernoInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
|
@ -162,6 +165,7 @@ func createReportControllers(
|
|||
backgroundScanWorkers int,
|
||||
client dclient.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
rclient registryclient.Client,
|
||||
metadataFactory metadatainformers.SharedInformerFactory,
|
||||
kubeInformer kubeinformers.SharedInformerFactory,
|
||||
kyvernoInformer kyvernoinformer.SharedInformerFactory,
|
||||
|
@ -212,6 +216,7 @@ func createReportControllers(
|
|||
backgroundscancontroller.NewController(
|
||||
client,
|
||||
kyvernoClient,
|
||||
rclient,
|
||||
metadataFactory,
|
||||
kyvernoV1.Policies(),
|
||||
kyvernoV1.ClusterPolicies(),
|
||||
|
@ -247,6 +252,7 @@ func createrLeaderControllers(
|
|||
kubeClient kubernetes.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
dynamicClient dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
configuration config.Configuration,
|
||||
metricsConfig metrics.MetricsConfigManager,
|
||||
eventGenerator event.Interface,
|
||||
|
@ -256,6 +262,7 @@ func createrLeaderControllers(
|
|||
policyCtrl, err := policy.NewPolicyController(
|
||||
kyvernoClient,
|
||||
dynamicClient,
|
||||
rclient,
|
||||
kyvernoInformer.Kyverno().V1().ClusterPolicies(),
|
||||
kyvernoInformer.Kyverno().V1().Policies(),
|
||||
kyvernoInformer.Kyverno().V1beta1().UpdateRequests(),
|
||||
|
@ -300,6 +307,7 @@ func createrLeaderControllers(
|
|||
backgroundScanWorkers,
|
||||
dynamicClient,
|
||||
kyvernoClient,
|
||||
rclient,
|
||||
metadataInformer,
|
||||
kubeInformer,
|
||||
kyvernoInformer,
|
||||
|
@ -390,7 +398,8 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
// setup registry client
|
||||
if err := setupRegistryClient(logger, kubeClient, imagePullSecrets, allowInsecureRegistry); err != nil {
|
||||
rclient, err := setupRegistryClient(logger, kubeClient, imagePullSecrets, allowInsecureRegistry)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to setup registry client")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
@ -476,6 +485,7 @@ func main() {
|
|||
kubeClient,
|
||||
kyvernoClient,
|
||||
dClient,
|
||||
rclient,
|
||||
configuration,
|
||||
policyCache,
|
||||
eventGenerator,
|
||||
|
@ -531,6 +541,7 @@ func main() {
|
|||
kubeClient,
|
||||
kyvernoClient,
|
||||
dClient,
|
||||
rclient,
|
||||
configuration,
|
||||
metricsConfig,
|
||||
eventGenerator,
|
||||
|
@ -595,6 +606,7 @@ func main() {
|
|||
resourceHandlers := webhooksresource.NewHandlers(
|
||||
dClient,
|
||||
kyvernoClient,
|
||||
rclient,
|
||||
configuration,
|
||||
metricsConfig,
|
||||
policyCache,
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"golang.org/x/exp/slices"
|
||||
|
@ -43,6 +44,7 @@ type GenerateController struct {
|
|||
client dclient.Interface
|
||||
kyvernoClient versioned.Interface
|
||||
statusControl common.StatusControlInterface
|
||||
rclient registryclient.Client
|
||||
|
||||
// listers
|
||||
urLister kyvernov1beta1listers.UpdateRequestNamespaceLister
|
||||
|
@ -61,6 +63,7 @@ func NewGenerateController(
|
|||
client dclient.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
statusControl common.StatusControlInterface,
|
||||
rclient registryclient.Client,
|
||||
policyLister kyvernov1listers.ClusterPolicyLister,
|
||||
npolicyLister kyvernov1listers.PolicyLister,
|
||||
urLister kyvernov1beta1listers.UpdateRequestNamespaceLister,
|
||||
|
@ -73,6 +76,7 @@ func NewGenerateController(
|
|||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
statusControl: statusControl,
|
||||
rclient: rclient,
|
||||
policyLister: policyLister,
|
||||
npolicyLister: npolicyLister,
|
||||
urLister: urLister,
|
||||
|
@ -195,7 +199,7 @@ func (c *GenerateController) applyGenerate(resource unstructured.Unstructured, u
|
|||
}
|
||||
|
||||
// check if the policy still applies to the resource
|
||||
engineResponse := engine.GenerateResponse(policyContext, ur)
|
||||
engineResponse := engine.GenerateResponse(c.rclient, policyContext, ur)
|
||||
if len(engineResponse.PolicyResponse.Rules) == 0 {
|
||||
logger.V(4).Info(doesNotApply)
|
||||
return nil, false, errors.New(doesNotApply)
|
||||
|
@ -341,7 +345,7 @@ func (c *GenerateController) ApplyGeneratePolicy(log logr.Logger, policyContext
|
|||
}
|
||||
|
||||
// add configmap json data to context
|
||||
if err := engine.LoadContext(log, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err := engine.LoadContext(log, c.rclient, rule.Context, policyContext, rule.Name); err != nil {
|
||||
log.Error(err, "cannot add configmaps to context")
|
||||
return nil, processExisting, err
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"go.uber.org/multierr"
|
||||
yamlv2 "gopkg.in/yaml.v2"
|
||||
|
@ -28,7 +29,7 @@ type MutateExistingController struct {
|
|||
// clients
|
||||
client dclient.Interface
|
||||
statusControl common.StatusControlInterface
|
||||
|
||||
rclient registryclient.Client
|
||||
// listers
|
||||
policyLister kyvernov1listers.ClusterPolicyLister
|
||||
npolicyLister kyvernov1listers.PolicyLister
|
||||
|
@ -43,6 +44,7 @@ type MutateExistingController struct {
|
|||
func NewMutateExistingController(
|
||||
client dclient.Interface,
|
||||
statusControl common.StatusControlInterface,
|
||||
rclient registryclient.Client,
|
||||
policyLister kyvernov1listers.ClusterPolicyLister,
|
||||
npolicyLister kyvernov1listers.PolicyLister,
|
||||
dynamicConfig config.Configuration,
|
||||
|
@ -52,6 +54,7 @@ func NewMutateExistingController(
|
|||
c := MutateExistingController{
|
||||
client: client,
|
||||
statusControl: statusControl,
|
||||
rclient: rclient,
|
||||
policyLister: policyLister,
|
||||
npolicyLister: npolicyLister,
|
||||
configuration: dynamicConfig,
|
||||
|
@ -90,7 +93,7 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e
|
|||
continue
|
||||
}
|
||||
|
||||
er := engine.Mutate(policyContext)
|
||||
er := engine.Mutate(c.rclient, policyContext)
|
||||
for _, r := range er.PolicyResponse.Rules {
|
||||
patched := r.PatchedTarget
|
||||
switch r.Status {
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
pkgCommon "github.com/kyverno/kyverno/pkg/common"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -46,6 +47,7 @@ type controller struct {
|
|||
// clients
|
||||
client dclient.Interface
|
||||
kyvernoClient versioned.Interface
|
||||
rclient registryclient.Client
|
||||
|
||||
// listers
|
||||
cpolLister kyvernov1listers.ClusterPolicyLister
|
||||
|
@ -67,6 +69,7 @@ type controller struct {
|
|||
func NewController(
|
||||
kyvernoClient versioned.Interface,
|
||||
client dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
||||
polInformer kyvernov1informers.PolicyInformer,
|
||||
urInformer kyvernov1beta1informers.UpdateRequestInformer,
|
||||
|
@ -79,6 +82,7 @@ func NewController(
|
|||
c := controller{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
rclient: rclient,
|
||||
cpolLister: cpolInformer.Lister(),
|
||||
polLister: polInformer.Lister(),
|
||||
urLister: urLister,
|
||||
|
@ -405,10 +409,10 @@ func (c *controller) processUR(ur *kyvernov1beta1.UpdateRequest) error {
|
|||
statusControl := common.NewStatusControl(c.kyvernoClient, c.urLister)
|
||||
switch ur.Spec.Type {
|
||||
case kyvernov1beta1.Mutate:
|
||||
ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.cpolLister, c.polLister, c.configuration, c.eventGen, logger)
|
||||
ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.rclient, c.cpolLister, c.polLister, c.configuration, c.eventGen, logger)
|
||||
return ctrl.ProcessUR(ur)
|
||||
case kyvernov1beta1.Generate:
|
||||
ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.eventGen, logger)
|
||||
ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.rclient, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.eventGen, logger)
|
||||
return ctrl.ProcessUR(ur)
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/controllers/report/resource"
|
||||
"github.com/kyverno/kyverno/pkg/controllers/report/utils"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
@ -41,6 +42,7 @@ type controller struct {
|
|||
// clients
|
||||
client dclient.Interface
|
||||
kyvernoClient versioned.Interface
|
||||
rclient registryclient.Client
|
||||
|
||||
// listers
|
||||
polLister kyvernov1listers.PolicyLister
|
||||
|
@ -61,6 +63,7 @@ type controller struct {
|
|||
func NewController(
|
||||
client dclient.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
rclient registryclient.Client,
|
||||
metadataFactory metadatainformers.SharedInformerFactory,
|
||||
polInformer kyvernov1informers.PolicyInformer,
|
||||
cpolInformer kyvernov1informers.ClusterPolicyInformer,
|
||||
|
@ -73,6 +76,7 @@ func NewController(
|
|||
c := controller{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
rclient: rclient,
|
||||
polLister: polInformer.Lister(),
|
||||
cpolLister: cpolInformer.Lister(),
|
||||
bgscanrLister: bgscanr.Lister(),
|
||||
|
@ -214,7 +218,7 @@ func (c *controller) updateReport(ctx context.Context, meta metav1.Object, gvk s
|
|||
}
|
||||
// if the resource changed, we need to rebuild the report
|
||||
if !reportutils.CompareHash(meta, resource.Hash) {
|
||||
scanner := utils.NewScanner(logger, c.client)
|
||||
scanner := utils.NewScanner(logger, c.client, c.rclient)
|
||||
before, err := c.getReport(ctx, meta.GetNamespace(), meta.GetName())
|
||||
if err != nil {
|
||||
return nil
|
||||
|
@ -300,7 +304,7 @@ func (c *controller) updateReport(ctx context.Context, meta metav1.Object, gvk s
|
|||
}
|
||||
// creations
|
||||
if len(toCreate) > 0 {
|
||||
scanner := utils.NewScanner(logger, c.client)
|
||||
scanner := utils.NewScanner(logger, c.client, c.rclient)
|
||||
resource, err := c.client.GetResource(ctx, gvk.GroupVersion().String(), gvk.Kind, resource.Namespace, resource.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"go.uber.org/multierr"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
@ -14,6 +15,7 @@ import (
|
|||
type scanner struct {
|
||||
logger logr.Logger
|
||||
client dclient.Interface
|
||||
rclient registryclient.Client
|
||||
excludeGroupRole []string
|
||||
}
|
||||
|
||||
|
@ -26,10 +28,11 @@ type Scanner interface {
|
|||
ScanResource(unstructured.Unstructured, map[string]string, ...kyvernov1.PolicyInterface) map[kyvernov1.PolicyInterface]ScanResult
|
||||
}
|
||||
|
||||
func NewScanner(logger logr.Logger, client dclient.Interface, excludeGroupRole ...string) Scanner {
|
||||
func NewScanner(logger logr.Logger, client dclient.Interface, rclient registryclient.Client, excludeGroupRole ...string) Scanner {
|
||||
return &scanner{
|
||||
logger: logger,
|
||||
client: client,
|
||||
rclient: rclient,
|
||||
excludeGroupRole: excludeGroupRole,
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +84,7 @@ func (s *scanner) validateResource(resource unstructured.Unstructured, nsLabels
|
|||
WithClient(s.client).
|
||||
WithNamespaceLabels(nsLabels).
|
||||
WithExcludeGroupRole(s.excludeGroupRole...)
|
||||
return engine.Validate(policyCtx), nil
|
||||
return engine.Validate(s.rclient, policyCtx), nil
|
||||
}
|
||||
|
||||
func (s *scanner) validateImages(resource unstructured.Unstructured, nsLabels map[string]string, policy kyvernov1.PolicyInterface) (*response.EngineResponse, error) {
|
||||
|
@ -104,7 +107,7 @@ func (s *scanner) validateImages(resource unstructured.Unstructured, nsLabels ma
|
|||
WithClient(s.client).
|
||||
WithNamespaceLabels(nsLabels).
|
||||
WithExcludeGroupRole(s.excludeGroupRole...)
|
||||
response, _ := engine.VerifyAndPatchImages(policyCtx)
|
||||
response, _ := engine.VerifyAndPatchImages(s.rclient, policyCtx)
|
||||
if len(response.PolicyResponse.Rules) > 0 {
|
||||
s.logger.Info("validateImages", "policy", policy, "response", response)
|
||||
}
|
||||
|
|
|
@ -59,13 +59,13 @@ type Response struct {
|
|||
type CosignError struct{}
|
||||
|
||||
// VerifySignature verifies that the image has the expected signatures
|
||||
func VerifySignature(opts Options) (*Response, error) {
|
||||
func VerifySignature(rclient registryclient.Client, opts Options) (*Response, error) {
|
||||
ref, err := name.ParseReference(opts.ImageRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse image %s", opts.ImageRef)
|
||||
}
|
||||
|
||||
cosignOpts, err := buildCosignOptions(opts)
|
||||
cosignOpts, err := buildCosignOptions(rclient, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ func VerifySignature(opts Options) (*Response, error) {
|
|||
return &Response{Digest: digest}, nil
|
||||
}
|
||||
|
||||
func buildCosignOptions(opts Options) (*cosign.CheckOpts, error) {
|
||||
func buildCosignOptions(rclient registryclient.Client, opts Options) (*cosign.CheckOpts, error) {
|
||||
var remoteOpts []remote.Option
|
||||
var err error
|
||||
signatureAlgorithmMap := map[string]crypto.Hash{
|
||||
|
@ -123,7 +123,7 @@ func buildCosignOptions(opts Options) (*cosign.CheckOpts, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "constructing client options")
|
||||
}
|
||||
remoteOpts = append(remoteOpts, registryclient.BuildRemoteOption(registryclient.DefaultClient))
|
||||
remoteOpts = append(remoteOpts, rclient.BuildRemoteOption())
|
||||
cosignOpts := &cosign.CheckOpts{
|
||||
Annotations: map[string]interface{}{},
|
||||
RegistryClientOpts: remoteOpts,
|
||||
|
@ -254,8 +254,8 @@ func loadCertChain(pem []byte) ([]*x509.Certificate, error) {
|
|||
|
||||
// FetchAttestations retrieves signed attestations and decodes them into in-toto statements
|
||||
// https://github.com/in-toto/attestation/blob/main/spec/README.md#statement
|
||||
func FetchAttestations(opts Options) (*Response, error) {
|
||||
cosignOpts, err := buildCosignOptions(opts)
|
||||
func FetchAttestations(rclient registryclient.Client, opts Options) (*Response, error) {
|
||||
cosignOpts, err := buildCosignOptions(rclient, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||
"github.com/google/go-containerregistry/pkg/v1/types"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/sigstore/cosign/pkg/cosign"
|
||||
"github.com/sigstore/cosign/pkg/cosign/bundle"
|
||||
"github.com/sigstore/cosign/pkg/oci"
|
||||
|
@ -76,15 +77,18 @@ func TestCosignKeyless(t *testing.T) {
|
|||
Subject: "jim",
|
||||
}
|
||||
|
||||
_, err := VerifySignature(opts)
|
||||
client, err := registryclient.New()
|
||||
assert.NilError(t, err)
|
||||
|
||||
_, err = VerifySignature(client, opts)
|
||||
assert.ErrorContains(t, err, "subject mismatch: expected jim, received jim@nirmata.com")
|
||||
|
||||
opts.Subject = "jim@nirmata.com"
|
||||
_, err = VerifySignature(opts)
|
||||
_, err = VerifySignature(client, opts)
|
||||
assert.ErrorContains(t, err, "issuer mismatch: expected https://github.com/, received https://github.com/login/oauth")
|
||||
|
||||
opts.Issuer = "https://github.com/login/oauth"
|
||||
_, err = VerifySignature(opts)
|
||||
_, err = VerifySignature(client, opts)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
)
|
||||
|
||||
// ApplyBackgroundChecks checks for validity of generate and mutateExisting rules on the resource
|
||||
|
@ -16,12 +17,12 @@ import (
|
|||
// - the caller has to check the ruleResponse to determine whether the path exist
|
||||
//
|
||||
// 2. returns the list of rules that are applicable on this policy and resource, if 1 succeed
|
||||
func ApplyBackgroundChecks(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
func ApplyBackgroundChecks(rclient registryclient.Client, policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
policyStartTime := time.Now()
|
||||
return filterRules(policyContext, policyStartTime)
|
||||
return filterRules(rclient, policyContext, policyStartTime)
|
||||
}
|
||||
|
||||
func filterRules(policyContext *PolicyContext, startTime time.Time) *response.EngineResponse {
|
||||
func filterRules(rclient registryclient.Client, policyContext *PolicyContext, startTime time.Time) *response.EngineResponse {
|
||||
kind := policyContext.newResource.GetKind()
|
||||
name := policyContext.newResource.GetName()
|
||||
namespace := policyContext.newResource.GetNamespace()
|
||||
|
@ -51,7 +52,7 @@ func filterRules(policyContext *PolicyContext, startTime time.Time) *response.En
|
|||
|
||||
applyRules := policyContext.policy.GetSpec().GetApplyRules()
|
||||
for _, rule := range autogen.ComputeRules(policyContext.policy) {
|
||||
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
|
||||
if ruleResp := filterRule(rclient, rule, policyContext); ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
if applyRules == kyvernov1.ApplyOne && ruleResp.Status != response.RuleStatusSkip {
|
||||
break
|
||||
|
@ -62,7 +63,7 @@ func filterRules(policyContext *PolicyContext, startTime time.Time) *response.En
|
|||
return resp
|
||||
}
|
||||
|
||||
func filterRule(rule kyvernov1.Rule, policyContext *PolicyContext) *response.RuleResponse {
|
||||
func filterRule(rclient registryclient.Client, rule kyvernov1.Rule, policyContext *PolicyContext) *response.RuleResponse {
|
||||
if !rule.HasGenerate() && !rule.IsMutateExisting() {
|
||||
return nil
|
||||
}
|
||||
|
@ -108,7 +109,7 @@ func filterRule(rule kyvernov1.Rule, policyContext *PolicyContext) *response.Rul
|
|||
policyContext.jsonContext.Checkpoint()
|
||||
defer policyContext.jsonContext.Restore()
|
||||
|
||||
if err = LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err = LoadContext(logger, rclient, rule.Context, policyContext, rule.Name); err != nil {
|
||||
logger.V(4).Info("cannot add external data to the context", "reason", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,16 +7,17 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenerateResponse checks for validity of generate rule on the resource
|
||||
func GenerateResponse(policyContext *PolicyContext, gr kyvernov1beta1.UpdateRequest) (resp *response.EngineResponse) {
|
||||
func GenerateResponse(rclient registryclient.Client, policyContext *PolicyContext, gr kyvernov1beta1.UpdateRequest) (resp *response.EngineResponse) {
|
||||
policyStartTime := time.Now()
|
||||
return filterGenerateRules(policyContext, gr.Spec.Policy, policyStartTime)
|
||||
return filterGenerateRules(rclient, policyContext, gr.Spec.Policy, policyStartTime)
|
||||
}
|
||||
|
||||
func filterGenerateRules(policyContext *PolicyContext, policyNameKey string, startTime time.Time) *response.EngineResponse {
|
||||
func filterGenerateRules(rclient registryclient.Client, policyContext *PolicyContext, policyNameKey string, startTime time.Time) *response.EngineResponse {
|
||||
kind := policyContext.newResource.GetKind()
|
||||
name := policyContext.newResource.GetName()
|
||||
namespace := policyContext.newResource.GetNamespace()
|
||||
|
@ -50,7 +51,7 @@ func filterGenerateRules(policyContext *PolicyContext, policyNameKey string, sta
|
|||
}
|
||||
|
||||
for _, rule := range autogen.ComputeRules(policyContext.policy) {
|
||||
if ruleResp := filterRule(rule, policyContext); ruleResp != nil {
|
||||
if ruleResp := filterRule(rclient, rule, policyContext); ruleResp != nil {
|
||||
resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -12,7 +13,7 @@ import (
|
|||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/cosign"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
|
@ -62,7 +63,7 @@ func extractMatchingImages(policyContext *PolicyContext, rule *kyvernov1.Rule) (
|
|||
return matchingImages, imageRefs, nil
|
||||
}
|
||||
|
||||
func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineResponse, *ImageVerificationMetadata) {
|
||||
func VerifyAndPatchImages(rclient registryclient.Client, policyContext *PolicyContext) (*response.EngineResponse, *ImageVerificationMetadata) {
|
||||
resp := &response.EngineResponse{}
|
||||
|
||||
policy := policyContext.policy
|
||||
|
@ -82,7 +83,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineRespons
|
|||
defer policyContext.jsonContext.Restore()
|
||||
|
||||
// update image registry secrets
|
||||
if err := registryclient.DefaultClient.RefreshKeychainPullSecrets(); err != nil {
|
||||
if err := rclient.RefreshKeychainPullSecrets(context.TODO()); err != nil {
|
||||
logger.Error(err, "failed to update image pull secrets")
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineRespons
|
|||
}
|
||||
|
||||
policyContext.jsonContext.Restore()
|
||||
if err := LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err := LoadContext(logger, rclient, rule.Context, policyContext, rule.Name); err != nil {
|
||||
appendResponse(resp, rule, fmt.Sprintf("failed to load context: %s", err.Error()), response.RuleStatusError)
|
||||
continue
|
||||
}
|
||||
|
@ -136,7 +137,7 @@ func VerifyAndPatchImages(policyContext *PolicyContext) (*response.EngineRespons
|
|||
}
|
||||
|
||||
for _, imageVerify := range ruleCopy.VerifyImages {
|
||||
iv.verify(imageVerify, ruleImages)
|
||||
iv.verify(rclient, imageVerify, ruleImages)
|
||||
}
|
||||
|
||||
if applyRules == kyvernov1.ApplyOne && resp.PolicyResponse.RulesAppliedCount > 0 {
|
||||
|
@ -153,7 +154,7 @@ func appendResponse(resp *response.EngineResponse, rule *kyvernov1.Rule, msg str
|
|||
incrementErrorCount(resp)
|
||||
}
|
||||
|
||||
func substituteVariables(rule *kyvernov1.Rule, ctx context.EvalInterface, logger logr.Logger) (*kyvernov1.Rule, error) {
|
||||
func substituteVariables(rule *kyvernov1.Rule, ctx enginecontext.EvalInterface, logger logr.Logger) (*kyvernov1.Rule, error) {
|
||||
// remove attestations as variables are not substituted in them
|
||||
ruleCopy := *rule.DeepCopy()
|
||||
for i := range ruleCopy.VerifyImages {
|
||||
|
@ -184,7 +185,7 @@ type imageVerifier struct {
|
|||
|
||||
// verify applies policy rules to each matching image. The policy rule results and annotation patches are
|
||||
// added to tme imageVerifier `resp` and `ivm` fields.
|
||||
func (iv *imageVerifier) verify(imageVerify kyvernov1.ImageVerification, matchedImageInfos []apiutils.ImageInfo) {
|
||||
func (iv *imageVerifier) verify(rclient registryclient.Client, imageVerify kyvernov1.ImageVerification, matchedImageInfos []apiutils.ImageInfo) {
|
||||
// for backward compatibility
|
||||
imageVerify = *imageVerify.Convert()
|
||||
|
||||
|
@ -213,10 +214,10 @@ func (iv *imageVerifier) verify(imageVerify kyvernov1.ImageVerification, matched
|
|||
continue
|
||||
}
|
||||
|
||||
ruleResp, digest := iv.verifyImage(imageVerify, imageInfo)
|
||||
ruleResp, digest := iv.verifyImage(rclient, imageVerify, imageInfo)
|
||||
|
||||
if imageVerify.MutateDigest {
|
||||
patch, retrievedDigest, err := iv.handleMutateDigest(digest, imageInfo)
|
||||
patch, retrievedDigest, err := iv.handleMutateDigest(rclient, digest, imageInfo)
|
||||
if err != nil {
|
||||
ruleResp = ruleError(iv.rule, response.ImageVerify, "failed to update digest", err)
|
||||
} else if patch != nil {
|
||||
|
@ -242,13 +243,13 @@ func (iv *imageVerifier) verify(imageVerify kyvernov1.ImageVerification, matched
|
|||
}
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) handleMutateDigest(digest string, imageInfo apiutils.ImageInfo) ([]byte, string, error) {
|
||||
func (iv *imageVerifier) handleMutateDigest(rclient registryclient.Client, digest string, imageInfo apiutils.ImageInfo) ([]byte, string, error) {
|
||||
if imageInfo.Digest != "" {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
if digest == "" {
|
||||
desc, err := registryclient.DefaultClient.FetchImageDescriptor(imageInfo.String())
|
||||
desc, err := rclient.FetchImageDescriptor(context.TODO(), imageInfo.String())
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
@ -292,7 +293,7 @@ func imageMatches(image string, imagePatterns []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyImage(imageVerify kyvernov1.ImageVerification, imageInfo apiutils.ImageInfo) (*response.RuleResponse, string) {
|
||||
func (iv *imageVerifier) verifyImage(rclient registryclient.Client, imageVerify kyvernov1.ImageVerification, imageInfo apiutils.ImageInfo) (*response.RuleResponse, string) {
|
||||
if len(imageVerify.Attestors) <= 0 && len(imageVerify.Attestations) <= 0 {
|
||||
return nil, ""
|
||||
}
|
||||
|
@ -308,16 +309,16 @@ func (iv *imageVerifier) verifyImage(imageVerify kyvernov1.ImageVerification, im
|
|||
}
|
||||
|
||||
if len(imageVerify.Attestors) > 0 {
|
||||
ruleResp, _, _ := iv.verifyAttestors(imageVerify.Attestors, imageVerify, imageInfo, "")
|
||||
ruleResp, _, _ := iv.verifyAttestors(rclient, imageVerify.Attestors, imageVerify, imageInfo, "")
|
||||
if ruleResp.Status != response.RuleStatusPass {
|
||||
return ruleResp, ""
|
||||
}
|
||||
}
|
||||
|
||||
return iv.verifyAttestations(imageVerify, imageInfo)
|
||||
return iv.verifyAttestations(rclient, imageVerify, imageInfo)
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyAttestors(attestors []kyvernov1.AttestorSet, imageVerify kyvernov1.ImageVerification,
|
||||
func (iv *imageVerifier) verifyAttestors(rclient registryclient.Client, attestors []kyvernov1.AttestorSet, imageVerify kyvernov1.ImageVerification,
|
||||
imageInfo apiutils.ImageInfo, predicateType string,
|
||||
) (*response.RuleResponse, *cosign.Response, []kyvernov1.AttestorSet) {
|
||||
var cosignResponse *cosign.Response
|
||||
|
@ -328,7 +329,7 @@ func (iv *imageVerifier) verifyAttestors(attestors []kyvernov1.AttestorSet, imag
|
|||
var err error
|
||||
path := fmt.Sprintf(".attestors[%d]", i)
|
||||
iv.logger.V(4).Info("verifying attestors", "path", path)
|
||||
cosignResponse, err = iv.verifyAttestorSet(attestorSet, imageVerify, imageInfo, path, predicateType)
|
||||
cosignResponse, err = iv.verifyAttestorSet(rclient, attestorSet, imageVerify, imageInfo, path, predicateType)
|
||||
if err != nil {
|
||||
iv.logger.Error(err, "failed to verify image")
|
||||
msg := fmt.Sprintf("failed to verify image %s: %s", image, err.Error())
|
||||
|
@ -352,7 +353,7 @@ func (iv *imageVerifier) verifyAttestors(attestors []kyvernov1.AttestorSet, imag
|
|||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusPass, nil), cosignResponse, newAttestors
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyAttestations(imageVerify kyvernov1.ImageVerification, imageInfo apiutils.ImageInfo) (*response.RuleResponse, string) {
|
||||
func (iv *imageVerifier) verifyAttestations(rclient registryclient.Client, imageVerify kyvernov1.ImageVerification, imageInfo apiutils.ImageInfo) (*response.RuleResponse, string) {
|
||||
image := imageInfo.String()
|
||||
for i, attestation := range imageVerify.Attestations {
|
||||
var attestationError error
|
||||
|
@ -377,7 +378,7 @@ func (iv *imageVerifier) verifyAttestations(imageVerify kyvernov1.ImageVerificat
|
|||
for _, a := range entries {
|
||||
entryPath := fmt.Sprintf("%s.entries[%d]", attestorPath, i)
|
||||
opts, subPath := iv.buildOptionsAndPath(a, imageVerify, image, attestation)
|
||||
cosignResp, err := cosign.FetchAttestations(*opts)
|
||||
cosignResp, err := cosign.FetchAttestations(rclient, *opts)
|
||||
if err != nil {
|
||||
iv.logger.Error(err, "failed to fetch attestations")
|
||||
msg := fmt.Sprintf("failed to fetch attestations %s: %s", image, err.Error())
|
||||
|
@ -412,7 +413,7 @@ func (iv *imageVerifier) verifyAttestations(imageVerify kyvernov1.ImageVerificat
|
|||
return ruleResponse(*iv.rule, response.ImageVerify, msg, response.RuleStatusPass, nil), ""
|
||||
}
|
||||
|
||||
func (iv *imageVerifier) verifyAttestorSet(attestorSet kyvernov1.AttestorSet, imageVerify kyvernov1.ImageVerification,
|
||||
func (iv *imageVerifier) verifyAttestorSet(rclient registryclient.Client, attestorSet kyvernov1.AttestorSet, imageVerify kyvernov1.ImageVerification,
|
||||
imageInfo apiutils.ImageInfo, path, predicateType string,
|
||||
) (*cosign.Response, error) {
|
||||
var errorList []error
|
||||
|
@ -433,11 +434,11 @@ func (iv *imageVerifier) verifyAttestorSet(attestorSet kyvernov1.AttestorSet, im
|
|||
entryError = errors.Wrapf(err, "failed to unmarshal nested attestor %s", attestorPath)
|
||||
} else {
|
||||
attestorPath += ".attestor"
|
||||
cosignResp, entryError = iv.verifyAttestorSet(*nestedAttestorSet, imageVerify, imageInfo, attestorPath, predicateType)
|
||||
cosignResp, entryError = iv.verifyAttestorSet(rclient, *nestedAttestorSet, imageVerify, imageInfo, attestorPath, predicateType)
|
||||
}
|
||||
} else {
|
||||
opts, subPath := iv.buildOptionsAndPath(a, imageVerify, image, kyvernov1.Attestation{PredicateType: predicateType})
|
||||
cosignResp, entryError = cosign.VerifySignature(*opts)
|
||||
cosignResp, entryError = cosign.VerifySignature(rclient, *opts)
|
||||
if entryError != nil {
|
||||
entryError = errors.Wrapf(entryError, attestorPath+subPath)
|
||||
}
|
||||
|
@ -636,7 +637,7 @@ func (iv *imageVerifier) checkAttestations(a kyvernov1.Attestation, s map[string
|
|||
|
||||
func evaluateConditions(
|
||||
conditions []kyvernov1.AnyAllConditions,
|
||||
ctx context.Interface,
|
||||
ctx enginecontext.Interface,
|
||||
s map[string]interface{},
|
||||
log logr.Logger,
|
||||
) (bool, error) {
|
||||
|
@ -645,7 +646,7 @@ func evaluateConditions(
|
|||
return false, fmt.Errorf("failed to extract predicate from statement: %v", s)
|
||||
}
|
||||
|
||||
if err := context.AddJSONObject(ctx, predicate); err != nil {
|
||||
if err := enginecontext.AddJSONObject(ctx, predicate); err != nil {
|
||||
return false, errors.Wrapf(err, fmt.Sprintf("failed to add Statement to the context %v", s))
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
gojmespath "github.com/jmespath/go-jmespath"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func processImageValidationRule(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) *response.RuleResponse {
|
||||
func processImageValidationRule(log logr.Logger, rclient registryclient.Client, ctx *PolicyContext, rule *kyvernov1.Rule) *response.RuleResponse {
|
||||
if isDeleteRequest(ctx) {
|
||||
return nil
|
||||
}
|
||||
|
@ -26,7 +27,7 @@ func processImageValidationRule(log logr.Logger, ctx *PolicyContext, rule *kyver
|
|||
if len(matchingImages) == 0 {
|
||||
return ruleResponse(*rule, response.Validation, "image verified", response.RuleStatusSkip, nil)
|
||||
}
|
||||
if err := LoadContext(log, rule.Context, ctx, rule.Name); err != nil {
|
||||
if err := LoadContext(log, rclient, rule.Context, ctx, rule.Name); err != nil {
|
||||
if _, ok := err.(gojmespath.NotFoundError); ok {
|
||||
log.V(3).Info("failed to load context", "reason", err.Error())
|
||||
} else {
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
kubefake "k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
|
@ -149,7 +150,7 @@ func Test_CosignMockAttest(t *testing.T) {
|
|||
err := cosign.SetMock("ghcr.io/jimbugwadia/pause2:latest", attestationPayloads)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er, ivm := VerifyAndPatchImages(policyContext)
|
||||
er, ivm := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusPass,
|
||||
fmt.Sprintf("expected: %v, got: %v, failure: %v",
|
||||
|
@ -163,7 +164,7 @@ func Test_CosignMockAttest_fail(t *testing.T) {
|
|||
err := cosign.SetMock("ghcr.io/jimbugwadia/pause2:latest", attestationPayloads)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er, _ := VerifyAndPatchImages(policyContext)
|
||||
er, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
}
|
||||
|
@ -411,7 +412,7 @@ var testOtherKey = `-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD
|
|||
func Test_ConfigMapMissingSuccess(t *testing.T) {
|
||||
policyContext := buildContext(t, testConfigMapMissing, testConfigMapMissingResource, "")
|
||||
cosign.ClearMock()
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusSkip, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -423,7 +424,7 @@ func Test_ConfigMapMissingFailure(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
policyContext.informerCacheResolvers = resolver
|
||||
cosign.ClearMock()
|
||||
resp, _ := VerifyAndPatchImages(policyContext)
|
||||
resp, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, response.RuleStatusError, resp.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -431,7 +432,7 @@ func Test_ConfigMapMissingFailure(t *testing.T) {
|
|||
func Test_SignatureGoodSigned(t *testing.T) {
|
||||
policyContext := buildContext(t, testSampleSingleKeyPolicy, testSampleResource, "")
|
||||
cosign.ClearMock()
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusPass, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -440,7 +441,7 @@ func Test_SignatureUnsigned(t *testing.T) {
|
|||
cosign.ClearMock()
|
||||
unsigned := strings.Replace(testSampleResource, ":signed", ":unsigned", -1)
|
||||
policyContext := buildContext(t, testSampleSingleKeyPolicy, unsigned, "")
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusFail, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -449,7 +450,7 @@ func Test_SignatureWrongKey(t *testing.T) {
|
|||
cosign.ClearMock()
|
||||
otherKey := strings.Replace(testSampleResource, ":signed", ":signed-by-someone-else", -1)
|
||||
policyContext := buildContext(t, testSampleSingleKeyPolicy, otherKey, "")
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusFail, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -460,7 +461,7 @@ func Test_SignaturesMultiKey(t *testing.T) {
|
|||
policy = strings.Replace(policy, "KEY2", testVerifyImageKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "0", -1)
|
||||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusPass, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -470,7 +471,7 @@ func Test_SignaturesMultiKeyFail(t *testing.T) {
|
|||
policy := strings.Replace(testSampleMultipleKeyPolicy, "KEY1", testVerifyImageKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "0", -1)
|
||||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusFail, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -481,7 +482,7 @@ func Test_SignaturesMultiKeyOneGoodKey(t *testing.T) {
|
|||
policy = strings.Replace(policy, "KEY2", testOtherKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "1", -1)
|
||||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusPass, err.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -492,7 +493,7 @@ func Test_SignaturesMultiKeyZeroGoodKey(t *testing.T) {
|
|||
policy = strings.Replace(policy, "KEY2", testOtherKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "1", -1)
|
||||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
resp, _ := VerifyAndPatchImages(policyContext)
|
||||
resp, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, response.RuleStatusFail, resp.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -508,14 +509,14 @@ func Test_RuleSelectorImageVerify(t *testing.T) {
|
|||
applyAll := kyverno.ApplyAll
|
||||
spec.ApplyRules = &applyAll
|
||||
|
||||
resp, _ := VerifyAndPatchImages(policyContext)
|
||||
resp, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 2)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, response.RuleStatusPass, resp.PolicyResponse.Rules[0].Message)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[1].Status, response.RuleStatusFail, resp.PolicyResponse.Rules[1].Message)
|
||||
|
||||
applyOne := kyverno.ApplyOne
|
||||
spec.ApplyRules = &applyOne
|
||||
resp, _ = VerifyAndPatchImages(policyContext)
|
||||
resp, _ = VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status, response.RuleStatusPass, resp.PolicyResponse.Rules[0].Message)
|
||||
}
|
||||
|
@ -619,7 +620,7 @@ func Test_NestedAttestors(t *testing.T) {
|
|||
policy = strings.Replace(policy, "KEY2", testVerifyImageKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "0", -1)
|
||||
policyContext := buildContext(t, policy, testSampleResource, "")
|
||||
err, _ := VerifyAndPatchImages(policyContext)
|
||||
err, _ := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
||||
|
@ -627,7 +628,7 @@ func Test_NestedAttestors(t *testing.T) {
|
|||
policy = strings.Replace(policy, "KEY2", testOtherKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "0", -1)
|
||||
policyContext = buildContext(t, policy, testSampleResource, "")
|
||||
err, _ = VerifyAndPatchImages(policyContext)
|
||||
err, _ = VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
|
||||
|
@ -635,7 +636,7 @@ func Test_NestedAttestors(t *testing.T) {
|
|||
policy = strings.Replace(policy, "KEY2", testOtherKey, -1)
|
||||
policy = strings.Replace(policy, "COUNT", "1", -1)
|
||||
policyContext = buildContext(t, policy, testSampleResource, "")
|
||||
err, _ = VerifyAndPatchImages(policyContext)
|
||||
err, _ = VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(err.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, err.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
}
|
||||
|
@ -728,7 +729,7 @@ func Test_MarkImageVerified(t *testing.T) {
|
|||
err := cosign.SetMock(image, attestationPayloads)
|
||||
assert.NilError(t, err)
|
||||
|
||||
engineResponse, verifiedImages := VerifyAndPatchImages(policyContext)
|
||||
engineResponse, verifiedImages := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Assert(t, engineResponse != nil)
|
||||
assert.Equal(t, len(engineResponse.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
@ -821,7 +822,7 @@ func Test_ParsePEMDelimited(t *testing.T) {
|
|||
err := cosign.SetMock(image, signaturePayloads)
|
||||
assert.NilError(t, err)
|
||||
|
||||
engineResponse, verifiedImages := VerifyAndPatchImages(policyContext)
|
||||
engineResponse, verifiedImages := VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
assert.Assert(t, engineResponse != nil)
|
||||
assert.Equal(t, len(engineResponse.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
)
|
||||
|
||||
// LoadContext - Fetches and adds external data to the Context.
|
||||
func LoadContext(logger logr.Logger, contextEntries []kyvernov1.ContextEntry, ctx *PolicyContext, ruleName string) error {
|
||||
func LoadContext(logger logr.Logger, rclient registryclient.Client, contextEntries []kyvernov1.ContextEntry, ctx *PolicyContext, ruleName string) error {
|
||||
if len(contextEntries) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ func LoadContext(logger logr.Logger, contextEntries []kyvernov1.ContextEntry, ct
|
|||
// Context Variable should be loaded after the values loaded from values file
|
||||
for _, entry := range contextEntries {
|
||||
if entry.ImageRegistry != nil && hasRegistryAccess {
|
||||
if err := loadImageData(logger, entry, ctx); err != nil {
|
||||
// rclient := store.GetRegistryClient()
|
||||
if err := loadImageData(rclient, logger, entry, ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if entry.Variable != nil {
|
||||
|
@ -68,7 +69,7 @@ func LoadContext(logger logr.Logger, contextEntries []kyvernov1.ContextEntry, ct
|
|||
return err
|
||||
}
|
||||
} else if entry.ImageRegistry != nil {
|
||||
if err := loadImageData(logger, entry, ctx); err != nil {
|
||||
if err := loadImageData(rclient, logger, entry, ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if entry.Variable != nil {
|
||||
|
@ -140,11 +141,11 @@ func loadVariable(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyC
|
|||
}
|
||||
}
|
||||
|
||||
func loadImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) error {
|
||||
if err := registryclient.DefaultClient.RefreshKeychainPullSecrets(); err != nil {
|
||||
func loadImageData(rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) error {
|
||||
if err := rclient.RefreshKeychainPullSecrets(context.TODO()); err != nil {
|
||||
return fmt.Errorf("unable to load image registry credentials, %w", err)
|
||||
}
|
||||
imageData, err := fetchImageData(logger, entry, ctx)
|
||||
imageData, err := fetchImageData(rclient, logger, entry, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -158,7 +159,7 @@ func loadImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Policy
|
|||
return nil
|
||||
}
|
||||
|
||||
func fetchImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) (interface{}, error) {
|
||||
func fetchImageData(rclient registryclient.Client, logger logr.Logger, entry kyvernov1.ContextEntry, ctx *PolicyContext) (interface{}, error) {
|
||||
ref, err := variables.SubstituteAll(logger, ctx.jsonContext, entry.ImageRegistry.Reference)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ailed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.Reference, err)
|
||||
|
@ -171,7 +172,7 @@ func fetchImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Polic
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.ImageRegistry.JMESPath, err)
|
||||
}
|
||||
imageData, err := fetchImageDataMap(refString)
|
||||
imageData, err := fetchImageDataMap(rclient, refString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -185,8 +186,8 @@ func fetchImageData(logger logr.Logger, entry kyvernov1.ContextEntry, ctx *Polic
|
|||
}
|
||||
|
||||
// FetchImageDataMap fetches image information from the remote registry.
|
||||
func fetchImageDataMap(ref string) (interface{}, error) {
|
||||
desc, err := registryclient.DefaultClient.FetchImageDescriptor(ref)
|
||||
func fetchImageDataMap(rclient registryclient.Client, ref string) (interface{}, error) {
|
||||
desc, err := rclient.FetchImageDescriptor(context.TODO(), ref)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -13,11 +13,12 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/mutate"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// Mutate performs mutation. Overlay first and then mutation patches
|
||||
func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
func Mutate(rclient registryclient.Client, policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
startTime := time.Now()
|
||||
policy := policyContext.policy
|
||||
resp = &response.EngineResponse{
|
||||
|
@ -69,7 +70,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
logger.Error(err, "failed to query resource object")
|
||||
}
|
||||
|
||||
if err := LoadContext(logger, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if err := LoadContext(logger, rclient, rule.Context, policyContext, rule.Name); err != nil {
|
||||
if _, ok := err.(gojmespath.NotFoundError); ok {
|
||||
logger.V(3).Info("failed to load context", "reason", err.Error())
|
||||
} else {
|
||||
|
@ -108,7 +109,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
logger.V(4).Info("apply rule to resource", "rule", rule.Name, "resource namespace", patchedResource.GetNamespace(), "resource name", patchedResource.GetName())
|
||||
var ruleResp *response.RuleResponse
|
||||
if rule.Mutation.ForEachMutation != nil {
|
||||
ruleResp, patchedResource = mutateForEach(ruleCopy, policyContext, patchedResource, logger)
|
||||
ruleResp, patchedResource = mutateForEach(rclient, ruleCopy, policyContext, patchedResource, logger)
|
||||
} else {
|
||||
ruleResp, patchedResource = mutateResource(ruleCopy, policyContext, patchedResource, logger)
|
||||
}
|
||||
|
@ -158,7 +159,7 @@ func mutateResource(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructu
|
|||
return ruleResp, mutateResp.PatchedResource
|
||||
}
|
||||
|
||||
func mutateForEach(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructured.Unstructured, logger logr.Logger) (*response.RuleResponse, unstructured.Unstructured) {
|
||||
func mutateForEach(rclient registryclient.Client, rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructured.Unstructured, logger logr.Logger) (*response.RuleResponse, unstructured.Unstructured) {
|
||||
foreachList := rule.Mutation.ForEachMutation
|
||||
if foreachList == nil {
|
||||
return nil, resource
|
||||
|
@ -169,7 +170,7 @@ func mutateForEach(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructur
|
|||
allPatches := make([][]byte, 0)
|
||||
|
||||
for _, foreach := range foreachList {
|
||||
if err := LoadContext(logger, rule.Context, ctx, rule.Name); err != nil {
|
||||
if err := LoadContext(logger, rclient, rule.Context, ctx, rule.Name); err != nil {
|
||||
logger.Error(err, "failed to load context")
|
||||
return ruleError(rule, response.Mutation, "failed to load context", err), resource
|
||||
}
|
||||
|
@ -189,7 +190,7 @@ func mutateForEach(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructur
|
|||
return ruleError(rule, response.Mutation, msg, err), resource
|
||||
}
|
||||
|
||||
mutateResp := mutateElements(rule.Name, foreach, ctx, elements, patchedResource, logger)
|
||||
mutateResp := mutateElements(rclient, rule.Name, foreach, ctx, elements, patchedResource, logger)
|
||||
if mutateResp.Status == response.RuleStatusError {
|
||||
logger.Error(err, "failed to mutate elements")
|
||||
return buildRuleResponse(rule, mutateResp, nil), resource
|
||||
|
@ -213,7 +214,7 @@ func mutateForEach(rule *kyvernov1.Rule, ctx *PolicyContext, resource unstructur
|
|||
return r, patchedResource
|
||||
}
|
||||
|
||||
func mutateElements(name string, foreach kyvernov1.ForEachMutation, ctx *PolicyContext, elements []interface{}, resource unstructured.Unstructured, logger logr.Logger) *mutate.Response {
|
||||
func mutateElements(rclient registryclient.Client, name string, foreach kyvernov1.ForEachMutation, ctx *PolicyContext, elements []interface{}, resource unstructured.Unstructured, logger logr.Logger) *mutate.Response {
|
||||
ctx.jsonContext.Checkpoint()
|
||||
defer ctx.jsonContext.Restore()
|
||||
|
||||
|
@ -235,7 +236,7 @@ func mutateElements(name string, foreach kyvernov1.ForEachMutation, ctx *PolicyC
|
|||
return mutateError(err, fmt.Sprintf("failed to add element to mutate.foreach[%d].context", i))
|
||||
}
|
||||
|
||||
if err := LoadContext(logger, foreach.Context, ctx, name); err != nil {
|
||||
if err := LoadContext(logger, rclient, foreach.Context, ctx, name); err != nil {
|
||||
return mutateError(err, fmt.Sprintf("failed to load to mutate.foreach[%d].context", i))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -93,7 +94,7 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
|
@ -166,7 +167,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Assert(t, strings.Contains(er.PolicyResponse.Rules[0].Message, "Unknown key \"name1\" in path"))
|
||||
}
|
||||
|
@ -263,7 +264,7 @@ func Test_variableSubstitutionCLI(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
t.Log(string(expectedPatch))
|
||||
|
@ -372,7 +373,7 @@ func Test_chained_rules(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
containers, _, err := unstructured.NestedSlice(er.PatchedResource.Object, "spec", "containers")
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, containers[0].(map[string]interface{})["image"], "otherregistry.corp.com/foo/bash:5.0")
|
||||
|
@ -460,7 +461,7 @@ func Test_precondition(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
|
@ -557,7 +558,7 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
t.Log(string(expectedPatch))
|
||||
t.Log(string(er.PolicyResponse.Rules[0].Patches[0]))
|
||||
if !reflect.DeepEqual(expectedPatch, er.PolicyResponse.Rules[0].Patches[0]) {
|
||||
|
@ -651,7 +652,7 @@ func Test_foreach(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
@ -758,7 +759,7 @@ func Test_foreach_element_mutation(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
@ -884,7 +885,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
@ -1011,7 +1012,7 @@ func Test_foreach_order_mutation_(t *testing.T) {
|
|||
err = enginecontext.MutateResourceWithImageInfo(resourceRaw, ctx)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
|
||||
|
@ -1457,7 +1458,7 @@ func Test_mutate_existing_resources(t *testing.T) {
|
|||
newResource: *trigger,
|
||||
}
|
||||
}
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
for _, rr := range er.PolicyResponse.Rules {
|
||||
for i, p := range rr.Patches {
|
||||
|
@ -1565,7 +1566,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
newResource: *resourceUnstructured,
|
||||
}
|
||||
|
||||
er := Mutate(policyContext)
|
||||
er := Mutate(registryclient.NewOrDie(), policyContext)
|
||||
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[1].Patches), 1)
|
||||
|
@ -1580,7 +1581,7 @@ func Test_RuleSelectorMutate(t *testing.T) {
|
|||
applyOne := kyverno.ApplyOne
|
||||
policyContext.policy.GetSpec().ApplyRules = &applyOne
|
||||
|
||||
er = Mutate(policyContext)
|
||||
er = Mutate(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules[0].Patches), 1)
|
||||
|
||||
|
@ -1947,7 +1948,7 @@ func Test_SpecialCharacters(t *testing.T) {
|
|||
}
|
||||
|
||||
// Mutate and make sure that we got the expected amount of rules.
|
||||
patches := Mutate(policyContext).GetPatches()
|
||||
patches := Mutate(registryclient.NewOrDie(), policyContext).GetPatches()
|
||||
if !reflect.DeepEqual(patches, tt.want) {
|
||||
t.Errorf("Mutate() got patches %s, expected %s", patches, tt.want)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
"github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/pss"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
|
@ -30,7 +31,7 @@ import (
|
|||
)
|
||||
|
||||
// Validate applies validation rules from policy on the resource
|
||||
func Validate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
func Validate(rclient registryclient.Client, policyContext *PolicyContext) (resp *response.EngineResponse) {
|
||||
resp = &response.EngineResponse{}
|
||||
startTime := time.Now()
|
||||
|
||||
|
@ -41,7 +42,7 @@ func Validate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
logger.V(4).Info("finished policy processing", "processingTime", resp.PolicyResponse.ProcessingTime.String(), "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount)
|
||||
}()
|
||||
|
||||
resp = validateResource(logger, policyContext)
|
||||
resp = validateResource(logger, rclient, policyContext)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -88,7 +89,7 @@ func buildResponse(ctx *PolicyContext, resp *response.EngineResponse, startTime
|
|||
resp.PolicyResponse.PolicyExecutionTimestamp = startTime.Unix()
|
||||
}
|
||||
|
||||
func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineResponse {
|
||||
func validateResource(log logr.Logger, rclient registryclient.Client, ctx *PolicyContext) *response.EngineResponse {
|
||||
resp := &response.EngineResponse{}
|
||||
|
||||
ctx.jsonContext.Checkpoint()
|
||||
|
@ -128,9 +129,9 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
|
|||
|
||||
var ruleResp *response.RuleResponse
|
||||
if hasValidate && !hasYAMLSignatureVerify {
|
||||
ruleResp = processValidationRule(log, ctx, rule)
|
||||
ruleResp = processValidationRule(log, rclient, ctx, rule)
|
||||
} else if hasValidateImage {
|
||||
ruleResp = processImageValidationRule(log, ctx, rule)
|
||||
ruleResp = processImageValidationRule(log, rclient, ctx, rule)
|
||||
} else if hasYAMLSignatureVerify {
|
||||
ruleResp = processYAMLValidationRule(log, ctx, rule)
|
||||
}
|
||||
|
@ -146,7 +147,7 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
|
|||
return resp
|
||||
}
|
||||
|
||||
func validateOldObject(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) (*response.RuleResponse, error) {
|
||||
func validateOldObject(log logr.Logger, rclient registryclient.Client, ctx *PolicyContext, rule *kyvernov1.Rule) (*response.RuleResponse, error) {
|
||||
ctxCopy := ctx.Copy()
|
||||
ctxCopy.newResource = *ctxCopy.oldResource.DeepCopy()
|
||||
ctxCopy.oldResource = unstructured.Unstructured{}
|
||||
|
@ -159,11 +160,11 @@ func validateOldObject(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule
|
|||
return nil, errors.Wrapf(err, "failed to replace old object in the JSON context")
|
||||
}
|
||||
|
||||
return processValidationRule(log, ctxCopy, rule), nil
|
||||
return processValidationRule(log, rclient, ctxCopy, rule), nil
|
||||
}
|
||||
|
||||
func processValidationRule(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) *response.RuleResponse {
|
||||
v := newValidator(log, ctx, rule)
|
||||
func processValidationRule(log logr.Logger, rclient registryclient.Client, ctx *PolicyContext, rule *kyvernov1.Rule) *response.RuleResponse {
|
||||
v := newValidator(log, rclient, ctx, rule)
|
||||
if rule.Validation.ForEachValidation != nil {
|
||||
return v.validateForEach()
|
||||
}
|
||||
|
@ -195,9 +196,10 @@ type validator struct {
|
|||
anyPattern apiextensions.JSON
|
||||
deny *kyvernov1.Deny
|
||||
podSecurity *kyvernov1.PodSecurity
|
||||
rclient registryclient.Client
|
||||
}
|
||||
|
||||
func newValidator(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) *validator {
|
||||
func newValidator(log logr.Logger, rclient registryclient.Client, ctx *PolicyContext, rule *kyvernov1.Rule) *validator {
|
||||
ruleCopy := rule.DeepCopy()
|
||||
return &validator{
|
||||
log: log,
|
||||
|
@ -209,10 +211,11 @@ func newValidator(log logr.Logger, ctx *PolicyContext, rule *kyvernov1.Rule) *va
|
|||
anyPattern: ruleCopy.Validation.GetAnyPattern(),
|
||||
deny: ruleCopy.Validation.Deny,
|
||||
podSecurity: ruleCopy.Validation.PodSecurity,
|
||||
rclient: rclient,
|
||||
}
|
||||
}
|
||||
|
||||
func newForeachValidator(foreach kyvernov1.ForEachValidation, rule *kyvernov1.Rule, ctx *PolicyContext, log logr.Logger) *validator {
|
||||
func newForeachValidator(log logr.Logger, rclient registryclient.Client, foreach kyvernov1.ForEachValidation, rule *kyvernov1.Rule, ctx *PolicyContext) *validator {
|
||||
ruleCopy := rule.DeepCopy()
|
||||
anyAllConditions, err := utils.ToMap(foreach.AnyAllConditions)
|
||||
if err != nil {
|
||||
|
@ -228,6 +231,7 @@ func newForeachValidator(foreach kyvernov1.ForEachValidation, rule *kyvernov1.Ru
|
|||
pattern: foreach.GetPattern(),
|
||||
anyPattern: foreach.GetAnyPattern(),
|
||||
deny: foreach.Deny,
|
||||
rclient: rclient,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +260,7 @@ func (v *validator) validate() *response.RuleResponse {
|
|||
|
||||
ruleResponse := v.validateResourceWithRule()
|
||||
if isUpdateRequest(v.ctx) {
|
||||
priorResp, err := validateOldObject(v.log, v.ctx, v.rule)
|
||||
priorResp, err := validateOldObject(v.log, v.rclient, v.ctx, v.rule)
|
||||
if err != nil {
|
||||
return ruleError(v.rule, response.Validation, "failed to validate old object", err)
|
||||
}
|
||||
|
@ -338,7 +342,7 @@ func (v *validator) validateElements(foreach kyvernov1.ForEachValidation, elemen
|
|||
return ruleError(v.rule, response.Validation, "failed to process foreach", err), applyCount
|
||||
}
|
||||
|
||||
foreachValidator := newForeachValidator(foreach, v.rule, ctx, v.log)
|
||||
foreachValidator := newForeachValidator(v.log, v.rclient, foreach, v.rule, ctx)
|
||||
r := foreachValidator.validate()
|
||||
if r == nil {
|
||||
v.log.V(2).Info("skip rule due to empty result")
|
||||
|
@ -398,7 +402,7 @@ func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, el
|
|||
}
|
||||
|
||||
func (v *validator) loadContext() error {
|
||||
if err := LoadContext(v.log, v.contextEntries, v.ctx, v.rule.Name); err != nil {
|
||||
if err := LoadContext(v.log, v.rclient, v.contextEntries, v.ctx, v.rule.Name); err != nil {
|
||||
if _, ok := err.(gojmespath.NotFoundError); ok {
|
||||
v.log.V(3).Info("failed to load context", "reason", err.Error())
|
||||
} else {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
utils2 "github.com/kyverno/kyverno/pkg/utils"
|
||||
"gotest.tools/assert"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
|
@ -131,7 +132,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/",
|
||||
}
|
||||
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -231,7 +232,7 @@ func TestValidate_image_tag_pass(t *testing.T) {
|
|||
"validation rule 'validate-tag' passed.",
|
||||
"validation rule 'validate-latest' passed.",
|
||||
}
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -305,7 +306,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
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/"}
|
||||
|
@ -388,7 +389,7 @@ func TestValidate_host_network_port(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
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 {
|
||||
|
@ -478,7 +479,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -566,7 +567,7 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
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 {
|
||||
|
@ -636,7 +637,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -709,7 +710,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -783,7 +784,7 @@ func TestValidate_inequality_List_Processing(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -863,7 +864,7 @@ func TestValidate_inequality_List_ProcessingBrackets(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod rule 2' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -937,7 +938,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
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 {
|
||||
|
@ -1012,7 +1013,7 @@ func TestValidate_AnchorList_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1087,7 +1088,7 @@ func TestValidate_AnchorList_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -1157,7 +1158,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1228,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'pod image rule' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1315,7 +1316,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
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 {
|
||||
|
@ -1402,7 +1403,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) {
|
|||
|
||||
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
|
||||
assert.NilError(t, err)
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
msgs := []string{"validation rule 'validate-host-path' passed."}
|
||||
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
|
@ -1478,7 +1479,7 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusError)
|
||||
|
@ -1571,7 +1572,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusError)
|
||||
|
@ -1632,7 +1633,7 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.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/")
|
||||
}
|
||||
|
@ -1723,7 +1724,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, len(er.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusError)
|
||||
|
@ -1816,7 +1817,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message,
|
||||
|
@ -1921,7 +1922,7 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Message, "The animal cow is not in the allowed list of animals.")
|
||||
}
|
||||
|
@ -1974,7 +1975,7 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
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].String(), er.PolicyResponse.Rules[i].Status.String())
|
||||
|
@ -2140,7 +2141,7 @@ func executeTest(t *testing.T, test testCase) {
|
|||
jsonContext: ctx,
|
||||
}
|
||||
|
||||
resp := Validate(pc)
|
||||
resp := Validate(registryclient.NewOrDie(), pc)
|
||||
if resp.IsSuccessful() && test.requestDenied {
|
||||
t.Errorf("Testcase has failed, policy: %v", policy.Name)
|
||||
}
|
||||
|
@ -2239,7 +2240,7 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
|
|||
msgs := []string{
|
||||
"restrict pod counts to be no more than 10 on node minikube",
|
||||
}
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
for index, r := range er.PolicyResponse.Rules {
|
||||
assert.Equal(t, r.Message, msgs[index])
|
||||
}
|
||||
|
@ -2328,7 +2329,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx})
|
||||
assert.Assert(t, !er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -2417,7 +2418,7 @@ func Test_StringInDenyCondition(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: ctx})
|
||||
assert.Assert(t, er.IsSuccessful())
|
||||
}
|
||||
|
||||
|
@ -3004,7 +3005,7 @@ func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string,
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
er := Validate(policyContext)
|
||||
er := Validate(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
assert.Equal(t, er.PolicyResponse.Rules[0].Status, status)
|
||||
if msg != "" {
|
||||
|
@ -3068,7 +3069,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
newResource: *resourceUnstructured}
|
||||
engineResponseCreate := Validate(policyContextCreate)
|
||||
engineResponseCreate := Validate(registryclient.NewOrDie(), policyContextCreate)
|
||||
assert.Equal(t, len(engineResponseCreate.PolicyResponse.Rules), 1)
|
||||
assert.Equal(t, engineResponseCreate.PolicyResponse.Rules[0].Status, response.RuleStatusFail)
|
||||
|
||||
|
@ -3076,7 +3077,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
|
|||
policy: &policy,
|
||||
jsonContext: ctx,
|
||||
oldResource: *resourceUnstructured}
|
||||
engineResponseDelete := Validate(policyContextDelete)
|
||||
engineResponseDelete := Validate(registryclient.NewOrDie(), policyContextDelete)
|
||||
assert.Equal(t, len(engineResponseDelete.PolicyResponse.Rules), 0)
|
||||
}
|
||||
|
||||
|
@ -3135,7 +3136,7 @@ func Test_ValidatePattern_anyPattern(t *testing.T) {
|
|||
resourceUnstructured, err := utils.ConvertToUnstructured(tc.rawResource)
|
||||
assert.NilError(t, err)
|
||||
|
||||
er := Validate(&PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
er := Validate(registryclient.NewOrDie(), &PolicyContext{policy: &policy, newResource: *resourceUnstructured, jsonContext: context.NewContext()})
|
||||
if tc.expectedFailed {
|
||||
assert.Assert(t, er.IsFailed())
|
||||
} else if tc.expectedSkipped {
|
||||
|
|
|
@ -13,14 +13,20 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
// applyPolicy applies policy on a resource
|
||||
func applyPolicy(policy kyvernov1.PolicyInterface, resource unstructured.Unstructured,
|
||||
logger logr.Logger, excludeGroupRole []string,
|
||||
client dclient.Interface, namespaceLabels map[string]string,
|
||||
func applyPolicy(
|
||||
policy kyvernov1.PolicyInterface,
|
||||
resource unstructured.Unstructured,
|
||||
logger logr.Logger,
|
||||
excludeGroupRole []string,
|
||||
client dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
namespaceLabels map[string]string,
|
||||
) (responses []*response.EngineResponse) {
|
||||
startTime := time.Now()
|
||||
defer func() {
|
||||
|
@ -56,7 +62,7 @@ func applyPolicy(policy kyvernov1.PolicyInterface, resource unstructured.Unstruc
|
|||
logger.Error(err, "unable to set operation in context")
|
||||
}
|
||||
|
||||
engineResponseMutation, err = mutation(policy, resource, logger, ctx, namespaceLabels)
|
||||
engineResponseMutation, err = mutation(policy, resource, logger, ctx, rclient, namespaceLabels)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to process mutation rule")
|
||||
}
|
||||
|
@ -68,19 +74,26 @@ func applyPolicy(policy kyvernov1.PolicyInterface, resource unstructured.Unstruc
|
|||
WithClient(client).
|
||||
WithExcludeGroupRole(excludeGroupRole...)
|
||||
|
||||
engineResponseValidation = engine.Validate(policyCtx)
|
||||
engineResponseValidation = engine.Validate(rclient, policyCtx)
|
||||
engineResponses = append(engineResponses, mergeRuleRespose(engineResponseMutation, engineResponseValidation))
|
||||
|
||||
return engineResponses
|
||||
}
|
||||
|
||||
func mutation(policy kyvernov1.PolicyInterface, resource unstructured.Unstructured, log logr.Logger, jsonContext context.Interface, namespaceLabels map[string]string) (*response.EngineResponse, error) {
|
||||
func mutation(
|
||||
policy kyvernov1.PolicyInterface,
|
||||
resource unstructured.Unstructured,
|
||||
log logr.Logger,
|
||||
jsonContext context.Interface,
|
||||
rclient registryclient.Client,
|
||||
namespaceLabels map[string]string,
|
||||
) (*response.EngineResponse, error) {
|
||||
policyContext := engine.NewPolicyContextWithJsonContext(jsonContext).
|
||||
WithPolicy(policy).
|
||||
WithNamespaceLabels(namespaceLabels).
|
||||
WithNewResource(resource)
|
||||
|
||||
engineResponse := engine.Mutate(policyContext)
|
||||
engineResponse := engine.Mutate(rclient, policyContext)
|
||||
if !engineResponse.IsSuccessful() {
|
||||
log.V(4).Info("failed to apply mutation rules; reporting them")
|
||||
return engineResponse, nil
|
||||
|
|
|
@ -81,7 +81,7 @@ func (pc *PolicyController) applyPolicy(policy kyvernov1.PolicyInterface, resour
|
|||
}
|
||||
|
||||
namespaceLabels := common.GetNamespaceSelectorsFromNamespaceLister(resource.GetKind(), resource.GetNamespace(), pc.nsLister, logger)
|
||||
engineResponse := applyPolicy(policy, resource, logger, pc.configHandler.GetExcludeGroupRole(), pc.client, namespaceLabels)
|
||||
engineResponse := applyPolicy(policy, resource, logger, pc.configHandler.GetExcludeGroupRole(), pc.client, pc.rclient, namespaceLabels)
|
||||
engineResponses = append(engineResponses, engineResponse...)
|
||||
|
||||
// post-processing, register the resource as processed
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"golang.org/x/exp/slices"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
@ -53,8 +54,10 @@ const (
|
|||
type PolicyController struct {
|
||||
client dclient.Interface
|
||||
kyvernoClient versioned.Interface
|
||||
pInformer kyvernov1informers.ClusterPolicyInformer
|
||||
npInformer kyvernov1informers.PolicyInformer
|
||||
rclient registryclient.Client
|
||||
|
||||
pInformer kyvernov1informers.ClusterPolicyInformer
|
||||
npInformer kyvernov1informers.PolicyInformer
|
||||
|
||||
eventGen event.Interface
|
||||
eventRecorder record.EventRecorder
|
||||
|
@ -93,6 +96,7 @@ type PolicyController struct {
|
|||
func NewPolicyController(
|
||||
kyvernoClient versioned.Interface,
|
||||
client dclient.Interface,
|
||||
rclient registryclient.Client,
|
||||
pInformer kyvernov1informers.ClusterPolicyInformer,
|
||||
npInformer kyvernov1informers.PolicyInformer,
|
||||
urInformer kyvernov1beta1informers.UpdateRequestInformer,
|
||||
|
@ -112,6 +116,7 @@ func NewPolicyController(
|
|||
pc := PolicyController{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
rclient: rclient,
|
||||
pInformer: pInformer,
|
||||
npInformer: npInformer,
|
||||
eventGen: eventGen,
|
||||
|
|
|
@ -105,7 +105,7 @@ func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest
|
|||
return false, errors.Wrapf(err, "failed to build policy context for rule %s", rule.Name)
|
||||
}
|
||||
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
engineResponse := engine.ApplyBackgroundChecks(pc.rclient, policyContext)
|
||||
if len(engineResponse.PolicyResponse.Rules) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
|
|
@ -11,51 +11,55 @@ import (
|
|||
"github.com/chrismellard/docker-credential-acr-env/pkg/credhelper"
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
"github.com/google/go-containerregistry/pkg/authn/github"
|
||||
kauth "github.com/google/go-containerregistry/pkg/authn/kubernetes"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/v1/google"
|
||||
gcrremote "github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sigstore/cosign/pkg/oci/remote"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// DefaultClient is default registry client.
|
||||
var DefaultClient, _ = InitClient()
|
||||
var baseKeychain = authn.NewMultiKeychain(
|
||||
authn.DefaultKeychain,
|
||||
google.Keychain,
|
||||
authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(io.Discard))),
|
||||
authn.NewKeychainFromHelper(credhelper.NewACRCredentialsHelper()),
|
||||
github.Keychain,
|
||||
)
|
||||
|
||||
// Client provides registry related objects.
|
||||
type Client interface {
|
||||
// Keychain provides keychain object.
|
||||
Keychain() authn.Keychain
|
||||
// getKeychain provides keychain object.
|
||||
getKeychain() authn.Keychain
|
||||
|
||||
// Transport provides transport object.
|
||||
Transport() *http.Transport
|
||||
// getTransport provides transport object.
|
||||
getTransport() http.RoundTripper
|
||||
|
||||
// FetchImageDescriptor fetches Descriptor from registry with given imageRef
|
||||
// and provides access to metadata about remote artifact.
|
||||
FetchImageDescriptor(imageRef string) (*gcrremote.Descriptor, error)
|
||||
FetchImageDescriptor(context.Context, string) (*gcrremote.Descriptor, error)
|
||||
|
||||
// UseLocalKeychain updates keychain with the default local keychain.
|
||||
UseLocalKeychain()
|
||||
// // RefreshKeychainPullSecrets loads fresh data from pull secrets and updates Keychain.
|
||||
// // If pull secrets are empty - returns.
|
||||
RefreshKeychainPullSecrets(context.Context) error
|
||||
|
||||
// RefreshKeychainPullSecrets loads fresh data from pull secrets and updates Keychain.
|
||||
// If pull secrets are empty - returns.
|
||||
RefreshKeychainPullSecrets() error
|
||||
// BuildRemoteOption builds remote.Option based on client.
|
||||
BuildRemoteOption() remote.Option
|
||||
}
|
||||
|
||||
// InitClient initialize registry client with given options.
|
||||
func InitClient(options ...Option) (Client, error) {
|
||||
baseKeychain := authn.NewMultiKeychain(
|
||||
authn.DefaultKeychain,
|
||||
google.Keychain,
|
||||
authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(io.Discard))),
|
||||
authn.NewKeychainFromHelper(credhelper.NewACRCredentialsHelper()),
|
||||
github.Keychain,
|
||||
)
|
||||
type client struct {
|
||||
keychain authn.Keychain
|
||||
transport *http.Transport
|
||||
pullSecretRefresher func(context.Context, *client) error
|
||||
}
|
||||
|
||||
// Option is an option to initialize registry client.
|
||||
type Option = func(*client) error
|
||||
|
||||
// New creates a new Client with options
|
||||
func New(options ...Option) (Client, error) {
|
||||
c := &client{
|
||||
keychain: baseKeychain,
|
||||
baseKeychain: baseKeychain,
|
||||
transport: gcrremote.DefaultTransport.(*http.Transport),
|
||||
keychain: baseKeychain,
|
||||
transport: gcrremote.DefaultTransport.(*http.Transport),
|
||||
}
|
||||
for _, opt := range options {
|
||||
if err := opt(c); err != nil {
|
||||
|
@ -65,28 +69,30 @@ func InitClient(options ...Option) (Client, error) {
|
|||
return c, nil
|
||||
}
|
||||
|
||||
// Option is an option to initialize registry client.
|
||||
type Option func(*client) error
|
||||
// New creates a new Client with options
|
||||
func NewOrDie(options ...Option) Client {
|
||||
c, err := New(options...)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// WithKeychainPullSecrets provides initialize registry client option that allows to use pull secrets.
|
||||
func WithKeychainPullSecrets(kubClient kubernetes.Interface, namespace, serviceAccount string, imagePullSecrets []string) Option {
|
||||
func WithKeychainPullSecrets(ctx context.Context, kubClient kubernetes.Interface, namespace, serviceAccount string, imagePullSecrets ...string) Option {
|
||||
return func(c *client) error {
|
||||
refresher := func(c *client) error {
|
||||
freshKeychain, err := generateKeychainForPullSecrets(kubClient, namespace, serviceAccount, imagePullSecrets)
|
||||
c.pullSecretRefresher = func(ctx context.Context, c *client) error {
|
||||
freshKeychain, err := generateKeychainForPullSecrets(ctx, kubClient, namespace, serviceAccount, imagePullSecrets...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.keychain = authn.NewMultiKeychain(
|
||||
c.baseKeychain,
|
||||
baseKeychain,
|
||||
freshKeychain,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
c.pullSecretRefresher = refresher
|
||||
return refresher(c)
|
||||
return c.pullSecretRefresher(ctx, c)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,79 +104,50 @@ func WithAllowInsecureRegistry() Option {
|
|||
}
|
||||
}
|
||||
|
||||
type client struct {
|
||||
keychain authn.Keychain
|
||||
transport *http.Transport
|
||||
|
||||
baseKeychain authn.Keychain
|
||||
pullSecretRefresher func(*client) error
|
||||
}
|
||||
|
||||
// Keychain provides keychain object.
|
||||
func (c *client) Keychain() authn.Keychain {
|
||||
return c.keychain
|
||||
}
|
||||
|
||||
// Transport provides transport object.
|
||||
func (c *client) Transport() *http.Transport {
|
||||
return c.transport
|
||||
}
|
||||
|
||||
// UseLocalKeychain updates keychain with the default local keychain.
|
||||
func (c *client) UseLocalKeychain() {
|
||||
c.keychain = authn.DefaultKeychain
|
||||
c.baseKeychain = authn.DefaultKeychain
|
||||
}
|
||||
|
||||
// FetchImageDescriptor fetches Descriptor from registry with given imageRef
|
||||
// and provides access to metadata about remote artifact.
|
||||
func (c *client) FetchImageDescriptor(imageRef string) (*gcrremote.Descriptor, error) {
|
||||
parsedRef, err := name.ParseReference(imageRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", imageRef, err)
|
||||
// WithLocalKeychain provides initialize keychain with the default local keychain.
|
||||
func WithLocalKeychain() Option {
|
||||
return func(c *client) error {
|
||||
c.pullSecretRefresher = nil
|
||||
c.keychain = authn.DefaultKeychain
|
||||
return nil
|
||||
}
|
||||
|
||||
desc, err := gcrremote.Get(parsedRef, gcrremote.WithAuthFromKeychain(c.keychain))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch image reference: %s, error: %v", imageRef, err)
|
||||
}
|
||||
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
// RefreshKeychainPullSecrets loads fresh data from pull secrets and updates Keychain.
|
||||
// If pull secrets are empty - returns.
|
||||
func (c *client) RefreshKeychainPullSecrets() error {
|
||||
func (c *client) RefreshKeychainPullSecrets(ctx context.Context) error {
|
||||
if c.pullSecretRefresher == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.pullSecretRefresher(c)
|
||||
}
|
||||
|
||||
// generateKeychainForPullSecrets generates keychain by fetching secrets data from imagePullSecrets.
|
||||
func generateKeychainForPullSecrets(
|
||||
client kubernetes.Interface,
|
||||
namespace, serviceAccount string,
|
||||
imagePullSecrets []string,
|
||||
) (authn.Keychain, error) {
|
||||
kcOpts := kauth.Options{
|
||||
Namespace: namespace,
|
||||
ServiceAccountName: serviceAccount,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
}
|
||||
|
||||
kc, err := kauth.New(context.Background(), client, kcOpts) // uses k8s client to fetch secrets data
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to initialize registry keychain")
|
||||
}
|
||||
return kc, err
|
||||
return c.pullSecretRefresher(ctx, c)
|
||||
}
|
||||
|
||||
// BuildRemoteOption builds remote.Option based on client.
|
||||
func BuildRemoteOption(c Client) remote.Option {
|
||||
func (c *client) BuildRemoteOption() remote.Option {
|
||||
return remote.WithRemoteOptions(
|
||||
gcrremote.WithAuthFromKeychain(c.Keychain()),
|
||||
gcrremote.WithTransport(c.Transport()),
|
||||
gcrremote.WithAuthFromKeychain(c.keychain),
|
||||
gcrremote.WithTransport(c.transport),
|
||||
)
|
||||
}
|
||||
|
||||
// FetchImageDescriptor fetches Descriptor from registry with given imageRef
|
||||
// and provides access to metadata about remote artifact.
|
||||
func (c *client) FetchImageDescriptor(ctx context.Context, imageRef string) (*gcrremote.Descriptor, error) {
|
||||
parsedRef, err := name.ParseReference(imageRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse image reference: %s, error: %v", imageRef, err)
|
||||
}
|
||||
desc, err := gcrremote.Get(parsedRef, gcrremote.WithAuthFromKeychain(c.keychain), gcrremote.WithContext(ctx))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch image reference: %s, error: %v", imageRef, err)
|
||||
}
|
||||
return desc, nil
|
||||
}
|
||||
|
||||
func (c *client) getKeychain() authn.Keychain {
|
||||
return c.keychain
|
||||
}
|
||||
|
||||
func (c *client) getTransport() http.RoundTripper {
|
||||
return c.transport
|
||||
}
|
||||
|
|
|
@ -16,22 +16,22 @@ func TestInitClientWithEmptyOptions(t *testing.T) {
|
|||
expClient := &client{
|
||||
transport: remote.DefaultTransport.(*http.Transport),
|
||||
}
|
||||
c, err := InitClient()
|
||||
c, err := New()
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, expClient.transport == c.Transport())
|
||||
assert.Assert(t, c.Keychain() != nil)
|
||||
assert.Assert(t, expClient.transport == c.getTransport())
|
||||
assert.Assert(t, c.getKeychain() != nil)
|
||||
}
|
||||
|
||||
func TestInitClientWithInsecureRegistryOption(t *testing.T) {
|
||||
expClient := &client{
|
||||
transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
|
||||
}
|
||||
c, err := InitClient(WithAllowInsecureRegistry())
|
||||
c, err := New(WithAllowInsecureRegistry())
|
||||
|
||||
expInsecureSkipVerify := expClient.transport.TLSClientConfig.InsecureSkipVerify
|
||||
gotInsecureSkipVerify := c.Transport().TLSClientConfig.InsecureSkipVerify
|
||||
gotInsecureSkipVerify := c.getTransport().(*http.Transport).TLSClientConfig.InsecureSkipVerify
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, expInsecureSkipVerify == gotInsecureSkipVerify)
|
||||
assert.Assert(t, c.Keychain() != nil)
|
||||
assert.Assert(t, c.getKeychain() != nil)
|
||||
}
|
||||
|
|
24
pkg/registryclient/utils.go
Normal file
24
pkg/registryclient/utils.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package registryclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
kauth "github.com/google/go-containerregistry/pkg/authn/kubernetes"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// generateKeychainForPullSecrets generates keychain by fetching secrets data from imagePullSecrets.
|
||||
func generateKeychainForPullSecrets(ctx context.Context, client kubernetes.Interface, namespace, serviceAccount string, imagePullSecrets ...string) (authn.Keychain, error) {
|
||||
kcOpts := kauth.Options{
|
||||
Namespace: namespace,
|
||||
ServiceAccountName: serviceAccount,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
}
|
||||
kc, err := kauth.New(ctx, client, kcOpts) // uses k8s client to fetch secrets data
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to initialize registry keychain")
|
||||
}
|
||||
return kc, err
|
||||
}
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
@ -145,7 +146,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
|
||||
policyContext := engine.NewPolicyContext().WithPolicy(policy).WithNewResource(*resource)
|
||||
|
||||
er := engine.Mutate(policyContext)
|
||||
er := engine.Mutate(registryclient.NewOrDie(), policyContext)
|
||||
t.Log("---Mutation---")
|
||||
validateResource(t, er.PatchedResource, tc.Expected.Mutation.PatchedResource)
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Mutation.PolicyResponse)
|
||||
|
@ -157,7 +158,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
|
||||
policyContext = policyContext.WithNewResource(*resource)
|
||||
|
||||
er = engine.Validate(policyContext)
|
||||
er = engine.Validate(registryclient.NewOrDie(), policyContext)
|
||||
t.Log("---Validation---")
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Validation.PolicyResponse)
|
||||
|
||||
|
@ -173,7 +174,7 @@ func runTestCase(t *testing.T, tc TestCase) bool {
|
|||
} else {
|
||||
policyContext := policyContext.WithClient(client)
|
||||
|
||||
er = engine.ApplyBackgroundChecks(policyContext)
|
||||
er = engine.ApplyBackgroundChecks(registryclient.NewOrDie(), policyContext)
|
||||
t.Log(("---Generation---"))
|
||||
validateResponse(t, er.PolicyResponse, tc.Expected.Generation.PolicyResponse)
|
||||
// Expected generate resource will be in same namespaces as resource
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
webhookgenerate "github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
|
||||
webhookutils "github.com/kyverno/kyverno/pkg/webhooks/utils"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
|
@ -45,6 +46,7 @@ func NewGenerationHandler(
|
|||
log logr.Logger,
|
||||
client dclient.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
rclient registryclient.Client,
|
||||
nsLister corev1listers.NamespaceLister,
|
||||
urLister kyvernov1beta1listers.UpdateRequestNamespaceLister,
|
||||
urGenerator webhookgenerate.Generator,
|
||||
|
@ -55,6 +57,7 @@ func NewGenerationHandler(
|
|||
log: log,
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
rclient: rclient,
|
||||
nsLister: nsLister,
|
||||
urLister: urLister,
|
||||
urGenerator: urGenerator,
|
||||
|
@ -67,6 +70,7 @@ type generationHandler struct {
|
|||
log logr.Logger
|
||||
client dclient.Interface
|
||||
kyvernoClient versioned.Interface
|
||||
rclient registryclient.Client
|
||||
nsLister corev1listers.NamespaceLister
|
||||
urLister kyvernov1beta1listers.UpdateRequestNamespaceLister
|
||||
urGenerator webhookgenerate.Generator
|
||||
|
@ -92,7 +96,7 @@ func (h *generationHandler) Handle(
|
|||
if request.Kind.Kind != "Namespace" && request.Namespace != "" {
|
||||
policyContext = policyContext.WithNamespaceLabels(common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log))
|
||||
}
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
engineResponse := engine.ApplyBackgroundChecks(h.rclient, policyContext)
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if rule.Status != response.RuleStatusPass {
|
||||
h.deleteGR(engineResponse)
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
"github.com/kyverno/kyverno/pkg/policycache"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks"
|
||||
|
@ -38,6 +39,7 @@ type handlers struct {
|
|||
// clients
|
||||
client dclient.Interface
|
||||
kyvernoClient versioned.Interface
|
||||
rclient registryclient.Client
|
||||
|
||||
// config
|
||||
configuration config.Configuration
|
||||
|
@ -64,6 +66,7 @@ type handlers struct {
|
|||
func NewHandlers(
|
||||
client dclient.Interface,
|
||||
kyvernoClient versioned.Interface,
|
||||
rclient registryclient.Client,
|
||||
configuration config.Configuration,
|
||||
metricsConfig metrics.MetricsConfigManager,
|
||||
pCache policycache.Cache,
|
||||
|
@ -80,6 +83,7 @@ func NewHandlers(
|
|||
return &handlers{
|
||||
client: client,
|
||||
kyvernoClient: kyvernoClient,
|
||||
rclient: rclient,
|
||||
configuration: configuration,
|
||||
metricsConfig: metricsConfig,
|
||||
pCache: pCache,
|
||||
|
@ -113,7 +117,7 @@ func (h *handlers) Validate(ctx context.Context, logger logr.Logger, request *ad
|
|||
}
|
||||
if len(generatePolicies) == 0 && request.Operation == admissionv1.Update {
|
||||
// handle generate source resource updates
|
||||
gh := generation.NewGenerationHandler(logger, h.client, h.kyvernoClient, h.nsLister, h.urLister, h.urGenerator, h.urUpdater, h.eventGen)
|
||||
gh := generation.NewGenerationHandler(logger, h.client, h.kyvernoClient, h.rclient, h.nsLister, h.urLister, h.urGenerator, h.urUpdater, h.eventGen)
|
||||
go gh.HandleUpdatesForGenerateRules(request, []kyvernov1.PolicyInterface{})
|
||||
}
|
||||
|
||||
|
@ -129,7 +133,7 @@ func (h *handlers) Validate(ctx context.Context, logger logr.Logger, request *ad
|
|||
namespaceLabels = common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, logger)
|
||||
}
|
||||
|
||||
vh := validation.NewValidationHandler(logger, h.kyvernoClient, h.pCache, h.pcBuilder, h.eventGen, h.admissionReports)
|
||||
vh := validation.NewValidationHandler(logger, h.kyvernoClient, h.rclient, h.pCache, h.pcBuilder, h.eventGen, h.admissionReports)
|
||||
|
||||
ok, msg, warnings := vh.HandleValidation(h.metricsConfig, request, policies, policyContext, namespaceLabels, startTime)
|
||||
if !ok {
|
||||
|
@ -163,7 +167,7 @@ func (h *handlers) Mutate(ctx context.Context, logger logr.Logger, request *admi
|
|||
if err := enginectx.MutateResourceWithImageInfo(request.Object.Raw, policyContext.JSONContext()); err != nil {
|
||||
logger.Error(err, "failed to patch images info to resource, policies that mutate images may be impacted")
|
||||
}
|
||||
mh := mutation.NewMutationHandler(logger, h.eventGen, h.openApiManager, h.nsLister)
|
||||
mh := mutation.NewMutationHandler(logger, h.rclient, h.eventGen, h.openApiManager, h.nsLister)
|
||||
mutatePatches, mutateWarnings, err := mh.HandleMutation(h.metricsConfig, request, mutatePolicies, policyContext, startTime)
|
||||
if err != nil {
|
||||
logger.Error(err, "mutation failed")
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||
|
@ -76,7 +77,7 @@ func (h *imageVerificationHandler) handleVerifyImages(logger logr.Logger, reques
|
|||
verifiedImageData := &engine.ImageVerificationMetadata{}
|
||||
for _, p := range policies {
|
||||
policyContext := policyContext.WithPolicy(p)
|
||||
resp, ivm := engine.VerifyAndPatchImages(policyContext)
|
||||
resp, ivm := engine.VerifyAndPatchImages(registryclient.NewOrDie(), policyContext)
|
||||
|
||||
engineResponses = append(engineResponses, resp)
|
||||
patches = append(patches, resp.GetPatches()...)
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/openapi"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
"github.com/kyverno/kyverno/pkg/utils"
|
||||
engineutils "github.com/kyverno/kyverno/pkg/utils/engine"
|
||||
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
|
||||
|
@ -41,12 +42,14 @@ type MutationHandler interface {
|
|||
|
||||
func NewMutationHandler(
|
||||
log logr.Logger,
|
||||
rclient registryclient.Client,
|
||||
eventGen event.Interface,
|
||||
openApiManager openapi.ValidateInterface,
|
||||
nsLister corev1listers.NamespaceLister,
|
||||
) MutationHandler {
|
||||
return &mutationHandler{
|
||||
log: log,
|
||||
rclient: rclient,
|
||||
eventGen: eventGen,
|
||||
openApiManager: openApiManager,
|
||||
nsLister: nsLister,
|
||||
|
@ -55,6 +58,7 @@ func NewMutationHandler(
|
|||
|
||||
type mutationHandler struct {
|
||||
log logr.Logger
|
||||
rclient registryclient.Client
|
||||
eventGen event.Interface
|
||||
openApiManager openapi.ValidateInterface
|
||||
nsLister corev1listers.NamespaceLister
|
||||
|
@ -144,7 +148,7 @@ func (h *mutationHandler) applyMutation(request *admissionv1.AdmissionRequest, p
|
|||
policyContext = policyContext.WithNamespaceLabels(common.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, h.log))
|
||||
}
|
||||
|
||||
engineResponse := engine.Mutate(policyContext)
|
||||
engineResponse := engine.Mutate(h.rclient, policyContext)
|
||||
policyPatches := engineResponse.GetPatches()
|
||||
|
||||
if !engineResponse.IsSuccessful() {
|
||||
|
|
|
@ -18,7 +18,7 @@ import (
|
|||
|
||||
// createUpdateRequests applies generate and mutateExisting policies, and creates update requests for background reconcile
|
||||
func (h *handlers) createUpdateRequests(logger logr.Logger, request *admissionv1.AdmissionRequest, policyContext *engine.PolicyContext, generatePolicies, mutatePolicies []kyvernov1.PolicyInterface, ts time.Time) {
|
||||
gh := generation.NewGenerationHandler(logger, h.client, h.kyvernoClient, h.nsLister, h.urLister, h.urGenerator, h.urUpdater, h.eventGen)
|
||||
gh := generation.NewGenerationHandler(logger, h.client, h.kyvernoClient, h.rclient, h.nsLister, h.urLister, h.urGenerator, h.urUpdater, h.eventGen)
|
||||
go h.handleMutateExisting(logger, request, mutatePolicies, policyContext, ts)
|
||||
go gh.Handle(h.metricsConfig, request, generatePolicies, policyContext, ts)
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func (h *handlers) handleMutateExisting(logger logr.Logger, request *admissionv1
|
|||
|
||||
var rules []response.RuleResponse
|
||||
policyContext := policyContext.WithPolicy(policy)
|
||||
engineResponse := engine.ApplyBackgroundChecks(policyContext)
|
||||
engineResponse := engine.ApplyBackgroundChecks(h.rclient, policyContext)
|
||||
|
||||
for _, rule := range engineResponse.PolicyResponse.Rules {
|
||||
if rule.Status == response.RuleStatusPass {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/kyverno/kyverno/pkg/event"
|
||||
"github.com/kyverno/kyverno/pkg/metrics"
|
||||
"github.com/kyverno/kyverno/pkg/policycache"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
|
||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||
|
@ -33,6 +34,7 @@ type ValidationHandler interface {
|
|||
func NewValidationHandler(
|
||||
log logr.Logger,
|
||||
kyvernoClient versioned.Interface,
|
||||
rclient registryclient.Client,
|
||||
pCache policycache.Cache,
|
||||
pcBuilder webhookutils.PolicyContextBuilder,
|
||||
eventGen event.Interface,
|
||||
|
@ -41,6 +43,7 @@ func NewValidationHandler(
|
|||
return &validationHandler{
|
||||
log: log,
|
||||
kyvernoClient: kyvernoClient,
|
||||
rclient: rclient,
|
||||
pCache: pCache,
|
||||
pcBuilder: pcBuilder,
|
||||
eventGen: eventGen,
|
||||
|
@ -51,6 +54,7 @@ func NewValidationHandler(
|
|||
type validationHandler struct {
|
||||
log logr.Logger
|
||||
kyvernoClient versioned.Interface
|
||||
rclient registryclient.Client
|
||||
pCache policycache.Cache
|
||||
pcBuilder webhookutils.PolicyContextBuilder
|
||||
eventGen event.Interface
|
||||
|
@ -95,7 +99,7 @@ func (v *validationHandler) HandleValidation(
|
|||
failurePolicy = kyvernov1.Fail
|
||||
}
|
||||
|
||||
engineResponse := engine.Validate(policyContext)
|
||||
engineResponse := engine.Validate(v.rclient, policyContext)
|
||||
if engineResponse.IsNil() {
|
||||
// we get an empty response if old and new resources created the same response
|
||||
// allow updates if resource update doesnt change the policy evaluation
|
||||
|
@ -142,7 +146,7 @@ func (v *validationHandler) buildAuditResponses(resource unstructured.Unstructur
|
|||
var responses []*response.EngineResponse
|
||||
for _, policy := range policies {
|
||||
policyContext := policyContext.WithPolicy(policy).WithNamespaceLabels(namespaceLabels)
|
||||
responses = append(responses, engine.Validate(policyContext))
|
||||
responses = append(responses, engine.Validate(v.rclient, policyContext))
|
||||
}
|
||||
return responses, nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
log "github.com/kyverno/kyverno/pkg/logging"
|
||||
"github.com/kyverno/kyverno/pkg/registryclient"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine"
|
||||
|
@ -531,6 +532,7 @@ func TestValidate_failure_action_overrides(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
er := engine.Validate(
|
||||
registryclient.NewOrDie(),
|
||||
engine.NewPolicyContext().WithPolicy(&policy).WithNewResource(*resourceUnstructured),
|
||||
)
|
||||
if tc.blocked && tc.messages != nil {
|
||||
|
@ -592,7 +594,7 @@ func Test_RuleSelector(t *testing.T) {
|
|||
|
||||
ctx := engine.NewPolicyContext().WithPolicy(&policy).WithNewResource(*resourceUnstructured)
|
||||
|
||||
resp := engine.Validate(ctx)
|
||||
resp := engine.Validate(registryclient.NewOrDie(), ctx)
|
||||
assert.Assert(t, resp.PolicyResponse.RulesAppliedCount == 2)
|
||||
assert.Assert(t, resp.PolicyResponse.RulesErrorCount == 0)
|
||||
|
||||
|
@ -603,7 +605,7 @@ func Test_RuleSelector(t *testing.T) {
|
|||
applyOne := kyvernov1.ApplyOne
|
||||
policy.Spec.ApplyRules = &applyOne
|
||||
|
||||
resp = engine.Validate(ctx)
|
||||
resp = engine.Validate(registryclient.NewOrDie(), ctx)
|
||||
assert.Assert(t, resp.PolicyResponse.RulesAppliedCount == 1)
|
||||
assert.Assert(t, resp.PolicyResponse.RulesErrorCount == 0)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue