Skip to content

Commit

Permalink
Record invocation.configSource section in slsa provenance
Browse files Browse the repository at this point in the history
Related to tektoncd#521.

Prior to this PR, the SLSA provenance that Chains produces did not record
the source information of remote resources.

In this change, we want to record the source information in the provenance
to track where the remote pipeline/task definition came from i.e. git repo,
tekton bundles etc. The source information is available in
PipelineRun/TaskRun `Status.Provenance` field.

If a remote pipeline definition references remote task definitions from other remote places,
`predicate.invocation.configSource` will record the source information of
the remote pipeline definition only, and `predicate.buildConfig.tasks[x].invocation.configSource`
will record the source information for the corresponding remote task definition.

Signed-off-by: Chuang Wang <chuangw@google.com>
  • Loading branch information
chuangw6 committed Nov 28, 2022
1 parent 40b43e9 commit a082e18
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 40 deletions.
17 changes: 15 additions & 2 deletions pkg/chains/formats/intotoite6/attest/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ func Step(step *v1beta1.Step, stepState *v1beta1.StepState) StepAttestation {
return attestation
}

func Invocation(params []v1beta1.Param, paramSpecs []v1beta1.ParamSpec) slsa.ProvenanceInvocation {
i := slsa.ProvenanceInvocation{}
func Invocation(source *v1beta1.ConfigSource, params []v1beta1.Param, paramSpecs []v1beta1.ParamSpec) slsa.ProvenanceInvocation {
i := slsa.ProvenanceInvocation{
ConfigSource: convertConfigSource(source),
}
iParams := make(map[string]v1beta1.ArrayOrString)

// get implicit parameters from defaults
Expand All @@ -75,6 +77,17 @@ func Invocation(params []v1beta1.Param, paramSpecs []v1beta1.ParamSpec) slsa.Pro
return i
}

func convertConfigSource(source *v1beta1.ConfigSource) slsa.ConfigSource {
if source == nil {
return slsa.ConfigSource{}
}
return slsa.ConfigSource{
URI: source.URI,
Digest: source.Digest,
EntryPoint: source.EntryPoint,
}
}

// supports the SPDX format which is recommended by in-toto
// ref: https://spdx.dev/spdx-specification-21-web-version/#h.49x2ik5
// ref: https://github.com/in-toto/attestation/blob/849867bee97e33678f61cc6bd5da293097f84c25/spec/field_types.md
Expand Down
65 changes: 35 additions & 30 deletions pkg/chains/formats/intotoite6/intotoite6_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ func TestTaskRunCreatePayload1(t *testing.T) {
{URI: "git+https://git.test.com.git", Digest: slsa.DigestSet{"sha1": "sha:taskrun"}},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "ab123"},
EntryPoint: "build.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"IMAGE": {Type: "string", StringVal: "test.io/test/image"},
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskrun"},
Expand Down Expand Up @@ -160,7 +165,11 @@ func TestPipelineRunCreatePayload(t *testing.T) {
{URI: "git+https://git.test.com.git", Digest: slsa.DigestSet{"sha1": "abcd"}},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "28b123"},
EntryPoint: "pipeline.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"IMAGE": {Type: "string", StringVal: "test.io/test/image"},
},
Expand Down Expand Up @@ -193,7 +202,11 @@ func TestPipelineRunCreatePayload(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/catalog",
Digest: slsa.DigestSet{"sha1": "x123"},
EntryPoint: "git-clone.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskdefault"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -258,7 +271,11 @@ func TestPipelineRunCreatePayload(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "ab123"},
EntryPoint: "build.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskrun"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -381,7 +398,11 @@ func TestPipelineRunCreatePayloadChildRefs(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/catalog",
Digest: slsa.DigestSet{"sha1": "x123"},
EntryPoint: "git-clone.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskdefault"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -446,7 +467,11 @@ func TestPipelineRunCreatePayloadChildRefs(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "ab123"},
EntryPoint: "build.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskrun"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -526,6 +551,11 @@ func TestTaskRunCreatePayload2(t *testing.T) {
{URI: "git+https://git.test.com.git", Digest: slsa.DigestSet{"sha1": "sha:taskdefault"}},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{
URI: "github.com/catalog",
Digest: slsa.DigestSet{"sha1": "x123"},
EntryPoint: "git-clone.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskdefault"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -559,31 +589,6 @@ func TestTaskRunCreatePayload2(t *testing.T) {
}
}

func TestCreatePayloadNilTaskRef(t *testing.T) {
tr, err := objectloader.TaskRunFromFile("testdata/taskrun1.json")
if err != nil {
t.Fatal(err)
}

tr.Spec.TaskRef = nil
cfg := config.Config{
Builder: config.BuilderConfig{
ID: "testid",
},
}
f, _ := NewFormatter(cfg, logtesting.TestLogger(t))

p, err := f.CreatePayload(objects.NewTaskRunObject(tr))
if err != nil {
t.Errorf("unexpected error: %s", err.Error())
}

ps := p.(in_toto.ProvenanceStatement)
if diff := cmp.Diff("", ps.Predicate.Invocation.ConfigSource.EntryPoint); diff != "" {
t.Errorf("InTotoIte6.CreatePayload(): -want +got: %s", diff)
}
}

func TestMultipleSubjects(t *testing.T) {
tr, err := objectloader.TaskRunFromFile("testdata/taskrun-multiple-subjects.json")
if err != nil {
Expand Down
15 changes: 13 additions & 2 deletions pkg/chains/formats/intotoite6/pipelinerun/pipelinerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ func invocation(pro *objects.PipelineRunObject) slsa.ProvenanceInvocation {
if ps := pro.Status.PipelineSpec; ps != nil {
paramSpecs = ps.Params
}
return attest.Invocation(pro.Spec.Params, paramSpecs)
var cconfigSource *v1beta1.ConfigSource
if p := pro.Status.Provenance; p != nil {
cconfigSource = p.ConfigSource
}
return attest.Invocation(cconfigSource, pro.Spec.Params, paramSpecs)
}

func buildConfig(pro *objects.PipelineRunObject, logger *zap.SugaredLogger) BuildConfig {
Expand Down Expand Up @@ -129,14 +133,21 @@ func buildConfig(pro *objects.PipelineRunObject, logger *zap.SugaredLogger) Buil
} else {
paramSpecs = []v1beta1.ParamSpec{}
}

// cconfigSource information in taskrun status
var cconfigSource *v1beta1.ConfigSource
if p := tr.Status.Provenance; p != nil {
cconfigSource = p.ConfigSource
}

task := TaskAttestation{
Name: t.Name,
After: after,
StartedOn: tr.Status.StartTime.Time,
FinishedOn: tr.Status.CompletionTime.Time,
Status: getStatus(tr.Status.Conditions),
Steps: steps,
Invocation: attest.Invocation(params, paramSpecs),
Invocation: attest.Invocation(cconfigSource, params, paramSpecs),
Results: tr.Status.TaskRunResults,
}

Expand Down
29 changes: 25 additions & 4 deletions pkg/chains/formats/intotoite6/pipelinerun/provenance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ func createPro() *objects.PipelineRunObject {

func TestInvocation(t *testing.T) {
expected := slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "28b123"},
EntryPoint: "pipeline.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"IMAGE": {Type: "string", StringVal: "test.io/test/image"},
},
Expand Down Expand Up @@ -97,7 +102,11 @@ func TestBuildConfig(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/catalog",
Digest: slsa.DigestSet{"sha1": "x123"},
EntryPoint: "git-clone.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskdefault"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -162,7 +171,11 @@ func TestBuildConfig(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "ab123"},
EntryPoint: "build.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskrun"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -273,7 +286,11 @@ func TestBuildConfigTaskOrder(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/catalog",
Digest: slsa.DigestSet{"sha1": "x123"},
EntryPoint: "git-clone.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
"CHAINS-GIT_COMMIT": {Type: "string", StringVal: "sha:taskdefault"},
"CHAINS-GIT_URL": {Type: "string", StringVal: "https://git.test.com"},
Expand Down Expand Up @@ -338,7 +355,11 @@ func TestBuildConfigTaskOrder(t *testing.T) {
},
},
Invocation: slsa.ProvenanceInvocation{
ConfigSource: slsa.ConfigSource{},
ConfigSource: slsa.ConfigSource{
URI: "github.com/test",
Digest: map[string]string{"sha1": "ab123"},
EntryPoint: "build.yaml",
},
Parameters: map[string]v1beta1.ArrayOrString{
// TODO: Is this right?
// "CHAINS-GIT_COMMIT": {Type: "string", StringVal: "abcd"},
Expand Down
6 changes: 5 additions & 1 deletion pkg/chains/formats/intotoite6/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ func invocation(tro *objects.TaskRunObject) slsa.ProvenanceInvocation {
if ts := tro.Status.TaskSpec; ts != nil {
paramSpecs = ts.Params
}
return attest.Invocation(tro.Spec.Params, paramSpecs)
var source *v1beta1.ConfigSource
if p := tro.Status.Provenance; p != nil {
source = p.ConfigSource
}
return attest.Invocation(source, tro.Spec.Params, paramSpecs)
}

func metadata(tro *objects.TaskRunObject) *slsa.ProvenanceMetadata {
Expand Down
11 changes: 10 additions & 1 deletion pkg/chains/formats/intotoite6/testdata/pipelinerun1.json
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,15 @@
}
}
}
},
"provenance": {
"configSource": {
"uri": "github.com/test",
"digest": {
"sha1": "28b123"
},
"entryPoint": "pipeline.yaml"
}
}
}
}
}
9 changes: 9 additions & 0 deletions pkg/chains/formats/intotoite6/testdata/taskrun1.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@
"description": "Digest of the file just built."
}
]
},
"provenance": {
"configSource": {
"uri": "github.com/test",
"digest": {
"sha1": "ab123"
},
"entryPoint": "build.yaml"
}
}
}
}
9 changes: 9 additions & 0 deletions pkg/chains/formats/intotoite6/testdata/taskrun2.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@
"description": "some calculated uri"
}
]
},
"provenance": {
"configSource": {
"uri": "github.com/catalog",
"digest": {
"sha1": "x123"
},
"entryPoint": "git-clone.yaml"
}
}
}
}

0 comments on commit a082e18

Please sign in to comment.