Skip to content

Commit

Permalink
Add resolved source info in ResolutionRequest status
Browse files Browse the repository at this point in the history
Related to
- #5529
- #5397

Before:
The `ResolutionRequestStatusFields` only has the `Data` that is a string
representation of the resolved content.

Now:
A new field called `Source` is now introduced to the `ResolutionRequestStatusFields`
to record the source information of the remote data in a structured way
using the standard SLSA ConfigSource struct.

Why?
Recently there is a clear requirement that the remote source
information of the remote data should be recorded in the provenance to
link back to its origin including the resolved the commit sha when users
only provide the branch/tag name for the resolver. Without this PR, the
only way to achieve this is to pass the resolved source information through
annotations, which has a couple of the drawbacks i.e. unstructured data,
hard to maintain and to make changes in future etc. That's where this PR
comes in to solve the problem.

Signed-off-by: Chuang Wang <[email protected]>
  • Loading branch information
chuangw6 authored and tekton-robot committed Sep 30, 2022
1 parent 4b53ae5 commit b15c5de
Show file tree
Hide file tree
Showing 20 changed files with 305 additions and 9 deletions.
26 changes: 26 additions & 0 deletions docs/how-to-write-a-resolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ import (

"github.com/tektoncd/pipeline/pkg/resolution/resolver/framework"
"knative.dev/pkg/injection/sharedmain"
"github.com/tektoncd/pipeline/pkg/apis/resolution/v1alpha1"
)
```

Expand Down Expand Up @@ -259,6 +260,31 @@ func (*myResolvedResource) Data() []byte {
func (*myResolvedResource) Annotations() map[string]string {
return nil
}

// Source is the source reference of the remote data that records where the remote
// file came from including the url, digest and the entrypoint. None atm.
func (*myResolvedResource) Source() *v1alpha1.ConfigSource {
return nil
}
```

Best practice: In order to enable Tekton Chains to record the source
information of the remote data in the SLSA provenance, the resolver should
implement the `Source()` method to return a correct ConfigSource value. See the
following example.

```go
// Source is the source reference of the remote data that records where the remote
// file came from including the url, digest and the entrypoint.
func (*myResolvedResource) Source() *v1alpha1.ConfigSource {
return &v1alpha1.ConfigSource{
URI: "https://github.com/user/example",
Digest: map[string]string{
"sha1": "example",
},
EntryPoint: "foo/bar/task.yaml",
}
}
```

## The deployment configuration
Expand Down
6 changes: 6 additions & 0 deletions docs/resolver-template/cmd/demoresolver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,9 @@ func (*myResolvedResource) Data() []byte {
func (*myResolvedResource) Annotations() map[string]string {
return nil
}

// Source is the source reference of the remote data that records where the remote
// file came from including the url, digest and the entrypoint. None atm.
func (*myResolvedResource) Source() *v1alpha1.ConfigSource {
return nil
}
2 changes: 2 additions & 0 deletions go.sum

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

64 changes: 61 additions & 3 deletions pkg/apis/pipeline/v1beta1/openapi_generated.go

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

36 changes: 34 additions & 2 deletions pkg/apis/pipeline/v1beta1/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,28 @@
}
}
},
"v1alpha1.ConfigSource": {
"description": "ConfigSource records where the task/pipeline file came from.",
"type": "object",
"properties": {
"digest": {
"description": "Digest is a collection of cryptographic digests for the contents of the artifact specified by URI. https://github.com/in-toto/attestation/blob/main/spec/field_types.md#DigestSet Example: {\"sha1\": \"f99d13e554ffcb696dee719fa85b695cb5b0f428\"}",
"type": "object",
"additionalProperties": {
"type": "string",
"default": ""
}
},
"entryPoint": {
"description": "EntryPoint identifying the entry point into the build. This is often a path to a configuration file and/or a target label within that file. Example: \"task/git-clone/0.8/git-clone.yaml\"",
"type": "string"
},
"uri": {
"description": "URI indicating the identity of the source of the config. https://github.com/in-toto/attestation/blob/main/spec/field_types.md#ResourceURI Example: https://github.com/tektoncd/catalog",
"type": "string"
}
}
},
"v1alpha1.PipelineResource": {
"description": "PipelineResource describes a resource that is an input to or output from a Task.",
"type": "object",
Expand Down Expand Up @@ -308,7 +330,8 @@
"description": "ResolutionRequestStatus are all the fields in a ResolutionRequest's status subresource.",
"type": "object",
"required": [
"data"
"data",
"source"
],
"properties": {
"annotations": {
Expand Down Expand Up @@ -338,20 +361,29 @@
"description": "ObservedGeneration is the 'Generation' of the Service that was last processed by the controller.",
"type": "integer",
"format": "int64"
},
"source": {
"description": "Source is the source reference of the remote data that records where the remote file came from including the url, digest and the entrypoint.",
"$ref": "#/definitions/v1alpha1.ConfigSource"
}
}
},
"v1alpha1.ResolutionRequestStatusFields": {
"description": "ResolutionRequestStatusFields are the ResolutionRequest-specific fields for the status subresource.",
"type": "object",
"required": [
"data"
"data",
"source"
],
"properties": {
"data": {
"description": "Data is a string representation of the resolved content of the requested resource in-lined into the ResolutionRequest object.",
"type": "string",
"default": ""
},
"source": {
"description": "Source is the source reference of the remote data that records where the remote file came from including the url, digest and the entrypoint.",
"$ref": "#/definitions/v1alpha1.ConfigSource"
}
}
},
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/resolution/v1alpha1/resolution_request_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,30 @@ type ResolutionRequestStatusFields struct {
// of the requested resource in-lined into the ResolutionRequest
// object.
Data string `json:"data"`
// Source is the source reference of the remote data that records where the remote
// file came from including the url, digest and the entrypoint.
Source *ConfigSource `json:"source"`
}

