Skip to content

Commit

Permalink
Remove unsupported tekton-provenance storage in config (#594)
Browse files Browse the repository at this point in the history
tekton-provenance storage option is not supported anymore.

Signed-off-by: Chuang Wang <chuangw@google.com>

Signed-off-by: Chuang Wang <chuangw@google.com>
  • Loading branch information
chuangw6 committed Oct 20, 2022
1 parent 3895211 commit 0bf0171
Show file tree
Hide file tree
Showing 11 changed files with 760 additions and 325 deletions.
26 changes: 24 additions & 2 deletions pkg/chains/formats/intotoite6/extract/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package extract

import (
"fmt"
"sort"
"strings"

Expand All @@ -30,8 +31,13 @@ import (
"go.uber.org/zap"
)

// SubjectDigests extracts OCI images and other structured results from the TaskRun and PipelineRun based on standard hinting set up
// It also goes through looking for any PipelineResources of Image type
// SubjectDigests returns software artifacts produced from the TaskRun/PipelineRun object
// in the form of standard subject field of intoto statement.
// The type hinting fields expected in results help identify the generated software artifacts.
// Valid type hinting fields must:
// - have suffix `IMAGE_URL` & `IMAGE_DIGEST` or `ARTIFACT_URI` & `ARTIFACT_DIGEST` pair.
// - the `*_DIGEST` field must be in the format of "<algorithm>:<actual-sha>" where the algorithm must be "sha256" and actual sha must be valid per https://github.com/opencontainers/image-spec/blob/main/descriptor.md#sha-256.
// - the `*_URL` or `*_URI` fields cannot be empty.
func SubjectDigests(obj objects.TektonObject, logger *zap.SugaredLogger) []intoto.Subject {
var subjects []intoto.Subject

Expand Down Expand Up @@ -118,3 +124,19 @@ func SubjectDigests(obj objects.TektonObject, logger *zap.SugaredLogger) []intot
})
return subjects
}

// RetrieveAllArtifactURIs returns all the URIs of the software artifacts produced from the run object.
// - It first extracts intoto subjects from run object results and converts the subjects
// to a slice of string URIs in the format of "NAME" + "@" + "ALGORITHM" + ":" + "DIGEST".
// - If no subjects could be extracted from results, then an empty slice is returned.
func RetrieveAllArtifactURIs(obj objects.TektonObject, logger *zap.SugaredLogger) []string {
result := []string{}
subjects := SubjectDigests(obj, logger)

for _, s := range subjects {
for algo, digest := range s.Digest {
result = append(result, fmt.Sprintf("%s@%s:%s", s.Name, algo, digest))
}
}
return result
}
165 changes: 165 additions & 0 deletions pkg/chains/formats/intotoite6/extract/extract_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
Copyright 2022 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package extract_test

import (
"fmt"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/tektoncd/chains/pkg/chains/formats/intotoite6/extract"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
logtesting "knative.dev/pkg/logging/testing"
)

const (
artifactURL1 = "gcr.io/test/kaniko-chains1"
artifactDigest1 = "a2e500bebfe16cf12fc56316ba72c645e1d29054541dc1ab6c286197434170a9"
artifactURL2 = "us-central1-maven.pkg.dev/test/java"
artifactDigest2 = "b2e500bebfe16cf12fc56316ba72c645e1d29054541dc1ab6c286197434170a9"
)

