Skip to content

Commit

Permalink
Add top-level build config to External Parameters (tektoncd#863)
Browse files Browse the repository at this point in the history
In the [build type design](https://docs.google.com/document/d/1ewqtPXyg_y3MmU6Tc6l1X8nfzjt0AJHlP6VOnFsGNpQ/edit#heading=h.8hw7rf805u8r), we decided the add the complete runSpec to externalParameters and the resolved top-level task/pipeline yaml to resolved dependencies. This has caused some friction in alignment between the Slsa specification, builders and verifiers.

According to the [SLSA spec](https://slsa.dev/provenance/v1#provenance), the external parameters should capture the inputs to the build interface. In the case where the build config is located remotely (e.g. in version control), one of the key ingredients that must be validated is the repo from where the build config was fetched. This information is available in the runSpec under pipelineRef or the taskRef however, that syntax is very specific to Tekton which makes it very challenging for generic verifiers (that validate provenances from several CI/CD systems) to identify without making the verification policy understand the Tekton API. To make matters worse, the repo uri is not necessarily embedded in the [resolver parameters](https://github.com/tektoncd/pipeline/blob/main/pkg/resolution/resolver/git/params.go). This means that depending on the parameters, verifiers need to add logic to extract the URI for verification.

In Tekton Chains, we have this information completely resolved and accessible. However, we add this to the resolved dependencies section of the provenance.
**Note** that this will also make it synchronous with the suggested [migration path from SLSA v0.2 to v1.0](https://slsa.dev/provenance/v1#migrating-from-02) where it says that the externalParameters should also contain the old invocation.ConfigSource.

This PR surfaces this information in `externalParameters` section of the SLSA 1.0 predicate and addresses issue tektoncd#846.
  • Loading branch information
chitrangpatel authored Jul 17, 2023
1 parent e97260e commit 5230749
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,29 @@ func internalParameters(pro *objects.PipelineRunObject) map[string]any {
// externalParameters adds the pipeline run spec
func externalParameters(pro *objects.PipelineRunObject) map[string]any {
externalParams := make(map[string]any)

// add the origin of top level pipeline config
// isRemotePipeline checks if the pipeline was fetched using a remote resolver
isRemotePipeline := false
if pro.Spec.PipelineRef != nil {
if pro.Spec.PipelineRef.Resolver != "" && pro.Spec.PipelineRef.Resolver != "Cluster" {
isRemotePipeline = true
}
}

if p := pro.Status.Provenance; p != nil && p.RefSource != nil && isRemotePipeline {
ref := ""
for alg, hex := range p.RefSource.Digest {
ref = fmt.Sprintf("%s:%s", alg, hex)
break
}
buildConfigSource := map[string]string{
"ref": ref,
"repository": p.RefSource.URI,
"path": p.RefSource.EntryPoint,
}
externalParams["buildConfigSource"] = buildConfigSource
}
externalParams["runSpec"] = pro.Spec
return externalParams
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,33 @@ func TestExternalParameters(t *testing.T) {
Value: v1beta1.ResultValue{Type: "array", ArrayVal: []string{}},
},
},
PipelineRef: &v1beta1.PipelineRef{
ResolverRef: v1beta1.ResolverRef{
Resolver: "git",
},
},
},
Status: v1beta1.PipelineRunStatus{
PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{
Provenance: &v1beta1.Provenance{
RefSource: &v1beta1.RefSource{
URI: "hello",
Digest: map[string]string{
"sha1": "abc123",
},
EntryPoint: "pipeline.yaml",
},
},
},
},
}

want := map[string]any{
"buildConfigSource": map[string]string{
"path": "pipeline.yaml",
"ref": "sha1:abc123",
"repository": "hello",
},
"runSpec": pr.Spec,
}
got := externalParameters(objects.NewPipelineRunObject(pr))
Expand Down
21 changes: 21 additions & 0 deletions pkg/chains/formats/slsa/v2alpha2/internal/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,27 @@ func internalParameters(tro *objects.TaskRunObject) map[string]any {
// externalParameters adds the task run spec
func externalParameters(tro *objects.TaskRunObject) map[string]any {
externalParams := make(map[string]any)
// add origin of the top level task config
// isRemoteTask checks if the task was fetched using a remote resolver
isRemoteTask := false
if tro.Spec.TaskRef != nil {
if tro.Spec.TaskRef.Resolver != "" && tro.Spec.TaskRef.Resolver != "Cluster" {
isRemoteTask = true
}
}
if t := tro.Status.Provenance; t != nil && t.RefSource != nil && isRemoteTask {
ref := ""
for alg, hex := range t.RefSource.Digest {
ref = fmt.Sprintf("%s:%s", alg, hex)
break
}
buildConfigSource := map[string]string{
"ref": ref,
"repository": t.RefSource.URI,
"path": t.RefSource.EntryPoint,
}
externalParams["buildConfigSource"] = buildConfigSource
}
externalParams["runSpec"] = tro.Spec
return externalParams
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,30 @@ func TestExternalParameters(t *testing.T) {
Value: v1beta1.ResultValue{Type: "array", ArrayVal: []string{}},
},
},
TaskRef: &v1beta1.TaskRef{
ResolverRef: v1beta1.ResolverRef{
Resolver: "git",
},
},
},
Status: v1beta1.TaskRunStatus{
TaskRunStatusFields: v1beta1.TaskRunStatusFields{
Provenance: &v1beta1.Provenance{
RefSource: &v1beta1.RefSource{
URI: "hello",
Digest: map[string]string{
"sha1": "abc123",
},
EntryPoint: "task.yaml",
},
},
},
},
}

want := map[string]any{
"runSpec": tr.Spec,
"buildConfigSource": map[string]string{"path": "task.yaml", "ref": "sha1:abc123", "repository": "hello"},
"runSpec": tr.Spec,
}
got := externalParameters(objects.NewTaskRunObject(tr))
if d := cmp.Diff(want, got); d != "" {
Expand Down

0 comments on commit 5230749

Please sign in to comment.