Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const (
InputResultName = "inputs/result"
// PipelineResourceName is the name of the resolved dependency of pipeline resource.
PipelineResourceName = "pipelineResource"
// StepActionConfigName is the name of the resolved dependencies of remote StepAction
StepActionConfigName = "stepAction"
)

// AddTaskDescriptorContent is used to toggle the fields in see AddTektonTaskDescriptor and AddSLSATaskDescriptor
Expand Down Expand Up @@ -183,6 +185,7 @@ func fromPipelineTask(logger *zap.SugaredLogger, pro *objects.PipelineRunObjectV
mats = append(mats, sidecarMaterials...)

// convert materials to resolved dependencies
resolvedDependencies = append(resolvedDependencies, fromRemoteStepActions(tr)...)
resolvedDependencies = append(resolvedDependencies, ConvertMaterialsToResolvedDependencies(mats, "")...)

}
Expand All @@ -191,6 +194,20 @@ func fromPipelineTask(logger *zap.SugaredLogger, pro *objects.PipelineRunObjectV
return resolvedDependencies, nil
}

// fromRemoteStepActions converts remote StepAction provenance into resolved dependencies
func fromRemoteStepActions(tro *objects.TaskRunObjectV1) []*intoto.ResourceDescriptor {
var rds []*intoto.ResourceDescriptor
for _, stepProv := range tro.GetRemoteStepActions() {
rd := &intoto.ResourceDescriptor{
Name: fmt.Sprintf("%s/%s", StepActionConfigName, stepProv.StepName),
Uri: stepProv.Provenance.RefSource.URI,
Digest: stepProv.Provenance.RefSource.Digest,
}
rds = append(rds, rd)
}
return rds
}

