mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-28 02:18:15 +00:00
feat: Add Manifest Index to ImageRegistry context (#9883)
* feat: Add Manifest Index to ImageRegistry context Signed-off-by: Netanel Kadosh <kadoshnetanel@gmail.com> * test: adding manifest list tests Signed-off-by: Netanel Kadosh <kadoshnetanel@gmail.com> --------- Signed-off-by: Netanel Kadosh <kadoshnetanel@gmail.com> Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
parent
244dbe19cf
commit
cef7be1fdc
7 changed files with 95 additions and 8 deletions
|
@ -34,6 +34,8 @@ func (a *rclientAdapter) ForRef(ctx context.Context, ref string) (*engineapi.Ima
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve image reference: %s, error: %v", ref, err)
|
||||
}
|
||||
// we ignore image index errors as it might be unavailable
|
||||
manifestList, _ := desc.ImageIndex()
|
||||
// We need to use the raw config and manifest to avoid dropping unknown keys
|
||||
// which are not defined in GGCR structs.
|
||||
rawManifest, err := image.RawManifest()
|
||||
|
@ -44,12 +46,21 @@ func (a *rclientAdapter) ForRef(ctx context.Context, ref string) (*engineapi.Ima
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch config for image reference: %s, error: %v", ref, err)
|
||||
}
|
||||
var rawManifestList []byte
|
||||
if manifestList != nil {
|
||||
rawManifestList, err = manifestList.RawManifest()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch image index for image reference: %s, error: %v", ref, err)
|
||||
}
|
||||
}
|
||||
|
||||
data := engineapi.ImageData{
|
||||
Image: ref,
|
||||
ResolvedImage: fmt.Sprintf("%s@%s", parsedRef.Context().Name(), desc.Digest.String()),
|
||||
Registry: parsedRef.Context().RegistryStr(),
|
||||
Repository: parsedRef.Context().RepositoryStr(),
|
||||
Identifier: parsedRef.Identifier(),
|
||||
ManifestList: rawManifestList,
|
||||
Manifest: rawManifest,
|
||||
Config: rawConfig,
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ type ImageData struct {
|
|||
Registry string
|
||||
Repository string
|
||||
Identifier string
|
||||
ManifestList []byte
|
||||
Manifest []byte
|
||||
Config []byte
|
||||
}
|
||||
|
|
|
@ -123,12 +123,20 @@ func (idl *imageDataLoader) fetchImageDataMap(client engineapi.ImageDataClient,
|
|||
return nil, fmt.Errorf("failed to decode config for image reference: %s, error: %v", ref, err)
|
||||
}
|
||||
|
||||
var manifestList interface{}
|
||||
if desc.ManifestList != nil {
|
||||
if err := json.Unmarshal(desc.ManifestList, &manifestList); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode image index for image reference: %s, error: %v", ref, err)
|
||||
}
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"image": desc.Image,
|
||||
"resolvedImage": desc.ResolvedImage,
|
||||
"registry": desc.Registry,
|
||||
"repository": desc.Repository,
|
||||
"identifier": desc.Identifier,
|
||||
"manifestList": manifestList,
|
||||
"manifest": manifest,
|
||||
"configData": configData,
|
||||
}
|
||||
|
|
|
@ -77,3 +77,40 @@ spec:
|
|||
list: request.object.spec.containers
|
||||
message: Images must specify a source/base image from which they are built to
|
||||
be valid.
|
||||
---
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: check-manifest-list
|
||||
spec:
|
||||
rules:
|
||||
- match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
name: check-manifest-list-rule
|
||||
preconditions:
|
||||
all:
|
||||
- key: '{{request.operation}}'
|
||||
operator: NotEquals
|
||||
value: DELETE
|
||||
validate:
|
||||
foreach:
|
||||
- context:
|
||||
- imageRegistry:
|
||||
reference: '{{ element.image }}'
|
||||
name: imageData
|
||||
- name: manifests
|
||||
variable:
|
||||
default: 0
|
||||
jmesPath: 'imageData.manifestList.manifests | length(@)'
|
||||
deny:
|
||||
conditions:
|
||||
all:
|
||||
- key: '{{ manifests }}'
|
||||
operator: Equals
|
||||
value: 0
|
||||
list: request.object.spec.containers
|
||||
message: Images must specify a manifest list to be valid.
|
||||
validationFailureAction: Enforce
|
||||
|
|
|
@ -13,6 +13,19 @@ results:
|
|||
- test-pod-with-trusted-registry
|
||||
result: pass
|
||||
rule: check-image-base-rule
|
||||
- kind: Pod
|
||||
policy: check-manifest-list
|
||||
resources:
|
||||
- test-pod-with-single-arch-no-index
|
||||
result: fail
|
||||
rule: check-manifest-list-rule
|
||||
- kind: Pod
|
||||
policy: check-manifest-list
|
||||
resources:
|
||||
- test-pod-with-trusted-registry
|
||||
- test-pod-with-single-arch-index
|
||||
result: pass
|
||||
rule: check-manifest-list-rule
|
||||
- kind: Pod
|
||||
policy: images
|
||||
resources:
|
||||
|
|
|
@ -16,4 +16,21 @@ spec:
|
|||
containers:
|
||||
- name: kyverno
|
||||
image: ghcr.io/kyverno/kyverno:v1.7.3
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-pod-with-single-arch-index
|
||||
spec:
|
||||
containers:
|
||||
- name: solr-single-arch
|
||||
image: solr:6
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-pod-with-single-arch-no-index
|
||||
spec:
|
||||
containers:
|
||||
- name: no-index
|
||||
image: ghcr.io/kyverno/test-verify-image:signed
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
apiVersion: cli.kyverno.io/v1alpha1
|
||||
globalValues:
|
||||
request.operation: CREATE
|
||||
kind: Value
|
||||
metadata:
|
||||
name: values
|
||||
globalValues:
|
||||
request.operation: CREATE
|
||||
policies:
|
||||
- name: gctx
|
||||
rules:
|
||||
- name: main-deployment-exists
|
||||
values:
|
||||
deploymentCount: 1
|
||||
- name: gctx
|
||||
rules:
|
||||
- name: main-deployment-exists
|
||||
values:
|
||||
deploymentCount: 1
|
||||
|
|
Loading…
Add table
Reference in a new issue