Skip to content

Commit d1a9c20

Browse files
authored
fix!: ensure we only pull artifacts when running full or fast layer validation (#256)
## Issue Resolves #242 ## Description This PR accomplishes a few things: 1. Ensures we only pull images when running full or fast layer validation 2. Rewords details to reflect the above It does this by introducing a `ValidationType` which can be set to `full`, `fast`, or `none`. At the host level, `ValidationType` is defaulted to `none`. When set on the artifact level, you can override the value configured on the host. This also means that `SkipLayerValidation` is no longer a supported field.
1 parent c1942b7 commit d1a9c20

File tree

11 files changed

+274
-136
lines changed

11 files changed

+274
-136
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The OCI validator plugin reconciles `OciValidator` custom resources to perform t
1313

1414
1. Validate OCI registry authentication
1515
2. Validate the existence of arbitrary OCI artifacts (pack, image, etc.)
16-
3. Validate downloading arbitrary OCI artifacts
16+
3. If `ValidationType` is set to `full` or `fast`, downloads the OCI artifacts and verifies their layers, manifests, and configs
1717

1818
Each `OciValidator` CR is (re)-processed every two minutes to continuously ensure that your OCI registry matches the expected state.
1919

api/v1alpha1/ocivalidator_types.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,19 @@ type OciRegistryRule struct {
4848
// Host is the URI of an OCI registry.
4949
Host string `json:"host" yaml:"host"`
5050

51-
// SkipLayerValidation specifies whether deep validation of the artifact layers should be skipped.
52-
// The existence of layers will always validated whether this option is enabled or disabled.
53-
// See more details here:
54-
// https://github.com/google/go-containerregistry/blob/8dadbe76ff8c20d0e509406f04b7eade43baa6c1/pkg/v1/validate/image.go#L105
55-
SkipLayerValidation bool `json:"skipLayerValidation,omitempty" yaml:"skipLayerValidation,omitempty"`
51+
// ValidationType specifies which (if any) type of validation is performed on the artifacts.
52+
// Valid values are "full", "fast", and "none". When set to "none", the artifact will not be pulled and no extra validation will be performed.
53+
// For both "full" and "fast" validationType, the following validations will be executed:
54+
// - Layers existence will be validated
55+
// - Config digest, size, content, and type will be validated
56+
// - Manifest digest, content, and size will be validated
57+
// For "full" validationType, the following additional validations will be performed:
58+
// - Layer digest, diffID, size, and media type will be validated
59+
// See more details about validation here:
60+
// https://github.com/google/go-containerregistry/blob/8dadbe76ff8c20d0e509406f04b7eade43baa6c1/pkg/v1/validate/image.go#L30
61+
// +kubebuilder:validation:Enum=full;fast;none
62+
// +kubebuilder:default:=none
63+
ValidationType ValidationType `json:"validationType" yaml:"validationType"`
5664

5765
// Artifacts is a slice of artifacts in the OCI registry that should be validated.
5866
Artifacts []Artifact `json:"artifacts,omitempty" yaml:"artifacts,omitempty"`
@@ -70,6 +78,18 @@ type OciRegistryRule struct {
7078
SignatureVerification SignatureVerification `json:"signatureVerification,omitempty" yaml:"signatureVerification,omitempty"`
7179
}
7280

81+
// ValidationType defines the type of extra validation to perform on the artifacts.
82+
type ValidationType string
83+
84+
const (
85+
// ValidationTypeFull specifies full validation of the artifacts.
86+
ValidationTypeFull ValidationType = "full"
87+
// ValidationTypeFast specifies fast validation of the artifacts.
88+
ValidationTypeFast ValidationType = "fast"
89+
// ValidationTypeNone specifies no extra validation of the artifacts, artifacts will not be pulled.
90+
ValidationTypeNone ValidationType = "none"
91+
)
92+
7393
// Name returns the name of the OciRegistryRule.
7494
func (r OciRegistryRule) Name() string {
7595
return r.RuleName
@@ -86,8 +106,9 @@ type Artifact struct {
86106
// When no tag or digest are specified, the default tag "latest" is used.
87107
Ref string `json:"ref" yaml:"ref"`
88108

89-
// SkipLayerValidation overrides the OciRegistryRule level SkiplayerValidation for a particular artifact.
90-
SkipLayerValidation *bool `json:"skipLayerValidation,omitempty" yaml:"skipLayerValidation,omitempty"`
109+
// ValidationType overrides the OciRegistryRule level ValidationType for a particular artifact.
110+
// +kubebuilder:validation:Enum=full;fast;none
111+
ValidationType *ValidationType `json:"validationType,omitempty" yaml:"validationType,omitempty"`
91112
}
92113

93114
// Auth defines the authentication information for the registry.

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chart/validator-plugin-oci/crds/validation.spectrocloud.labs_ocivalidators.yaml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ spec:
6161
6262
When no tag or digest are specified, the default tag "latest" is used.
6363
type: string
64-
skipLayerValidation:
65-
description: SkipLayerValidation overrides the OciRegistryRule
66-
level SkiplayerValidation for a particular artifact.
67-
type: boolean
64+
validationType:
65+
description: ValidationType overrides the OciRegistryRule
66+
level ValidationType for a particular artifact.
67+
enum:
68+
- full
69+
- fast
70+
- none
71+
type: string
6872
required:
6973
- ref
7074
type: object
@@ -148,16 +152,28 @@ spec:
148152
- provider
149153
- secretName
150154
type: object
151-
skipLayerValidation:
155+
validationType:
156+
default: none
152157
description: |-
153-
SkipLayerValidation specifies whether deep validation of the artifact layers should be skipped.
154-
The existence of layers will always validated whether this option is enabled or disabled.
155-
See more details here:
156-
https://github.com/google/go-containerregistry/blob/8dadbe76ff8c20d0e509406f04b7eade43baa6c1/pkg/v1/validate/image.go#L105
157-
type: boolean
158+
ValidationType specifies which (if any) type of validation is performed on the artifacts.
159+
Valid values are "full", "fast", and "none". When set to "none", the artifact will not be pulled and no extra validation will be performed.
160+
For both "full" and "fast" validationType, the following validations will be executed:
161+
- Layers existence will be validated
162+
- Config digest, size, content, and type will be validated
163+
- Manifest digest, content, and size will be validated
164+
For "full" validationType, the following additional validations will be performed:
165+
- Layer digest, diffID, size, and media type will be validated
166+
See more details about validation here:
167+
https://github.com/google/go-containerregistry/blob/8dadbe76ff8c20d0e509406f04b7eade43baa6c1/pkg/v1/validate/image.go#L30
168+
enum:
169+
- full
170+
- fast
171+
- none
172+
type: string
158173
required:
159174
- host
160175
- name
176+
- validationType
161177
type: object
162178
maxItems: 5
163179
type: array

config/crd/bases/validation.spectrocloud.labs_ocivalidators.yaml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ spec:
6161
6262
When no tag or digest are specified, the default tag "latest" is used.
6363
type: string
64-
skipLayerValidation:
65-
description: SkipLayerValidation overrides the OciRegistryRule
66-
level SkiplayerValidation for a particular artifact.
67-
type: boolean
64+
validationType:
65+
description: ValidationType overrides the OciRegistryRule
66+
level ValidationType for a particular artifact.
67+
enum:
68+
- full
69+
- fast
70+
- none
71+
type: string
6872
required:
6973
- ref
7074
type: object
@@ -148,16 +152,28 @@ spec:
148152
- provider
149153
- secretName
150154
type: object
151-
skipLayerValidation:
155+
validationType:
156+
default: none
152157
description: |-
153-
SkipLayerValidation specifies whether deep validation of the artifact layers should be skipped.
154-
The existence of layers will always validated whether this option is enabled or disabled.
155-
See more details here:
156-
https://github.com/google/go-containerregistry/blob/8dadbe76ff8c20d0e509406f04b7eade43baa6c1/pkg/v1/validate/image.go#L105
157-
type: boolean
158+
ValidationType specifies which (if any) type of validation is performed on the artifacts.
159+
Valid values are "full", "fast", and "none". When set to "none", the artifact will not be pulled and no extra validation will be performed.
160+
For both "full" and "fast" validationType, the following validations will be executed:
161+
- Layers existence will be validated
162+
- Config digest, size, content, and type will be validated
163+
- Manifest digest, content, and size will be validated
164+
For "full" validationType, the following additional validations will be performed:
165+
- Layer digest, diffID, size, and media type will be validated
166+
See more details about validation here:
167+
https://github.com/google/go-containerregistry/blob/8dadbe76ff8c20d0e509406f04b7eade43baa6c1/pkg/v1/validate/image.go#L30
168+
enum:
169+
- full
170+
- fast
171+
- none
172+
type: string
158173
required:
159174
- host
160175
- name
176+
- validationType
161177
type: object
162178
maxItems: 5
163179
type: array

config/samples/ocivalidator-private-registry.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ spec:
88
# private oci registry artifacts using basic auth and a caCert
99
- name: "private oci registry"
1010
host: "oci-airgap.spectrocloud.dev"
11+
validationType: "full"
1112
artifacts:
1213
- ref: "spectro-images/gcr.io/spectro-images-fips/kube-apiserver:v1.26.5"
14+
validationType: "fast"
1315
- ref: "spectro-packs/spectro-packs/archive/vault:0.25.0"
14-
skipLayerValidation: true
1516
auth:
1617
basic:
1718
username: some-user
@@ -40,7 +41,6 @@ spec:
4041
# private ecr registry with ecr auth and no artifact specified
4142
- name: "private ecr registry"
4243
host: "745150053801.dkr.ecr.us-east-1.amazonaws.com"
43-
skipLayerValidation: true
4444
auth:
4545
ecr:
4646
accessKeyID: some-access-key-id
@@ -50,11 +50,10 @@ spec:
5050
# private oci registry with secret key auth and signature verification enabled
5151
- name: "private oci registry with signature verification enabled"
5252
host: "registry.hub.docker.com"
53-
skipLayerValidation: true
53+
validationType: "fast"
5454
artifacts:
5555
- ref: "ahmadibraspectrocloud/validator:signed"
5656
- ref: "ahmadibraspectrocloud/validator-plugin-oci:signed"
57-
skipLayerValidation: false
5857
signatureVerification:
5958
secretName: "cosign-public-keys"
6059
auth:

config/samples/ocivalidator-public-registry.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ spec:
1414
# public oci registry artifact referenced by default "latest" tag
1515
- name: "public oci registry with default latest tag"
1616
host: "registry.hub.docker.com"
17+
validationType: "full"
1718
artifacts:
1819
- ref: "ahmadibraspectrocloud/kubebuilder-cron"
1920

2021
# public oci registry with signature verification enabled
2122
- name: "public oci registry with signature verification enabled"
2223
host: "registry.hub.docker.com"
24+
validationType: "fast"
2325
artifacts:
2426
- ref: "ahmadibraspectrocloud/kb-guestbook:signed"
2527
signatureVerification:

internal/controller/ocivalidator_controller_test.go

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ var _ = Describe("OCIValidator controller", Ordered, func() {
3737
Spec: v1alpha1.OciValidatorSpec{
3838
OciRegistryRules: []v1alpha1.OciRegistryRule{
3939
{
40-
RuleName: "basic auth and empty artifact list",
41-
Host: "foo1.registry.io",
40+
RuleName: "basic auth and empty artifact list",
41+
Host: "foo1.registry.io",
42+
ValidationType: v1alpha1.ValidationTypeNone,
4243
Auth: v1alpha1.Auth{
4344
Basic: &v1alpha1.BasicAuth{
4445
Username: "userName",
@@ -51,9 +52,9 @@ var _ = Describe("OCIValidator controller", Ordered, func() {
5152
},
5253
},
5354
{
54-
RuleName: "layer validation skipped on rule level",
55-
Host: "foo.registry.io",
56-
SkipLayerValidation: true,
55+
RuleName: "full layer validation enabled on rule level",
56+
Host: "foo.registry.io",
57+
ValidationType: v1alpha1.ValidationTypeFull,
5758
Artifacts: []v1alpha1.Artifact{
5859
{
5960
Ref: "foo/bar:latest",
@@ -64,38 +65,41 @@ var _ = Describe("OCIValidator controller", Ordered, func() {
6465
},
6566
},
6667
{
67-
RuleName: "layer validation skipped on artifact level",
68-
Host: "foo.registry.io",
68+
RuleName: "fast layer validation enabled on artifact level",
69+
Host: "foo.registry.io",
70+
ValidationType: v1alpha1.ValidationTypeNone,
6971
Artifacts: []v1alpha1.Artifact{
7072
{
71-
Ref: "foo/bar:latest",
72-
SkipLayerValidation: util.Ptr(true),
73+
Ref: "foo/bar:latest",
74+
ValidationType: util.Ptr(v1alpha1.ValidationTypeFast),
7375
},
7476
},
7577
SignatureVerification: v1alpha1.SignatureVerification{
7678
Provider: "cosign",
7779
},
7880
},
7981
{
80-
RuleName: "secret auth and ca cert provided",
81-
Host: "foo2.registry.io",
82+
RuleName: "secret auth and ca cert provided",
83+
Host: "foo2.registry.io",
84+
ValidationType: v1alpha1.ValidationTypeNone,
8285
Auth: v1alpha1.Auth{
8386
SecretName: util.Ptr("auth-secret"),
8487
},
8588
CaCert: "dummy-ca-cert",
8689
Artifacts: []v1alpha1.Artifact{
8790
{
88-
Ref: "foo/bar:latest",
89-
SkipLayerValidation: util.Ptr(true),
91+
Ref: "foo/bar:latest",
92+
ValidationType: util.Ptr(v1alpha1.ValidationTypeFast),
9093
},
9194
},
9295
SignatureVerification: v1alpha1.SignatureVerification{
9396
Provider: "cosign",
9497
},
9598
},
9699
{
97-
RuleName: "ecr auth and pubkeys secret provided and created",
98-
Host: "foo3.registry.io",
100+
RuleName: "ecr auth and pubkeys secret provided and created",
101+
Host: "foo3.registry.io",
102+
ValidationType: v1alpha1.ValidationTypeNone,
99103
Auth: v1alpha1.Auth{
100104
ECR: &v1alpha1.ECRAuth{
101105
AccessKeyID: "accessKeyID",

0 commit comments

Comments
 (0)