func TestSubjectDigests(t *testing.T) {
var tests = []struct {
name string
// a map of url:digest pairs for type hinting results
results map[string]string
wantSubjects []intoto.Subject
wantFullURLs []string
}{
{
name: "valid type hinting result fields",
results: map[string]string{
artifactURL1: "sha256:" + artifactDigest1,
artifactURL2: "sha256:" + artifactDigest2,
},
wantSubjects: []intoto.Subject{
{
Name: artifactURL1,
Digest: map[string]string{
"sha256": artifactDigest1,
},
},
{
Name: artifactURL2,
Digest: map[string]string{
"sha256": artifactDigest2,
},
},
},
wantFullURLs: []string{
fmt.Sprintf("%s@sha256:%s", artifactURL1, artifactDigest1),
fmt.Sprintf("%s@sha256:%s", artifactURL2, artifactDigest2),
},
},
{
name: "invalid/missing digest algorithm name",
results: map[string]string{
artifactURL1: "sha1:" + artifactDigest1,
artifactURL2: artifactDigest2,
},
wantSubjects: nil,
wantFullURLs: []string{},
},
{
name: "invalid digest sha",
results: map[string]string{
artifactURL1: "sha256:a123",
},
wantSubjects: nil,
wantFullURLs: []string{},
},
{
name: "invalid url value",
results: map[string]string{
"": "sha256:" + artifactDigest1,
},
wantSubjects: nil,
wantFullURLs: []string{},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
// test both taskrun object and pipelinerun object
runObjects := []objects.TektonObject{
createTaskRunObjectWithResults(tc.results),
createPipelineRunObjectWithResults(tc.results),
}

for _, o := range runObjects {
gotSubjects := extract.SubjectDigests(o, logtesting.TestLogger(t))
if diff := cmp.Diff(tc.wantSubjects, gotSubjects, cmpopts.SortSlices(func(x, y intoto.Subject) bool { return x.Name < y.Name })); diff != "" {
t.Errorf("Wrong subjects extracted, diff=%s", diff)
}

gotURIs := extract.RetrieveAllArtifactURIs(o, logtesting.TestLogger(t))
if diff := cmp.Diff(tc.wantFullURLs, gotURIs, cmpopts.SortSlices(func(x, y string) bool { return x < y })); diff != "" {
t.Errorf("Wrong URIs extracted, diff=%s", diff)
}
}

})
}
}

func createTaskRunObjectWithResults(results map[string]string) objects.TektonObject {
trResults := []v1beta1.TaskRunResult{}
prefix := 0
for url, digest := range results {
trResults = append(trResults,
v1beta1.TaskRunResult{Name: fmt.Sprintf("%v_IMAGE_DIGEST", prefix), Value: *v1beta1.NewStructuredValues(digest)},
v1beta1.TaskRunResult{Name: fmt.Sprintf("%v_IMAGE_URL", prefix), Value: *v1beta1.NewStructuredValues(url)},
)
prefix++
}

return objects.NewTaskRunObject(
&v1beta1.TaskRun{
Status: v1beta1.TaskRunStatus{
TaskRunStatusFields: v1beta1.TaskRunStatusFields{
TaskRunResults: trResults,
},
},
},
)
}

func createPipelineRunObjectWithResults(results map[string]string) objects.TektonObject {
prResults := []v1beta1.PipelineRunResult{}
prefix := 0
for url, digest := range results {
prResults = append(prResults,
v1beta1.PipelineRunResult{Name: fmt.Sprintf("%v_IMAGE_DIGEST", prefix), Value: *v1beta1.NewStructuredValues(digest)},
v1beta1.PipelineRunResult{Name: fmt.Sprintf("%v_IMAGE_URL", prefix), Value: *v1beta1.NewStructuredValues(url)},
)
prefix++
}

return objects.NewPipelineRunObject(
&v1beta1.PipelineRun{
Status: v1beta1.PipelineRunStatus{
PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{
PipelineResults: prResults,
},
},
},
)
}
3 changes: 1 addition & 2 deletions pkg/chains/formats/intotoite6/pipelinerun/pipelinerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ limitations under the License.
package pipelinerun

