Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/kind-cluster-image-policy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ jobs:
- cluster_image_policy_with_attestations_rego
- cluster_image_policy_with_include_typemeta
- cluster_image_policy_from_configmap_with_fetch_config_file
- cluster_image_policy_from_url

env:
KO_DOCKER_REPO: "registry.local:5000/policy-controller"
Expand Down
52 changes: 40 additions & 12 deletions config/300-clusterimagepolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,19 @@ spec:
includeTypeMeta:
description: IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.
type: boolean
remote:
description: Remote defines the url to a policy.
type: object
properties:
sha256sum:
description: Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.
type: string
url:
description: URL to the policy data.
type: string
type:
description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)
type: string
url:
description: URL to the policy data.
type: string
predicateType:
description: PredicateType defines which predicate type to verify. Matches cosign verify-attestation options.
type: string
Expand Down Expand Up @@ -305,12 +312,19 @@ spec:
includeTypeMeta:
description: IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.
type: boolean
remote:
description: Remote defines the url to a policy.
type: object
properties:
sha256sum:
description: Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.
type: string
url:
description: URL to the policy data.
type: string
type:
description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)
type: string
url:
description: URL to the policy data.
type: string
- name: v1beta1
served: true
storage: false
Expand Down Expand Up @@ -369,12 +383,19 @@ spec:
includeTypeMeta:
description: IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.
type: boolean
remote:
description: Remote defines the url to a policy.
type: object
properties:
sha256sum:
description: Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.
type: string
url:
description: URL to the policy data.
type: string
type:
description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)
type: string
url:
description: URL to the policy data.
type: string
predicateType:
description: PredicateType defines which predicate type to verify. Matches cosign verify-attestation options.
type: string
Expand Down Expand Up @@ -580,9 +601,16 @@ spec:
includeTypeMeta:
description: IncludeTypeMeta controls whether the TypeMeta will be included and made available for CIP level policy evalutation. Note that this only gets evaluated iff at least one authority matches.
type: boolean
remote:
description: Remote defines the url to a policy.
type: object
properties:
sha256sum:
description: Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.
type: string
url:
description: URL to the policy data.
type: string
type:
description: Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :)
type: string
url:
description: URL to the policy data.
type: string
14 changes: 13 additions & 1 deletion docs/api-types/index-v1alpha1.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* [MatchResource](#matchresource)
* [Policy](#policy)
* [RFC3161Timestamp](#rfc3161timestamp)
* [RemotePolicy](#remotepolicy)
* [Source](#source)
* [StaticRef](#staticref)
* [TLog](#tlog)
Expand Down Expand Up @@ -282,7 +283,7 @@ Policy specifies a policy to use for Attestation or the CIP validation (iff at l
| ----- | ----------- | ------ | -------- |
| type | Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :) | string | true |
| data | Data contains the policy definition. | string | false |
| url | URL to the policy data. | apis.URL | false |
| remote | Remote defines the url to a policy. | [RemotePolicy](#remotepolicy) | false |
| configMapRef | ConfigMapRef defines the reference to a configMap with the policy definition. | [ConfigMapReference](#configmapreference) | false |
| fetchConfigFile | FetchConfigFile controls whether ConfigFile will be fetched and made available for CIP level policy evaluation. Note that this only gets evaluated (and hence fetched) iff at least one authority matches. The ConfigFile will then be available in this format: https://github.com/opencontainers/image-spec/blob/main/config.md | bool | false |
| includeSpec | IncludeSpec controls whether resource `Spec` will be included and made available for CIP level policy evaluation. Note that this only gets evaluated iff at least one authority matches. Also note that because Spec may be of a different shape depending on the resource being evaluatied (see MatchResource for filtering) you might want to configure these to match the policy file to ensure the shape of the Spec is what you expect when evaling the policy. | bool | false |
Expand All @@ -301,6 +302,17 @@ RFC3161Timestamp specifies the URL to a RFC3161 time-stamping server that holds

[Back to TOC](#table-of-contents)

## RemotePolicy

RemotePolicy defines all the properties to fetch a remote policy

| Field | Description | Scheme | Required |
| ----- | ----------- | ------ | -------- |
| url | URL to the policy data. | apis.URL | false |
| sha256sum | Sha256sum defines the exact sha256sum computed out of the 'body' of the http response. | string | false |

[Back to TOC](#table-of-contents)

## Source

Source specifies the location of the signature
Expand Down
14 changes: 13 additions & 1 deletion docs/api-types/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* [MatchResource](#matchresource)
* [Policy](#policy)
* [RFC3161Timestamp](#rfc3161timestamp)
* [RemotePolicy](#remotepolicy)
* [Source](#source)
* [StaticRef](#staticref)
* [TLog](#tlog)
Expand Down Expand Up @@ -167,7 +168,7 @@ Policy specifies a policy to use for Attestation or the CIP validation (iff at l
| ----- | ----------- | ------ | -------- |
| type | Which kind of policy this is, currently only rego or cue are supported. Furthermore, only cue is tested :) | string | true |
| data | Data contains the policy definition. | string | false |
| url | URL to the policy data. | apis.URL | false |
| remote | Remote defines the url to a policy. | [RemotePolicy](#remotepolicy) | false |
| configMapRef | ConfigMapRef defines the reference to a configMap with the policy definition. | [ConfigMapReference](#configmapreference) | false |
| fetchConfigFile | FetchConfigFile controls whether ConfigFile will be fetched and made available for CIP level policy evaluation. Note that this only gets evaluated (and hence fetched) iff at least one authority matches. The ConfigFile will then be available in this format: https://github.com/opencontainers/image-spec/blob/main/config.md | bool | false |
| includeSpec | IncludeSpec controls whether resource `Spec` will be included and made available for CIP level policy evaluation. Note that this only gets evaluated iff at least one authority matches. Also note that because Spec may be of a different shape depending on the resource being evaluatied (see MatchResource for filtering) you might want to configure these to match the policy file to ensure the shape of the Spec is what you expect when evaling the policy. | bool | false |
Expand All @@ -186,6 +187,17 @@ RFC3161Timestamp specifies the URL to a RFC3161 time-stamping server that holds

[Back to TOC](#table-of-contents)

## RemotePolicy

RemotePolicy defines all the properties to fetch a remote policy

| Field | Description | Scheme | Required |
| ----- | ----------- | ------ | -------- |
| url | URL to the policy data. | apis.URL | false |
| sha256sum | Sha256sum defines the exact sha256sum computed out of the 'body' of the http response. | string | false |

[Back to TOC](#table-of-contents)

## Source

Source specifies the location of the signature
Expand Down
14 changes: 10 additions & 4 deletions pkg/apis/policy/v1alpha1/clusterimagepolicy_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,11 @@ func (authority *Authority) ConvertTo(ctx context.Context, sink *v1beta1.Authori
func (p *Policy) ConvertTo(ctx context.Context, sink *v1beta1.Policy) {
sink.Type = p.Type
sink.Data = p.Data
if p.URL != nil {
sink.URL = p.URL.DeepCopy()
if p.Remote != nil {
sink.Remote = &v1beta1.RemotePolicy{
URL: p.Remote.URL,
Sha256sum: p.Remote.Sha256sum,
}
}
if p.ConfigMapRef != nil {
sink.ConfigMapRef = &v1beta1.ConfigMapReference{
Expand All @@ -170,8 +173,11 @@ func (p *Policy) ConvertTo(ctx context.Context, sink *v1beta1.Policy) {
func (p *Policy) ConvertFrom(ctx context.Context, source *v1beta1.Policy) {
p.Type = source.Type
p.Data = source.Data
if source.URL != nil {
p.URL = source.URL.DeepCopy()
if source.Remote != nil {
p.Remote = &RemotePolicy{
URL: source.Remote.URL,
Sha256sum: source.Remote.Sha256sum,
}
}
if source.ConfigMapRef != nil {
p.ConfigMapRef = &ConfigMapReference{
Expand Down
12 changes: 10 additions & 2 deletions pkg/apis/policy/v1alpha1/clusterimagepolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ type MatchResource struct {
ResourceSelector *metav1.LabelSelector `json:"selector,omitempty"`
}

// RemotePolicy defines all the properties to fetch a remote policy
type RemotePolicy struct {
// URL to the policy data.
URL apis.URL `json:"url,omitempty"`
// Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.
Sha256sum string `json:"sha256sum,omitempty"`
}

// Policy specifies a policy to use for Attestation or the CIP validation (iff
// at least one authority matches).
// Exactly one of Data, URL, or ConfigMapReference must be specified.
Expand All @@ -224,9 +232,9 @@ type Policy struct {
// Data contains the policy definition.
// +optional
Data string `json:"data,omitempty"`
// URL to the policy data.
// Remote defines the url to a policy.
// +optional
URL *apis.URL `json:"url,omitempty"`
Remote *RemotePolicy `json:"remote,omitempty"`
// ConfigMapRef defines the reference to a configMap with the policy definition.
// +optional
ConfigMapRef *ConfigMapReference `json:"configMapRef,omitempty"`
Expand Down
29 changes: 25 additions & 4 deletions pkg/apis/policy/v1alpha1/clusterimagepolicy_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,19 @@ func (cmr *ConfigMapReference) Validate(ctx context.Context) *apis.FieldError {
return errs
}

func (r *RemotePolicy) Validate(ctx context.Context) *apis.FieldError {
var errs *apis.FieldError
urlObj := r.URL
u, err := url.Parse(urlObj.String())
if err != nil || (err == nil && (u.Host == "" || u.Scheme == "" || u.Scheme != "https")) {
errs = errs.Also(apis.ErrInvalidValue(r.URL.String(), "url", "url valid is invalid. host and https scheme are expected"))
}
if r.Sha256sum == "" {
errs = errs.Also(apis.ErrMissingField("sha256sum"))
}
return errs
}

func (p *Policy) Validate(ctx context.Context) *apis.FieldError {
if p == nil {
return nil
Expand All @@ -269,11 +282,19 @@ func (p *Policy) Validate(ctx context.Context) *apis.FieldError {
if p.Type != "cue" && p.Type != "rego" {
errs = errs.Also(apis.ErrInvalidValue(p.Type, "type", "only [cue,rego] are supported at the moment"))
}
if p.Data == "" && p.ConfigMapRef == nil {
errs = errs.Also(apis.ErrMissingField("data", "configMapRef"))
if p.Data == "" && p.ConfigMapRef == nil && p.Remote == nil {
errs = errs.Also(apis.ErrMissingField("data", "configMapRef", "remote"))
}
if p.Data != "" && p.ConfigMapRef != nil && p.Remote != nil {
errs = errs.Also(apis.ErrMultipleOneOf("data", "configMapRef", "remote"))
}
if (p.Data != "" && p.ConfigMapRef != nil) ||
(p.Data != "" && p.Remote != nil) ||
(p.ConfigMapRef != nil && p.Remote != nil) {
errs = errs.Also(apis.ErrMultipleOneOf("data", "configMapRef", "remote"))
}
if p.Data != "" && p.ConfigMapRef != nil {
errs = errs.Also(apis.ErrMultipleOneOf("data", "configMapRef"))
if p.Remote != nil {
errs = errs.Also(p.Remote.Validate(ctx).ViaField("remote"))
}
if p.ConfigMapRef != nil {
errs = errs.Also(p.ConfigMapRef.Validate(ctx).ViaField("configMapRef"))
Expand Down
44 changes: 42 additions & 2 deletions pkg/apis/policy/v1alpha1/clusterimagepolicy_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ func TestAttestationsValidation(t *testing.T) {
Type: "cue",
},
},
errorString: "missing field(s): policy.configMapRef, policy.data",
errorString: "missing field(s): policy.configMapRef, policy.data, policy.remote",
}, {
name: "custom with both policy data and configMapRef",
attestation: Attestation{Name: "second", PredicateType: "custom",
Expand All @@ -1023,7 +1023,47 @@ func TestAttestationsValidation(t *testing.T) {
},
},
},
errorString: "expected exactly one, got both: policy.configMapRef, policy.data",
errorString: "expected exactly one, got both: policy.configMapRef, policy.data, policy.remote",
}, {
name: "custom with both policy data, url and configMapRef",
attestation: Attestation{Name: "second", PredicateType: "custom",
Policy: &Policy{
Type: "cue",
Data: `predicateType: "cosign.sigstore.dev/attestation/vuln/v1"`,
ConfigMapRef: &ConfigMapReference{
Name: "cmname",
Key: "keyname",
},
Remote: &RemotePolicy{
URL: *apis.HTTPS("example.com"),
Sha256sum: "123123123",
},
},
},
errorString: "expected exactly one, got both: policy.configMapRef, policy.data, policy.remote",
}, {
name: "custom with both policy url",
attestation: Attestation{Name: "second", PredicateType: "custom",
Policy: &Policy{
Type: "cue",
Remote: &RemotePolicy{
URL: *apis.HTTPS("example.com"),
Sha256sum: "123123123",
},
},
},
}, {
name: "custom with invalid policy url scheme",
attestation: Attestation{Name: "second", PredicateType: "custom",
Policy: &Policy{
Type: "cue",
Remote: &RemotePolicy{
URL: *apis.HTTP("example.com"),
Sha256sum: "123123123",
},
},
},
errorString: "invalid value: http://example.com: policy.remote.url\nurl valid is invalid. host and https scheme are expected",
}, {
name: "custom with invalid configMapRef, missing key",
attestation: Attestation{Name: "second", PredicateType: "custom",
Expand Down
23 changes: 20 additions & 3 deletions pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions pkg/apis/policy/v1beta1/clusterimagepolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ type Attestation struct {
Policy *Policy `json:"policy,omitempty"`
}

// RemotePolicy defines all the properties to fetch a remote policy
type RemotePolicy struct {
// URL to the policy data.
URL apis.URL `json:"url,omitempty"`
// Sha256sum defines the exact sha256sum computed out of the 'body' of the http response.
Sha256sum string `json:"sha256sum,omitempty"`
}

// Policy specifies a policy to use for Attestation or the CIP validation (iff
// at least one authority matches).
// Exactly one of Data, URL, or ConfigMapReference must be specified.
Expand All @@ -214,9 +222,9 @@ type Policy struct {
// Data contains the policy definition.
// +optional
Data string `json:"data,omitempty"`
// URL to the policy data.
// Remote defines the url to a policy.
// +optional
URL *apis.URL `json:"url,omitempty"`
Remote *RemotePolicy `json:"remote,omitempty"`
// ConfigMapRef defines the reference to a configMap with the policy definition.
// +optional
ConfigMapRef *ConfigMapReference `json:"configMapRef,omitempty"`
Expand Down
Loading