// taskDependencies gather all dependencies in a task and adds them to resolvedDependencies
func taskDependencies(ctx context.Context, opts ResolveOptions, tro *objects.TaskRunObjectV1) ([]*intoto.ResourceDescriptor, error) {
var resolvedDependencies []*intoto.ResourceDescriptor
Expand Down Expand Up @@ -224,6 +241,8 @@ func taskDependencies(ctx context.Context, opts ResolveOptions, tro *objects.Tas
resolvedDependencies = append(resolvedDependencies,
ConvertMaterialsToResolvedDependencies(mats, PipelineResourceName)...)

resolvedDependencies = append(resolvedDependencies, fromRemoteStepActions(tro)...)

// remove duplicate resolved dependencies
resolvedDependencies, err = RemoveDuplicateResolvedDependencies(resolvedDependencies)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,118 @@ func TestTaskRun(t *testing.T) {
},
},
},
{
name: "resolvedDependencies from remote StepAction",
obj: objects.NewTaskRunObjectV1(&v1.TaskRun{
Status: v1.TaskRunStatus{
TaskRunStatusFields: v1.TaskRunStatusFields{
Steps: []v1.StepState{
{
Name: "remote-build",
ImageID: "gcr.io/test/build@sha256:aaa111",
Provenance: &v1.Provenance{
RefSource: &v1.RefSource{
URI: "git+https://github.com/tektoncd/stepactions",
Digest: map[string]string{"sha256": "bbb222"},
},
},
},
},
},
},
}),
want: []*intoto.ResourceDescriptor{
{
Uri: "oci://gcr.io/test/build",
Digest: common.DigestSet{"sha256": "aaa111"},
},
{
Name: "stepAction/remote-build",
Uri: "git+https://github.com/tektoncd/stepactions",
Digest: common.DigestSet{"sha256": "bbb222"},
},
},
},
{
name: "local StepAction excluded from resolvedDependencies",
obj: objects.NewTaskRunObjectV1(&v1.TaskRun{
Status: v1.TaskRunStatus{
TaskRunStatusFields: v1.TaskRunStatusFields{
Steps: []v1.StepState{
{
Name: "local-step",
ImageID: "gcr.io/test/local@sha256:ccc333",
},
},
},
},
}),
want: []*intoto.ResourceDescriptor{
{
Uri: "oci://gcr.io/test/local",
Digest: common.DigestSet{"sha256": "ccc333"},
},
},
},
{
name: "multiple remote StepActions produce distinct resolvedDependencies",
obj: objects.NewTaskRunObjectV1(&v1.TaskRun{
Status: v1.TaskRunStatus{
TaskRunStatusFields: v1.TaskRunStatusFields{
Steps: []v1.StepState{
{
Name: "git-clone",
ImageID: "gcr.io/test/git@sha256:aaa111",
Provenance: &v1.Provenance{
RefSource: &v1.RefSource{
URI: "git+https://github.com/tektoncd/stepactions",
Digest: map[string]string{"sha256": "step1digest"},
},
},
},
{
Name: "build",
ImageID: "gcr.io/test/build@sha256:bbb222",
Provenance: &v1.Provenance{
RefSource: &v1.RefSource{
URI: "git+https://github.com/tektoncd/stepactions",
Digest: map[string]string{"sha256": "step2digest"},
},
},
},
{
Name: "local-lint",
ImageID: "gcr.io/test/lint@sha256:ccc333",
},
},
},
},
}),
want: []*intoto.ResourceDescriptor{
{
Uri: "oci://gcr.io/test/git",
Digest: common.DigestSet{"sha256": "aaa111"},
},
{
Uri: "oci://gcr.io/test/build",
Digest: common.DigestSet{"sha256": "bbb222"},
},
{
Uri: "oci://gcr.io/test/lint",
Digest: common.DigestSet{"sha256": "ccc333"},
},
{
Name: "stepAction/git-clone",
Uri: "git+https://github.com/tektoncd/stepactions",
Digest: common.DigestSet{"sha256": "step1digest"},
},
{
Name: "stepAction/build",
Uri: "git+https://github.com/tektoncd/stepactions",
Digest: common.DigestSet{"sha256": "step2digest"},
},
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
Expand Down
20 changes: 20 additions & 0 deletions pkg/chains/objects/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ type Result struct {
Value v1.ParamValue
}

// StepProvenance associates a step name with its remote StepAction provenanance
type StepProvenance struct {
StepName string
Provenance *v1.Provenance
}

// Tekton object is an extended Kubernetes object with operations specific
// to Tekton objects.
type TektonObject interface {
Expand Down Expand Up @@ -172,6 +178,20 @@ func (tro *TaskRunObjectV1) GetStepResults() []Result {
return res
}

// GetRemoteStepActions returns the provenance of each step that used a remotely resolved StepAction.
func (tro *TaskRunObjectV1) GetRemoteStepActions() []StepProvenance {
var remoteSteps []StepProvenance
for _, step := range tro.Status.Steps {
if step.Provenance != nil && step.Provenance.RefSource != nil {
remoteSteps = append(remoteSteps, StepProvenance{
StepName: step.Name,
Provenance: step.Provenance,
})
}
}
return remoteSteps
}

func (tro *TaskRunObjectV1) GetStepImages() []string {
images := []string{}
for _, stepState := range tro.Status.Steps {
Expand Down
50 changes: 50 additions & 0 deletions pkg/chains/objects/objects_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,56 @@ func TestTaskRun_GetResults(t *testing.T) {

}

func TestTaskRun_GetRemoteStepActions(t *testing.T) {
t.Run("returns remote StepActions only", func(t *testing.T) {
tr := NewTaskRunObjectV1(&v1.TaskRun{
Status: v1.TaskRunStatus{
TaskRunStatusFields: v1.TaskRunStatusFields{
Steps: []v1.StepState{
{
Name: "remote-step",
ImageID: "gcr.io/test/image@sha256:abc",
Provenance: &v1.Provenance{
RefSource: &v1.RefSource{
URI: "git+https://github.com/tektoncd/stepactions",
Digest: map[string]string{"sha256": "def456"},
},
},
},
{
Name: "local-step",
ImageID: "gcr.io/test/local@sha256:789",
},
},
},
},
})
got := tr.GetRemoteStepActions()
want := []StepProvenance{
{
StepName: "remote-step",
Provenance: &v1.Provenance{
RefSource: &v1.RefSource{
URI: "git+https://github.com/tektoncd/stepactions",
Digest: map[string]string{"sha256": "def456"},
},
},
},
}
if d := cmp.Diff(want, got); d != "" {
t.Fatalf("GetRemoteStepActions (-want, +got):\n%s", d)
}
})

t.Run("returns empty when no remote StepActions", func(t *testing.T) {
tr := NewTaskRunObjectV1(getTaskRun())
got := tr.GetRemoteStepActions()
if len(got) != 0 {
t.Fatalf("expected empty slice, got %v", got)
}
})
}

func TestPipelineRun_GetGVK(t *testing.T) {
assert.Equal(t, "tekton.dev/v1/PipelineRun", NewPipelineRunObjectV1(getPipelineRun()).GetGVK())
}
Expand Down
Loading