1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

feat: add basic structure for image verify cache (#7890)

* feat: add interface for image verify cache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: add basic client for cache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: add ttl to client

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: add flags and flag setup

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: added a default image verify cache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: add propogation of cache to image verifier

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: add useCache to image verification types

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* bug: add ivcache to image verifier

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: add logger to cache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* typo: DisabledImageVerfiyCache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* typo: DisabledImageVerfiyCache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* Update cmd/internal/flag.go

Signed-off-by: shuting <shutting06@gmail.com>

* feat: add use cache to v2beta1 crd

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* bug: change public attribute TTL to private

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* fix: replace nil in test with disabled cache

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* fix: convert ttl time to time.Duration

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: update opts to use time.Duration

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat:add policy version and remove delete functions

by adding policy version, old entries will automatically become outdated and we will not have to remove them manually

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* feat: remove clear and update get and set to take interface as input

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

* style: fix lint issue

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>

---------

Signed-off-by: Vishal Choudhary <sendtovishalchoudhary@gmail.com>
Signed-off-by: shuting <shutting06@gmail.com>
Co-authored-by: shuting <shutting06@gmail.com>
Co-authored-by: shuting <shuting@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Vishal Choudhary 2023-08-07 01:24:52 +05:30 committed by GitHub
parent bc95283b04
commit b385693509
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 411 additions and 30 deletions

View file

@ -109,6 +109,11 @@ type ImageVerification struct {
// ImageRegistryCredentials provides credentials that will be used for authentication with registry
// +kubebuilder:validation:Optional
ImageRegistryCredentials *ImageRegistryCredentials `json:"imageRegistryCredentials,omitempty" yaml:"imageRegistryCredentials,omitempty"`
// UseCache enables caching of image verify responses for this rule
// +kubebuilder:default=true
// +kubebuilder:validation:Optional
UseCache bool `json:"useCache" yaml:"useCache"`
}
type AttestorSet struct {

View file

@ -54,6 +54,11 @@ type ImageVerification struct {
// ImageRegistryCredentials provides credentials that will be used for authentication with registry
// +kubebuilder:validation:Optional
ImageRegistryCredentials *kyvernov1.ImageRegistryCredentials `json:"imageRegistryCredentials,omitempty" yaml:"imageRegistryCredentials,omitempty"`
// UseCache enables caching of image verify responses for this rule
// +kubebuilder:default=true
// +kubebuilder:validation:Optional
UseCache bool `json:"useCache" yaml:"useCache"`
}
// Validate implements programmatic validation

View file

@ -7748,6 +7748,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -11851,6 +11856,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -15596,6 +15606,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -19699,6 +19714,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -23755,6 +23775,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -27859,6 +27884,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -31605,6 +31635,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -35708,6 +35743,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have

View file

@ -157,6 +157,7 @@ func main() {
setup.Jp,
setup.KyvernoDynamicClient,
setup.RegistryClient,
setup.ImageVerifyCacheClient,
setup.KubeClient,
setup.KyvernoClient,
setup.RegistrySecretLister,

View file

@ -16,6 +16,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/metrics"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
"github.com/kyverno/kyverno/pkg/utils/match"
@ -130,6 +131,7 @@ func (h *handlers) executePolicy(
h.jp,
h.client,
nil,
imageverifycache.DisabledImageVerifyCache(),
spec.Context,
enginectx,
); err != nil {

View file

@ -27,6 +27,7 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/variables/regex"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/logging"
datautils "github.com/kyverno/kyverno/pkg/utils/data"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
@ -790,6 +791,7 @@ func initializeMockController(objects []runtime.Object) (*generate.GenerateContr
jmespath.New(cfg),
adapters.Client(client),
nil,
imageverifycache.DisabledImageVerifyCache(),
store.ContextLoaderFactory(nil),
nil,
"",

View file

@ -15,6 +15,7 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/registryclient"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -119,6 +120,7 @@ OuterLoop:
jmespath.New(cfg),
adapters.Client(c.Client),
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
store.ContextLoaderFactory(nil),
nil,
"",

View file

@ -8,6 +8,7 @@ import (
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
)
func ContextLoaderFactory(cmResolver engineapi.ConfigmapResolver) engineapi.ContextLoaderFactory {
@ -48,6 +49,7 @@ func (w wrapper) Load(
jp jmespath.Interface,
client engineapi.RawClient,
rclientFactory engineapi.RegistryClientFactory,
ivCache imageverifycache.Client,
contextEntries []kyvernov1.ContextEntry,
jsonContext enginecontext.Interface,
) error {
@ -57,5 +59,5 @@ func (w wrapper) Load(
if !GetRegistryAccess() {
rclientFactory = nil
}
return w.inner.Load(ctx, jp, client, rclientFactory, contextEntries, jsonContext)
return w.inner.Load(ctx, jp, client, rclientFactory, ivCache, contextEntries, jsonContext)
}

View file

@ -14,6 +14,7 @@ type Configuration interface {
UsesDeferredLoading() bool
UsesCosign() bool
UsesRegistryClient() bool
UsesImageVerifyCache() bool
UsesLeaderElection() bool
UsesKyvernoClient() bool
UsesDynamicClient() bool
@ -87,6 +88,12 @@ func WithRegistryClient() ConfigurationOption {
}
}
func WithImageVerifyCache() ConfigurationOption {
return func(c *configuration) {
c.usesImageVerifyCache = true
}
}
func WithLeaderElection() ConfigurationOption {
return func(c *configuration) {
c.usesLeaderElection = true
@ -141,6 +148,7 @@ type configuration struct {
usesDeferredLoading bool
usesCosign bool
usesRegistryClient bool
usesImageVerifyCache bool
usesLeaderElection bool
usesKyvernoClient bool
usesDynamicClient bool
@ -186,6 +194,10 @@ func (c *configuration) UsesRegistryClient() bool {
return c.usesRegistryClient
}
func (c *configuration) UsesImageVerifyCache() bool {
return c.usesImageVerifyCache
}
func (c *configuration) UsesLeaderElection() bool {
return c.usesLeaderElection
}

View file

@ -16,6 +16,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/context/resolvers"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/registryclient"
"k8s.io/client-go/kubernetes"
corev1listers "k8s.io/client-go/listers/core/v1"
@ -29,6 +30,7 @@ func NewEngine(
jp jmespath.Interface,
client dclient.Interface,
rclient registryclient.Client,
ivCache imageverifycache.Client,
kubeClient kubernetes.Interface,
kyvernoClient versioned.Interface,
secretLister corev1listers.SecretNamespaceLister,
@ -43,6 +45,7 @@ func NewEngine(
jp,
adapters.Client(client),
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), secretLister),
ivCache,
factories.DefaultContextLoaderFactory(configMapResolver),
exceptionsSelector,
imageSignatureRepository,

View file

@ -44,6 +44,10 @@ var (
registryCredentialHelpers string
// leader election
leaderElectionRetryPeriod time.Duration
// image verify cache
imageVerifyCacheEnabled bool
imageVerifyCacheTTLDuration int64
imageVerifyCacheMaxSize int64
)
func initLoggingFlags() {
@ -102,6 +106,12 @@ func initRegistryClientFlags() {
flag.StringVar(&registryCredentialHelpers, "registryCredentialHelpers", "", "Credential helpers to enable (default,google,amazon,azure,github). No helpers are added when this flag is empty.")
}
func initImageVerifyCacheFlags() {
flag.BoolVar(&imageVerifyCacheEnabled, "imageVerifyCacheEnabled", true, "Whether to use a TTL cache for storing verified images.")
flag.Int64Var(&imageVerifyCacheMaxSize, "imageVerifyCacheMaxSize", 0, "Max size limit for the TTL cache, 0 means no size limit.")
flag.Int64Var(&imageVerifyCacheTTLDuration, "imageVerifyCacheTTLDuration", 0, "Max TTL value for a cache, 0 means no TTL.")
}
func initLeaderElectionFlags() {
flag.DurationVar(&leaderElectionRetryPeriod, "leaderElectionRetryPeriod", leaderelection.DefaultRetryPeriod, "Configure leader election retry period.")
}
@ -177,6 +187,10 @@ func initFlags(config Configuration, opts ...Option) {
if config.UsesRegistryClient() {
initRegistryClientFlags()
}
// image verify cache
if config.UsesImageVerifyCache() {
initImageVerifyCacheFlags()
}
// leader election
if config.UsesLeaderElection() {
initLeaderElectionFlags()

View file

@ -0,0 +1,23 @@
package internal
import (
"context"
"time"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/imageverifycache"
)
func setupImageVerifyCache(ctx context.Context, logger logr.Logger) imageverifycache.Client {
logger = logger.WithName("image-verify-cache").WithValues("enabled", imageVerifyCacheEnabled, "maxsize", imageVerifyCacheMaxSize, "ttl", imageVerifyCacheTTLDuration)
logger.Info("setup image verify cache...")
opts := []imageverifycache.Option{
imageverifycache.WithLogger(logger),
imageverifycache.WithCacheEnableFlag(imageVerifyCacheEnabled),
imageverifycache.WithMaxSize(imageVerifyCacheMaxSize),
imageverifycache.WithTTLDuration(time.Duration(imageVerifyCacheTTLDuration)),
}
imageVerifyCache, err := imageverifycache.New(opts...)
checkError(logger, err, "failed to create image verify cache client")
return imageVerifyCache
}

View file

@ -13,6 +13,7 @@ import (
metadataclient "github.com/kyverno/kyverno/pkg/clients/metadata"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/registryclient"
corev1listers "k8s.io/client-go/listers/core/v1"
@ -30,20 +31,21 @@ func shutdown(logger logr.Logger, sdowns ...context.CancelFunc) context.CancelFu
}
type SetupResult struct {
Logger logr.Logger
Configuration config.Configuration
MetricsConfiguration config.MetricsConfiguration
MetricsManager metrics.MetricsConfigManager
Jp jmespath.Interface
KubeClient kubeclient.UpstreamInterface
LeaderElectionClient kubeclient.UpstreamInterface
RegistryClient registryclient.Client
RegistrySecretLister corev1listers.SecretNamespaceLister
KyvernoClient kyvernoclient.UpstreamInterface
DynamicClient dynamicclient.UpstreamInterface
ApiServerClient apiserverclient.UpstreamInterface
MetadataClient metadataclient.UpstreamInterface
KyvernoDynamicClient dclient.Interface
Logger logr.Logger
Configuration config.Configuration
MetricsConfiguration config.MetricsConfiguration
MetricsManager metrics.MetricsConfigManager
Jp jmespath.Interface
KubeClient kubeclient.UpstreamInterface
LeaderElectionClient kubeclient.UpstreamInterface
RegistryClient registryclient.Client
ImageVerifyCacheClient imageverifycache.Client
RegistrySecretLister corev1listers.SecretNamespaceLister
KyvernoClient kyvernoclient.UpstreamInterface
DynamicClient dynamicclient.UpstreamInterface
ApiServerClient apiserverclient.UpstreamInterface
MetadataClient metadataclient.UpstreamInterface
KyvernoDynamicClient dclient.Interface
}
func Setup(config Configuration, name string, skipResourceFilters bool) (context.Context, SetupResult, context.CancelFunc) {
@ -66,6 +68,10 @@ func Setup(config Configuration, name string, skipResourceFilters bool) (context
if config.UsesRegistryClient() {
registryClient, registrySecretLister = setupRegistryClient(ctx, logger, client)
}
var imageVerifyCache imageverifycache.Client
if config.UsesImageVerifyCache() {
imageVerifyCache = setupImageVerifyCache(ctx, logger)
}
var leaderElectionClient kubeclient.UpstreamInterface
if config.UsesLeaderElection() {
leaderElectionClient = createKubernetesClient(logger, kubeclient.WithMetrics(metricsManager, metrics.KubeClient), kubeclient.WithTracing())
@ -92,20 +98,21 @@ func Setup(config Configuration, name string, skipResourceFilters bool) (context
}
return ctx,
SetupResult{
Logger: logger,
Configuration: configuration,
MetricsConfiguration: metricsConfiguration,
MetricsManager: metricsManager,
Jp: jmespath.New(configuration),
KubeClient: client,
LeaderElectionClient: leaderElectionClient,
RegistryClient: registryClient,
RegistrySecretLister: registrySecretLister,
KyvernoClient: kyvernoClient,
DynamicClient: dynamicClient,
ApiServerClient: apiServerClient,
MetadataClient: metadataClient,
KyvernoDynamicClient: dClient,
Logger: logger,
Configuration: configuration,
MetricsConfiguration: metricsConfiguration,
MetricsManager: metricsManager,
Jp: jmespath.New(configuration),
KubeClient: client,
LeaderElectionClient: leaderElectionClient,
RegistryClient: registryClient,
ImageVerifyCacheClient: imageVerifyCache,
RegistrySecretLister: registrySecretLister,
KyvernoClient: kyvernoClient,
DynamicClient: dynamicClient,
ApiServerClient: apiServerClient,
MetadataClient: metadataClient,
KyvernoDynamicClient: dClient,
},
shutdown(logger.WithName("shutdown"), sdownMaxProcs, sdownMetrics, sdownTracing, sdownSignals)
}

View file

@ -216,6 +216,7 @@ func main() {
internal.WithDeferredLoading(),
internal.WithCosign(),
internal.WithRegistryClient(),
internal.WithImageVerifyCache(),
internal.WithLeaderElection(),
internal.WithKyvernoClient(),
internal.WithDynamicClient(),
@ -309,6 +310,7 @@ func main() {
setup.Jp,
setup.KyvernoDynamicClient,
setup.RegistryClient,
setup.ImageVerifyCacheClient,
setup.KubeClient,
setup.KyvernoClient,
setup.RegistrySecretLister,

View file

@ -198,6 +198,7 @@ func main() {
internal.WithDeferredLoading(),
internal.WithCosign(),
internal.WithRegistryClient(),
internal.WithImageVerifyCache(),
internal.WithLeaderElection(),
internal.WithKyvernoClient(),
internal.WithDynamicClient(),
@ -241,6 +242,7 @@ func main() {
setup.Jp,
setup.KyvernoDynamicClient,
setup.RegistryClient,
setup.ImageVerifyCacheClient,
setup.KubeClient,
setup.KyvernoClient,
setup.RegistrySecretLister,

View file

@ -3931,6 +3931,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -8034,6 +8039,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -11779,6 +11789,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -15882,6 +15897,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have

View file

@ -3932,6 +3932,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -8036,6 +8041,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -11782,6 +11792,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -15885,6 +15900,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have

View file

@ -7951,6 +7951,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -12054,6 +12059,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -15799,6 +15809,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -19902,6 +19917,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -23958,6 +23978,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -28062,6 +28087,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have
@ -31808,6 +31838,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have a
@ -35911,6 +35946,11 @@ spec:
- Cosign
- Notary
type: string
useCache:
default: true
description: UseCache enables caching of image verify
responses for this rule
type: boolean
verifyDigest:
default: true
description: VerifyDigest validates that images have

View file

@ -2310,6 +2310,17 @@ ImageRegistryCredentials
<p>ImageRegistryCredentials provides credentials that will be used for authentication with registry</p>
</td>
</tr>
<tr>
<td>
<code>useCache</code><br/>
<em>
bool
</em>
</td>
<td>
<p>UseCache enables caching of image verify responses for this rule</p>
</td>
</tr>
</tbody>
</table>
<hr />
@ -6718,6 +6729,17 @@ ImageRegistryCredentials
<p>ImageRegistryCredentials provides credentials that will be used for authentication with registry</p>
</td>
</tr>
<tr>
<td>
<code>useCache</code><br/>
<em>
bool
</em>
</td>
<td>
<p>UseCache enables caching of image verify responses for this rule</p>
</td>
</tr>
</tbody>
</table>
<hr />

View file

@ -41,6 +41,7 @@ type ImageVerificationApplyConfiguration struct {
VerifyDigest *bool `json:"verifyDigest,omitempty"`
Required *bool `json:"required,omitempty"`
ImageRegistryCredentials *ImageRegistryCredentialsApplyConfiguration `json:"imageRegistryCredentials,omitempty"`
UseCache *bool `json:"useCache,omitempty"`
}
// ImageVerificationApplyConfiguration constructs an declarative configuration of the ImageVerification type for use with
@ -200,3 +201,11 @@ func (b *ImageVerificationApplyConfiguration) WithImageRegistryCredentials(value
b.ImageRegistryCredentials = value
return b
}
// WithUseCache sets the UseCache field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UseCache field is set to the value of the last call.
func (b *ImageVerificationApplyConfiguration) WithUseCache(value bool) *ImageVerificationApplyConfiguration {
b.UseCache = &value
return b
}

View file

@ -35,6 +35,7 @@ type ImageVerificationApplyConfiguration struct {
VerifyDigest *bool `json:"verifyDigest,omitempty"`
Required *bool `json:"required,omitempty"`
ImageRegistryCredentials *kyvernov1.ImageRegistryCredentialsApplyConfiguration `json:"imageRegistryCredentials,omitempty"`
UseCache *bool `json:"useCache,omitempty"`
}
// ImageVerificationApplyConfiguration constructs an declarative configuration of the ImageVerification type for use with
@ -126,3 +127,11 @@ func (b *ImageVerificationApplyConfiguration) WithImageRegistryCredentials(value
b.ImageRegistryCredentials = value
return b
}
// WithUseCache sets the UseCache field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UseCache field is set to the value of the last call.
func (b *ImageVerificationApplyConfiguration) WithUseCache(value bool) *ImageVerificationApplyConfiguration {
b.UseCache = &value
return b
}

View file

@ -6,6 +6,7 @@ import (
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
)
type RegistryClientFactory interface {
@ -24,6 +25,7 @@ type ContextLoader interface {
jp jmespath.Interface,
client RawClient,
rclientFactory RegistryClientFactory,
ivCache imageverifycache.Client,
contextEntries []kyvernov1.ContextEntry,
jsonContext enginecontext.Interface,
) error

View file

@ -15,6 +15,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/internal"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/tracing"
@ -31,6 +32,7 @@ type engine struct {
jp jmespath.Interface
client engineapi.Client
rclientFactory engineapi.RegistryClientFactory
ivCache imageverifycache.Client
contextLoader engineapi.ContextLoaderFactory
exceptionSelector engineapi.PolicyExceptionSelector
imageSignatureRepository string
@ -47,6 +49,7 @@ func NewEngine(
jp jmespath.Interface,
client engineapi.Client,
rclientFactory engineapi.RegistryClientFactory,
ivCache imageverifycache.Client,
contextLoader engineapi.ContextLoaderFactory,
exceptionSelector engineapi.PolicyExceptionSelector,
imageSignatureRepository string,
@ -72,6 +75,7 @@ func NewEngine(
jp: jp,
client: client,
rclientFactory: rclientFactory,
ivCache: ivCache,
contextLoader: contextLoader,
exceptionSelector: exceptionSelector,
imageSignatureRepository: imageSignatureRepository,
@ -176,6 +180,7 @@ func (e *engine) ContextLoader(
e.jp,
e.client,
e.rclientFactory,
e.ivCache,
contextEntries,
jsonContext,
)

View file

@ -10,6 +10,7 @@ import (
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/context/loaders"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/toggle"
)
@ -46,6 +47,7 @@ func (l *contextLoader) Load(
jp jmespath.Interface,
client engineapi.RawClient,
rclientFactory engineapi.RegistryClientFactory,
ivCache imageverifycache.Client,
contextEntries []kyvernov1.ContextEntry,
jsonContext enginecontext.Interface,
) error {

View file

@ -14,6 +14,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/mutate/patch"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/imageverifycache"
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
jsonutils "github.com/kyverno/kyverno/pkg/utils/json"
"gomodules.xyz/jsonpatch/v2"
@ -23,6 +24,7 @@ import (
type mutateImageHandler struct {
configuration config.Configuration
rclientFactory engineapi.RegistryClientFactory
ivCache imageverifycache.Client
ivm *engineapi.ImageVerificationMetadata
images []apiutils.ImageInfo
imageSignatureRepository string
@ -34,6 +36,7 @@ func NewMutateImageHandler(
rule kyvernov1.Rule,
configuration config.Configuration,
rclientFactory engineapi.RegistryClientFactory,
ivCache imageverifycache.Client,
ivm *engineapi.ImageVerificationMetadata,
imageSignatureRepository string,
) (handlers.Handler, error) {
@ -80,7 +83,7 @@ func (h mutateImageHandler) Process(
engineapi.RuleError(rule.Name, engineapi.ImageVerify, "failed to fetch secrets", err),
)
}
iv := internal.NewImageVerifier(logger, rclient, policyContext, *ruleCopy, h.ivm, h.imageSignatureRepository)
iv := internal.NewImageVerifier(logger, rclient, h.ivCache, policyContext, *ruleCopy, h.ivm, h.imageSignatureRepository)
patch, ruleResponse := iv.Verify(ctx, imageVerify, h.images, h.configuration)
patches = append(patches, patch...)
engineResponses = append(engineResponses, ruleResponse...)

View file

@ -41,6 +41,7 @@ func (e *engine) verifyAndPatchImages(
rule,
e.configuration,
e.rclientFactory,
e.ivCache,
&ivm,
e.imageSignatureRepository,
)

View file

@ -22,6 +22,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/mutate/patch"
"github.com/kyverno/kyverno/pkg/engine/policycontext"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/registryclient"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"gomodules.xyz/jsonpatch/v2"
@ -185,6 +186,7 @@ func testVerifyAndPatchImages(
jp,
nil,
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
factories.DefaultContextLoaderFactory(cmResolver),
nil,
"",

View file

@ -17,6 +17,7 @@ import (
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/images"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/notary"
apiutils "github.com/kyverno/kyverno/pkg/utils/api"
"github.com/kyverno/kyverno/pkg/utils/jsonpointer"
@ -29,6 +30,7 @@ import (
type ImageVerifier struct {
logger logr.Logger
rclient engineapi.RegistryClient
ivCache imageverifycache.Client
policyContext engineapi.PolicyContext
rule kyvernov1.Rule
ivm *engineapi.ImageVerificationMetadata
@ -38,6 +40,7 @@ type ImageVerifier struct {
func NewImageVerifier(
logger logr.Logger,
rclient engineapi.RegistryClient,
ivCache imageverifycache.Client,
policyContext engineapi.PolicyContext,
rule kyvernov1.Rule,
ivm *engineapi.ImageVerificationMetadata,
@ -46,6 +49,7 @@ func NewImageVerifier(
return &ImageVerifier{
logger: logger,
rclient: rclient,
ivCache: ivCache,
policyContext: policyContext,
rule: rule,
ivm: ivm,

View file

@ -13,6 +13,7 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/registryclient"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
"github.com/stretchr/testify/require"
@ -38,6 +39,7 @@ func testMutate(
jp,
adapters.Client(client),
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
contextLoader,
nil,
"",

View file

@ -14,6 +14,7 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/registryclient"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
@ -38,6 +39,7 @@ func testValidate(
jp,
nil,
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
contextLoader,
nil,
"",

View file

@ -0,0 +1,93 @@
package imageverifycache
import (
"context"
"sync"
"time"
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
)
type cache struct {
logger logr.Logger
isCacheEnabled bool
maxSize int64
ttl time.Duration
lock sync.Mutex
}
type Option = func(*cache) error
func New(options ...Option) (Client, error) {
cache := &cache{}
for _, opt := range options {
if err := opt(cache); err != nil {
return nil, err
}
}
return cache, nil
}
func DisabledImageVerifyCache() Client {
return &cache{
logger: logr.Discard(),
isCacheEnabled: false,
maxSize: 0,
ttl: 0,
}
}
func WithLogger(l logr.Logger) Option {
return func(c *cache) error {
c.logger = l
return nil
}
}
func WithCacheEnableFlag(b bool) Option {
return func(c *cache) error {
c.isCacheEnabled = b
return nil
}
}
func WithMaxSize(s int64) Option {
return func(c *cache) error {
c.maxSize = s
return nil
}
}
func WithTTLDuration(t time.Duration) Option {
return func(c *cache) error {
c.ttl = t
return nil
}
}
func (c *cache) Set(ctx context.Context, policy kyvernov1.PolicyInterface, ruleName string, imageRef string) (bool, error) {
c.lock.Lock()
defer c.lock.Unlock()
c.logger.Info("Setting cache", "policy", policy.GetName(), "ruleName", ruleName, "imageRef", imageRef)
if !c.isCacheEnabled {
return false, nil
}
c.logger.Info("Successfully set cache", "policy", policy.GetName(), "ruleName", ruleName, "imageRef", imageRef)
return false, nil
}
func (c *cache) Get(ctx context.Context, policy kyvernov1.PolicyInterface, ruleName string, imageRef string) (bool, error) {
c.lock.Lock()
defer c.lock.Unlock()
c.logger.Info("Searching in cache", "policy", policy.GetName(), "ruleName", ruleName, "imageRef", imageRef)
if !c.isCacheEnabled {
return false, nil
}
c.logger.Info("Cache entry not found", "policy", policy.GetName(), "ruleName", ruleName, "imageRef", imageRef)
c.logger.Info("Cache entry found", "policy", policy.GetName(), "ruleName", ruleName, "imageRef", imageRef)
return false, nil
}

View file

@ -0,0 +1,18 @@
package imageverifycache
import (
"context"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
)
type Client interface {
// Set Adds an image to the cache. The image is considered to be verified for the given rule in the policy
// The entry outomatically expires after sometime
// Returns true when the cache entry is added
Set(ctx context.Context, policy kyvernov1.PolicyInterface, ruleName string, imageRef string) (bool, error)
// Get Searches for the image verified using the rule in the policy in the cache
// Returns true when the cache entry is found
Get(ctx context.Context, policy kyvernov1.PolicyInterface, ruleName string, imagerRef string) (bool, error)
}

View file

@ -13,6 +13,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/imageverifycache"
"github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/openapi"
"github.com/kyverno/kyverno/pkg/policycache"
@ -60,6 +61,7 @@ func NewFakeHandlers(ctx context.Context, policyCache policycache.Cache) webhook
jp,
adapters.Client(dclient),
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
factories.DefaultContextLoaderFactory(configMapResolver),
peLister,
"",

View file

@ -13,6 +13,7 @@ import (
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/engine/factories"
"github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/imageverifycache"
log "github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/registryclient"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
@ -1060,6 +1061,7 @@ func TestValidate_failure_action_overrides(t *testing.T) {
jp,
nil,
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
factories.DefaultContextLoaderFactory(nil),
nil,
"",
@ -1162,6 +1164,7 @@ func Test_RuleSelector(t *testing.T) {
jp,
nil,
factories.DefaultRegistryClientFactory(adapters.RegistryClient(rclient), nil),
imageverifycache.DisabledImageVerifyCache(),
factories.DefaultContextLoaderFactory(nil),
nil,
"",