mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
feat: add support for background scanning of existing resource in image verification (#10287)
* feat: add support for background scanning of existing resource in image verification Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: change rule response type to image verify Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * chore: fix nilptr reference Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> --------- Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
This commit is contained in:
parent
1923a6f789
commit
47adea6f1c
26 changed files with 419 additions and 5 deletions
|
@ -66,6 +66,17 @@ func (s *scanner) ScanResource(ctx context.Context, resource unstructured.Unstru
|
|||
}
|
||||
spec := pol.GetSpec()
|
||||
if spec.HasVerifyImages() && len(errors) == 0 {
|
||||
if response != nil {
|
||||
// remove responses of verify image rules
|
||||
ruleResponses := make([]engineapi.RuleResponse, 0, len(response.PolicyResponse.Rules))
|
||||
for _, v := range response.PolicyResponse.Rules {
|
||||
if v.RuleType() != engineapi.ImageVerify {
|
||||
ruleResponses = append(ruleResponses, v)
|
||||
}
|
||||
}
|
||||
response.PolicyResponse.Rules = ruleResponses
|
||||
}
|
||||
|
||||
ivResponse, err := s.validateImages(ctx, resource, nsLabels, pol)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to scan images")
|
||||
|
@ -106,6 +117,9 @@ func (s *scanner) validateResource(ctx context.Context, resource unstructured.Un
|
|||
WithPolicy(policy).
|
||||
WithNamespaceLabels(nsLabels)
|
||||
response := s.engine.Validate(ctx, policyCtx)
|
||||
if len(response.PolicyResponse.Rules) > 0 {
|
||||
s.logger.Info("validateResource", "policy", policy, "response", response)
|
||||
}
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@ func (h validateImageHandler) Process(
|
|||
key, err := cache.MetaNamespaceKeyFunc(exception)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
|
||||
return resource, handlers.WithError(rule, engineapi.Validation, "failed to compute exception key", err)
|
||||
return resource, handlers.WithError(rule, engineapi.ImageVerify, "failed to compute exception key", err)
|
||||
} else {
|
||||
logger.V(3).Info("policy rule skipped due to policy exception", "exception", key)
|
||||
return resource, handlers.WithResponses(
|
||||
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule skipped due to policy exception "+key).WithException(exception),
|
||||
engineapi.RuleSkip(rule.Name, engineapi.ImageVerify, "rule skipped due to policy exception "+key).WithException(exception),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -90,11 +90,11 @@ func (h validateImageHandler) Process(
|
|||
logger.V(4).Info("validated image", "rule", rule.Name)
|
||||
if len(passedImages) > 0 || len(passedImages)+len(skippedImages) == 0 {
|
||||
if len(skippedImages) > 0 {
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, strings.Join(append([]string{"image verified, skipped images:"}, skippedImages...), " "))
|
||||
return resource, handlers.WithPass(rule, engineapi.ImageVerify, strings.Join(append([]string{"image verified, skipped images:"}, skippedImages...), " "))
|
||||
}
|
||||
return resource, handlers.WithPass(rule, engineapi.Validation, "image verified")
|
||||
return resource, handlers.WithPass(rule, engineapi.ImageVerify, "image verified")
|
||||
} else {
|
||||
return resource, handlers.WithSkip(rule, engineapi.Validation, strings.Join(append([]string{"image skipped, skipped images:"}, skippedImages...), " "))
|
||||
return resource, handlers.WithSkip(rule, engineapi.ImageVerify, strings.Join(append([]string{"image skipped, skipped images:"}, skippedImages...), " "))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
## Description
|
||||
|
||||
This test performs a simple verification of an image and creates a policy report for it
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
Pod creation should pass and report should be generated.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: test-verify-images
|
|
@ -0,0 +1,45 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: keyed-basic-policy
|
||||
spec:
|
||||
background: true
|
||||
failurePolicy: Fail
|
||||
webhookTimeoutSeconds: 30
|
||||
validationFailureAction: Audit
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
name: keyed-basic-rule
|
||||
verifyImages:
|
||||
- attestors:
|
||||
- entries:
|
||||
- keys:
|
||||
publicKeys: |-
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
|
||||
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
|
||||
-----END PUBLIC KEY-----
|
||||
rekor:
|
||||
ignoreTlog: true
|
||||
url: https://rekor.sigstore.dev
|
||||
imageReferences:
|
||||
- ghcr.io/kyverno/test-verify-image:*
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
- name: require-ns-purpose-label
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "You must have label `purpose` with value `production` set on all new namespaces."
|
||||
pattern:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: keyed-basic-policy
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/kyverno/test-verify-image:signed
|
||||
name: test-secret
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
|
@ -0,0 +1,39 @@
|
|||
apiVersion: v1
|
||||
items:
|
||||
- apiVersion: wgpolicyk8s.io/v1alpha2
|
||||
kind: PolicyReport
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kyverno
|
||||
namespace: test-verify-images
|
||||
ownerReferences:
|
||||
- apiVersion: v1
|
||||
kind: Pod
|
||||
name: test-secret-pod
|
||||
results:
|
||||
- policy: keyed-basic-policy
|
||||
result: pass
|
||||
rule: keyed-basic-rule
|
||||
scored: true
|
||||
source: kyverno
|
||||
- message: 'validation error: You must have label `purpose` with value `production`
|
||||
set on all new namespaces. rule require-ns-purpose-label failed at path /metadata/labels/'
|
||||
policy: keyed-basic-policy
|
||||
result: fail
|
||||
rule: require-ns-purpose-label
|
||||
scored: true
|
||||
source: kyverno
|
||||
scope:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
||||
summary:
|
||||
error: 0
|
||||
fail: 1
|
||||
pass: 1
|
||||
skip: 0
|
||||
warn: 0
|
||||
kind: List
|
||||
metadata:
|
||||
resourceVersion: ""
|
|
@ -0,0 +1,27 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: verify-image-background-audit
|
||||
spec:
|
||||
timeouts:
|
||||
delete: 2m
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-1.yaml
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-2.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-01-assert-1.yaml
|
||||
- name: step-02
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-02-apply-1.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-02-assert-1.yaml
|
||||
- name: step-03
|
||||
try:
|
||||
- assert:
|
||||
file: chainsaw-step-03-assert-1.yaml
|
|
@ -0,0 +1,8 @@
|
|||
## Description
|
||||
|
||||
This test performs a simple verification of an image and creates a policy report for it
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
Pod creation should pass and report should be generated.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: test-verify-images
|
|
@ -0,0 +1,33 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: keyed-basic-policy
|
||||
spec:
|
||||
background: true
|
||||
failurePolicy: Fail
|
||||
webhookTimeoutSeconds: 30
|
||||
validationFailureAction: Audit
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
name: keyed-basic-rule
|
||||
verifyImages:
|
||||
- attestors:
|
||||
- entries:
|
||||
- keys:
|
||||
publicKeys: |-
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
|
||||
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
|
||||
-----END PUBLIC KEY-----
|
||||
rekor:
|
||||
ignoreTlog: true
|
||||
url: https://rekor.sigstore.dev
|
||||
imageReferences:
|
||||
- ghcr.io/kyverno/test-verify-image:*
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: keyed-basic-policy
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/kyverno/test-verify-image:signed
|
||||
name: test-secret
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
|
@ -0,0 +1,32 @@
|
|||
apiVersion: v1
|
||||
items:
|
||||
- apiVersion: wgpolicyk8s.io/v1alpha2
|
||||
kind: PolicyReport
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kyverno
|
||||
namespace: test-verify-images
|
||||
ownerReferences:
|
||||
- apiVersion: v1
|
||||
kind: Pod
|
||||
name: test-secret-pod
|
||||
results:
|
||||
- policy: keyed-basic-policy
|
||||
result: pass
|
||||
rule: keyed-basic-rule
|
||||
scored: true
|
||||
source: kyverno
|
||||
scope:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
||||
summary:
|
||||
error: 0
|
||||
fail: 0
|
||||
pass: 1
|
||||
skip: 0
|
||||
warn: 0
|
||||
kind: List
|
||||
metadata:
|
||||
resourceVersion: ""
|
|
@ -0,0 +1,27 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: verify-image-background-basic
|
||||
spec:
|
||||
timeouts:
|
||||
delete: 2m
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-1.yaml
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-2.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-01-assert-1.yaml
|
||||
- name: step-02
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-02-apply-1.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-02-assert-1.yaml
|
||||
- name: step-03
|
||||
try:
|
||||
- assert:
|
||||
file: chainsaw-step-03-assert-1.yaml
|
|
@ -0,0 +1,8 @@
|
|||
## Description
|
||||
|
||||
This test creates background scan reports for image verification.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
Pod creation should pass as the image has been signed by the public key specified in the policy.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: test-verify-images
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
||||
spec:
|
||||
containers:
|
||||
- image: ghcr.io/kyverno/test-verify-image:signed
|
||||
name: test-secret
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
|
@ -0,0 +1,33 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: keyed-basic-policy
|
||||
spec:
|
||||
background: true
|
||||
failurePolicy: Fail
|
||||
webhookTimeoutSeconds: 30
|
||||
validationFailureAction: Audit
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
name: keyed-basic-rule
|
||||
verifyImages:
|
||||
- attestors:
|
||||
- entries:
|
||||
- keys:
|
||||
publicKeys: |-
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM
|
||||
5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==
|
||||
-----END PUBLIC KEY-----
|
||||
rekor:
|
||||
ignoreTlog: true
|
||||
url: https://rekor.sigstore.dev
|
||||
imageReferences:
|
||||
- ghcr.io/kyverno/test-verify-image:*
|
||||
mutateDigest: false
|
||||
verifyDigest: false
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: keyed-basic-policy
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,32 @@
|
|||
apiVersion: v1
|
||||
items:
|
||||
- apiVersion: wgpolicyk8s.io/v1alpha2
|
||||
kind: PolicyReport
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: kyverno
|
||||
namespace: test-verify-images
|
||||
ownerReferences:
|
||||
- apiVersion: v1
|
||||
kind: Pod
|
||||
name: test-secret-pod
|
||||
results:
|
||||
- policy: keyed-basic-policy
|
||||
result: pass
|
||||
rule: keyed-basic-rule
|
||||
scored: true
|
||||
source: kyverno
|
||||
scope:
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
name: test-secret-pod
|
||||
namespace: test-verify-images
|
||||
summary:
|
||||
error: 0
|
||||
fail: 0
|
||||
pass: 1
|
||||
skip: 0
|
||||
warn: 0
|
||||
kind: List
|
||||
metadata:
|
||||
resourceVersion: ""
|
|
@ -0,0 +1,27 @@
|
|||
apiVersion: chainsaw.kyverno.io/v1alpha1
|
||||
kind: Test
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: verify-image-background-existing
|
||||
spec:
|
||||
timeouts:
|
||||
delete: 2m
|
||||
steps:
|
||||
- name: step-01
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-1.yaml
|
||||
- apply:
|
||||
file: chainsaw-step-01-apply-2.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-01-assert-1.yaml
|
||||
- name: step-02
|
||||
try:
|
||||
- apply:
|
||||
file: chainsaw-step-02-apply-1.yaml
|
||||
- assert:
|
||||
file: chainsaw-step-02-assert-1.yaml
|
||||
- name: step-03
|
||||
try:
|
||||
- assert:
|
||||
file: chainsaw-step-03-assert-1.yaml
|
Loading…
Reference in a new issue