// GetStatus implements KRShaped.
func (rr *ResolutionRequest) GetStatus() *duckv1.Status {
return &rr.Status.Status
}

// ConfigSource records where the task/pipeline file came from.
type ConfigSource struct {
// URI indicating the identity of the source of the config.
// https://github.com/in-toto/attestation/blob/main/spec/field_types.md#ResourceURI
// Example: https://github.com/tektoncd/catalog
URI string `json:"uri,omitempty"`

// Digest is a collection of cryptographic digests for the contents of the artifact specified by URI.
// https://github.com/in-toto/attestation/blob/main/spec/field_types.md#DigestSet
// Example: {"sha1": "f99d13e554ffcb696dee719fa85b695cb5b0f428"}
Digest map[string]string `json:"digest,omitempty"`

// EntryPoint identifying the entry point into the build. This is often a path to a
// configuration file and/or a target label within that file.
// Example: "task/git-clone/0.8/git-clone.yaml"
EntryPoint string `json:"entryPoint,omitempty"`
}
30 changes: 29 additions & 1 deletion pkg/apis/resolution/v1alpha1/zz_generated.deepcopy.go

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

21 changes: 21 additions & 0 deletions pkg/apis/resolution/v1beta1/resolution_request_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,30 @@ type ResolutionRequestStatusFields struct {
// of the requested resource in-lined into the ResolutionRequest
// object.
Data string `json:"data"`
// Source is the source reference of the remote data that records the url, digest
// and the entrypoint.
Source *ConfigSource `json:"source"`
}

// GetStatus implements KRShaped.
func (rr *ResolutionRequest) GetStatus() *duckv1.Status {
return &rr.Status.Status
}

// ConfigSource records where the task/pipeline file came from.
type ConfigSource struct {
// URI indicating the identity of the source of the config.
// https://github.com/in-toto/attestation/blob/main/spec/field_types.md#ResourceURI
// Example: https://github.com/tektoncd/catalog
URI string `json:"uri,omitempty"`

// Digest is a collection of cryptographic digests for the contents of the artifact specified by URI.
// https://github.com/in-toto/attestation/blob/main/spec/field_types.md#DigestSet
// Example: {"sha1": "f99d13e554ffcb696dee719fa85b695cb5b0f428"}
Digest map[string]string `json:"digest,omitempty"`

// EntryPoint identifying the entry point into the build. This is often a path to a
// configuration file and/or a target label within that file.
// Example: "task/git-clone/0.8/git-clone.yaml"
EntryPoint string `json:"entryPoint,omitempty"`
}
30 changes: 29 additions & 1 deletion pkg/apis/resolution/v1beta1/zz_generated.deepcopy.go

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

Loading

0 comments on commit b15c5de

Please sign in to comment.