import (
"fmt"
"time"

intoto "github.com/in-toto/in-toto-golang/in_toto"
Expand Down Expand Up @@ -58,7 +57,7 @@ func GenerateAttestation(builderID string, pro *objects.PipelineRunObject, logge
Builder: slsa.ProvenanceBuilder{
ID: builderID,
},
BuildType: fmt.Sprintf("%s/%s", pro.GetGroupVersionKind().GroupVersion().String(), pro.GetGroupVersionKind().Kind),
BuildType: pro.GetGVK(),
Invocation: invocation(pro),
BuildConfig: buildConfig(pro, logger),
Metadata: metadata(pro),
Expand Down
6 changes: 1 addition & 5 deletions pkg/chains/formats/intotoite6/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ limitations under the License.
package taskrun

import (
"fmt"

intoto "github.com/in-toto/in-toto-golang/in_toto"
slsa "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
"github.com/tektoncd/chains/pkg/artifacts"
Expand All @@ -30,8 +28,6 @@ import (
func GenerateAttestation(builderID string, tro *objects.TaskRunObject, logger *zap.SugaredLogger) (interface{}, error) {
subjects := extract.SubjectDigests(tro, logger)

tr := tro.GetObject().(*v1beta1.TaskRun)

att := intoto.ProvenanceStatement{
StatementHeader: intoto.StatementHeader{
Type: intoto.StatementInTotoV01,
Expand All @@ -42,7 +38,7 @@ func GenerateAttestation(builderID string, tro *objects.TaskRunObject, logger *z
Builder: slsa.ProvenanceBuilder{
ID: builderID,
},
BuildType: fmt.Sprintf("%s/%s", tr.GetGroupVersionKind().GroupVersion().String(), tr.GetGroupVersionKind().Kind),
BuildType: tro.GetGVK(),
Invocation: invocation(tro),
BuildConfig: buildConfig(tro),
Metadata: metadata(tro),
Expand Down
25 changes: 13 additions & 12 deletions pkg/chains/objects/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package objects
import (
"context"
"errors"
"fmt"

"github.com/tektoncd/pipeline/pkg/apis/pipeline/pod"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
Expand Down Expand Up @@ -51,7 +52,7 @@ type Result struct {
// to Tekton objects.
type TektonObject interface {
Object
GetKind() string
GetGVK() string
GetObject() interface{}
GetLatestAnnotations(ctx context.Context, clientSet versioned.Interface) (map[string]string, error)
Patch(ctx context.Context, clientSet versioned.Interface, patchBytes []byte) error
Expand All @@ -78,17 +79,17 @@ type TaskRunObject struct {
*v1beta1.TaskRun
}

var _ TektonObject = &TaskRunObject{}

func NewTaskRunObject(tr *v1beta1.TaskRun) *TaskRunObject {
return &TaskRunObject{
tr,
}
}

// Get the TaskRun kind
func (tro *TaskRunObject) GetKind() string {
// TODO: Want to use tro.GetObjectKind().GroupVersionKind().Kind but
// never seems to be populated
return "taskrun"
// Get the TaskRun GroupVersionKind
func (tro *TaskRunObject) GetGVK() string {
return fmt.Sprintf("%s/%s", tro.GetGroupVersionKind().GroupVersion().String(), tro.GetGroupVersionKind().Kind)
}

// Get the latest annotations on the TaskRun
Expand Down Expand Up @@ -135,21 +136,21 @@ func (tro *TaskRunObject) GetPullSecrets() []string {
type PipelineRunObject struct {
// The base PipelineRun
*v1beta1.PipelineRun
// TaskRuns that were apart of this PipelineRun
// taskRuns that were apart of this PipelineRun
taskRuns []*v1beta1.TaskRun
}

var _ TektonObject = &PipelineRunObject{}

func NewPipelineRunObject(pr *v1beta1.PipelineRun) *PipelineRunObject {
return &PipelineRunObject{
PipelineRun: pr,
}
}

// Get the PipelineRun kind
func (pro *PipelineRunObject) GetKind() string {
// TODO: Want to use tro.GetObjectKind().GroupVersionKind().Kind but
// never seems to be populated
return "pipelinerun"
// Get the PipelineRun GroupVersionKind
func (pro *PipelineRunObject) GetGVK() string {
return fmt.Sprintf("%s/%s", pro.GetGroupVersionKind().GroupVersion().String(), pro.GetGroupVersionKind().Kind)
}

// Request the current annotations on the PipelineRun object
Expand Down
4 changes: 2 additions & 2 deletions pkg/chains/signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func (o *ObjectSigner) Sign(ctx context.Context, tektonObj objects.TektonObject)
payloader, ok := o.Formatters[payloadFormat]

if !ok {
logger.Warnf("Format %s configured for %s: %v was not found", payloadFormat, tektonObj.GetKind(), signableType.Type())
logger.Warnf("Format %s configured for %s: %v was not found", payloadFormat, tektonObj.GetGVK(), signableType.Type())
continue
}

Expand All @@ -181,7 +181,7 @@ func (o *ObjectSigner) Sign(ctx context.Context, tektonObj objects.TektonObject)
logger.Error(err)
continue
}
logger.Infof("Created payload of type %s for %s %s/%s", string(payloadFormat), tektonObj.GetKind(), tektonObj.GetNamespace(), tektonObj.GetName())
logger.Infof("Created payload of type %s for %s %s/%s", string(payloadFormat), tektonObj.GetGVK(), tektonObj.GetNamespace(), tektonObj.GetName())

// Sign it!
signerType := signableType.Signer(cfg)
Expand Down
Loading

0 comments on commit 0bf0171

Please sign in to comment.