Skip to content

Commit

Permalink
feat: update chain's controllers to use v1 Tekton APIs natively while…
Browse files Browse the repository at this point in the history
… converting to v1beta1 to keep formats backwards compatible
  • Loading branch information
aaron-prindle committed Dec 15, 2023
1 parent 61dd9f2 commit a74698d
Show file tree
Hide file tree
Showing 125 changed files with 9,630 additions and 1,541 deletions.
1 change: 0 additions & 1 deletion .github/workflows/kind-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ jobs:
fail-fast: false # Keep running if one leg fails.
matrix:
pipelines-release:
- v0.41.3 # LTS
- v0.44.4 # LTS
- v0.47.3 # LTS
- v0.50.1 # LTS
Expand Down
2 changes: 1 addition & 1 deletion cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ func main() {
flag.Parse()
ctx := injection.WithNamespaceScope(signals.NewContext(), *namespace)

sharedmain.MainWithContext(ctx, "watcher", taskrun.NewController, pipelinerun.NewController)
sharedmain.MainWithContext(ctx, "watcher", taskrun.NewControllerV1, pipelinerun.NewControllerV1)
}
10 changes: 5 additions & 5 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ Supported keys include:

| Key | Description | Supported Values | Default |
| :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------- | :-------- |
| `artifacts.taskrun.format` | The format to store `TaskRun` payloads in. | `in-toto`, `slsa/v1`, `slsa/v2alpha2` | `in-toto` |
| `artifacts.taskrun.format` | The format to store `TaskRun` payloads in. | `in-toto`, `slsa/v1`, `slsa/v2alpha3` | `in-toto` |
| `artifacts.taskrun.storage` | The storage backend to store `TaskRun` signatures in. Multiple backends can be specified with comma-separated list ("tekton,oci"). To disable the `TaskRun` artifact input an empty string (""). | `tekton`, `oci`, `gcs`, `docdb`, `grafeas` | `tekton` |
| `artifacts.taskrun.signer` | The signature backend to sign `TaskRun` payloads with. | `x509`, `kms` | `x509` |

> NOTE:
>
> - `slsa/v1` is an alias of `in-toto` for backwards compatibility.
> - `slsa/v2alpha2` corresponds to the slsav1.0 spec.
> - `slsa/v2alpha3` corresponds to the slsav1.0 spec.
### PipelineRun Configuration

| Key | Description | Supported Values | Default |
| :--------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------- | :-------- |
| `artifacts.pipelinerun.format` | The format to store `PipelineRun` payloads in. | `in-toto`, `slsa/v1`, `slsa/v2alpha2` | `in-toto` |
| `artifacts.pipelinerun.format` | The format to store `PipelineRun` payloads in. | `in-toto`, `slsa/v1`, `slsa/v2alpha3` | `in-toto` |
| `artifacts.pipelinerun.storage` | The storage backend to store `PipelineRun` signatures in. Multiple backends can be specified with comma-separated list ("tekton,oci"). To disable the `PipelineRun` artifact input an empty string (""). | `tekton`, `oci`, `gcs`, `docdb`, `grafeas` | `tekton` |
| `artifacts.pipelinerun.signer` | The signature backend to sign `PipelineRun` payloads with. | `x509`, `kms` | `x509` |
| `artifacts.pipelinerun.enable-deep-inspection` | This boolean option will configure whether Chains should inspect child taskruns in order to capture inputs/outputs within a pipelinerun. `"false"` means that Chains only checks pipeline level results, whereas `"true"` means Chains inspects both pipeline level and task level results. | `"true"`, `"false"` | `"false"` |
Expand All @@ -43,7 +43,7 @@ Supported keys include:
>
> - For grafeas storage backend, currently we only support Container Analysis. We will make grafeas server address configurabe within a short time.
> - `slsa/v1` is an alias of `in-toto` for backwards compatibility.
> - `slsa/v2alpha2` corresponds to the slsav1.0 spec.
> - `slsa/v2alpha3` corresponds to the slsav1.0 spec.
### OCI Configuration

Expand Down Expand Up @@ -96,7 +96,7 @@ You can read more about Grafeas notes and occurrences [here](https://github.com/
> NOTE:
> Considerations for the builddefinition.buildtype parameter:
>
> - It is only valid for `slsa/v2alpha2` configurations (see TaskRun or PipelineRun configuration).
> - It is only valid for `slsa/v2alpha3` configurations (see TaskRun or PipelineRun configuration).
> - The parameter can take one of two values:
> - `https://tekton.dev/chains/v2/slsa`: This buildType strictly conforms to the slsav1.0 spec.
> - `https://tekton.dev/chains/v2/slsa-tekton`: This buildType also conforms to the slsav1.0 spec, but adds additional informaton specific to Tekton. This information includes the PipelinRun/TaskRun labels and annotations as internalParameters. It also includes capturing each pipeline task in a PipelinRun under resolvedDependencies.
Expand Down
2 changes: 1 addition & 1 deletion docs/slsa-provenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ The following shows the mapping between slsa version and formatter name.

| SLSA Version | Formatter Name |
| ------------ | ---------------------- |
| v1.0 | `slsa/v2alpha2` |
| v1.0 | `slsa/v2alpha3` |
| v0.2 | `slsa/v1` or `in-toto` |

To configure Task-level provenance version
Expand Down
2 changes: 1 addition & 1 deletion examples/kaniko/gcp/kaniko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: kaniko-gcp
Expand Down
2 changes: 1 addition & 1 deletion examples/kaniko/gcp/taskrun.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: kaniko-gcp
Expand Down
2 changes: 1 addition & 1 deletion examples/kaniko/kaniko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: kaniko-chains
Expand Down
2 changes: 1 addition & 1 deletion examples/kaniko/taskrun.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: kaniko-run
Expand Down
2 changes: 1 addition & 1 deletion examples/pipelineruns/pipeline-output-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: image-pipelinerun
Expand Down
2 changes: 1 addition & 1 deletion examples/releases/v0.3.0-build-chains-taskrun.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
generateName: build-chains-
Expand Down
2 changes: 1 addition & 1 deletion examples/taskruns/task-output-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: tekton.dev/v1beta1
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: build-push-run-output-image-test
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/tektoncd/chains

go 1.20
go 1.21

require (
cloud.google.com/go/compute/metadata v0.2.3
Expand Down Expand Up @@ -268,6 +268,7 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jstemmer/go-junit-report v1.0.0 // indirect
github.com/julz/importas v0.1.0 // indirect
github.com/kelseyhightower/envconfig v1.4.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jstemmer/go-junit-report v1.0.0 h1:8X1gzZpR+nVQLAht+L/foqOeX2l9DTZoaIPbEQHxsds=
github.com/jstemmer/go-junit-report v1.0.0/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
Expand Down
119 changes: 65 additions & 54 deletions pkg/artifacts/signable.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ import (
"context"
_ "crypto/sha256" // Recommended by go-digest.
_ "crypto/sha512" // Recommended by go-digest.
"encoding/json"
"fmt"
"regexp"
"strings"

"github.com/google/go-containerregistry/pkg/name"
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
"github.com/opencontainers/go-digest"
"github.com/opentracing/opentracing-go/log"
"github.com/tektoncd/chains/internal/backport"
"github.com/tektoncd/chains/pkg/chains/objects"
"github.com/tektoncd/chains/pkg/config"
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
"k8s.io/apimachinery/pkg/util/sets"
"knative.dev/pkg/logging"
Expand Down Expand Up @@ -65,12 +68,12 @@ type TaskRunArtifact struct{}
var _ Signable = &TaskRunArtifact{}

func (ta *TaskRunArtifact) ShortKey(obj interface{}) string {
tro := obj.(*objects.TaskRunObject)
tro := obj.(*objects.TaskRunObjectV1)
return "taskrun-" + string(tro.UID)
}

func (ta *TaskRunArtifact) FullKey(obj interface{}) string {
tro := obj.(*objects.TaskRunObject)
tro := obj.(*objects.TaskRunObjectV1)
gvk := tro.GetGroupVersionKind()
return fmt.Sprintf("%s-%s-%s-%s", gvk.Group, gvk.Version, gvk.Kind, tro.UID)
}
Expand Down Expand Up @@ -104,12 +107,12 @@ type PipelineRunArtifact struct{}
var _ Signable = &PipelineRunArtifact{}

func (pa *PipelineRunArtifact) ShortKey(obj interface{}) string {
pro := obj.(*objects.PipelineRunObject)
pro := obj.(*objects.PipelineRunObjectV1)
return "pipelinerun-" + string(pro.UID)
}

func (pa *PipelineRunArtifact) FullKey(obj interface{}) string {
pro := obj.(*objects.PipelineRunObject)
pro := obj.(*objects.PipelineRunObjectV1)
gvk := pro.GetGroupVersionKind()
return fmt.Sprintf("%s-%s-%s-%s", gvk.Group, gvk.Version, gvk.Kind, pro.UID)
}
Expand Down Expand Up @@ -149,40 +152,56 @@ type image struct {
}

func (oa *OCIArtifact) ExtractObjects(ctx context.Context, obj objects.TektonObject) []interface{} {
log := logging.FromContext(ctx)
objs := []interface{}{}

// TODO: Not applicable to PipelineRuns, should look into a better way to separate this out
if tr, ok := obj.GetObject().(*v1beta1.TaskRun); ok {
imageResourceNames := map[string]*image{}
if tr.Status.TaskSpec != nil && tr.Status.TaskSpec.Resources != nil {
for _, output := range tr.Status.TaskSpec.Resources.Outputs {
if output.Type == backport.PipelineResourceTypeImage {
imageResourceNames[output.Name] = &image{}
}
if trV1, ok := obj.GetObject().(*v1.TaskRun); ok {
var resources v1beta1.TaskResources //nolint:staticcheck
shouldReplace := false
if serializedResources, ok := trV1.Annotations["tekton.dev/v1beta1-status-taskrunstatusfields-taskspec-resources"]; ok {
if err := json.Unmarshal([]byte(serializedResources), &resources); err == nil {
shouldReplace = true
}
}

for _, rr := range tr.Status.ResourcesResult {
img, ok := imageResourceNames[rr.ResourceName]
if !ok {
continue
}
// We have a result for an image!
if rr.Key == "url" {
img.url = rr.Value
} else if rr.Key == "digest" {
img.digest = rr.Value
var results []v1beta1.RunResult //nolint:staticcheck
if serializedResources, ok := trV1.Annotations["tekton.dev/v1beta1ResourcesResult"]; ok {
if err := json.Unmarshal([]byte(serializedResources), &results); err == nil {
shouldReplace = shouldReplace && true
}
}
trV1Beta1 := &v1beta1.TaskRun{} //nolint:staticcheck
if err := trV1Beta1.ConvertFrom(ctx, trV1); err == nil {
if shouldReplace {
trV1Beta1.Status.TaskSpec.Resources = &resources //nolint:staticcheck
trV1Beta1.Status.ResourcesResult = results //nolint:staticcheck
}
imageResourceNames := map[string]*image{}
if trV1Beta1.Status.TaskSpec != nil && trV1Beta1.Status.TaskSpec.Resources != nil { //nolint:staticcheck
for _, output := range trV1Beta1.Status.TaskSpec.Resources.Outputs { //nolint:staticcheck
if output.Type == backport.PipelineResourceTypeImage {
imageResourceNames[output.Name] = &image{}
}
}
}
for _, rr := range trV1Beta1.Status.ResourcesResult {
img, ok := imageResourceNames[rr.ResourceName]
if !ok {
continue
}
// We have a result for an image!
if rr.Key == "url" {
img.url = rr.Value
} else if rr.Key == "digest" {
img.digest = rr.Value
}
}

for _, image := range imageResourceNames {
dgst, err := name.NewDigest(fmt.Sprintf("%s@%s", image.url, image.digest))
if err != nil {
log.Error(err)
continue
for _, image := range imageResourceNames {
dgst, err := name.NewDigest(fmt.Sprintf("%s@%s", image.url, image.digest))
if err != nil {
log.Error(err)
continue
}
objs = append(objs, dgst)
}
objs = append(objs, dgst)
}
}

Expand All @@ -208,16 +227,15 @@ func ExtractOCIImagesFromResults(ctx context.Context, obj objects.TektonObject)
logger.Errorf("error getting digest: %v", err)
continue
}

objs = append(objs, dgst)
}

// look for a comma separated list of images
for _, key := range obj.GetResults() {
if key.Name != "IMAGES" {
if key.GetName() != "IMAGES" {
continue
}
imgs := strings.FieldsFunc(key.Value.StringVal, split)
imgs := strings.FieldsFunc(key.GetStringValue(), split)

for _, img := range imgs {
trimmed := strings.TrimSpace(img)
Expand Down Expand Up @@ -291,43 +309,36 @@ func ExtractStructuredTargetFromResults(ctx context.Context, obj objects.TektonO
}

// TODO(#592): support structured results using Run
results := []objects.Result{}
for _, res := range obj.GetResults() {
results = append(results, objects.Result{
Name: res.Name,
Value: res.Value,
})
}
for _, res := range results {
if strings.HasSuffix(res.Name, categoryMarker) {
if strings.HasSuffix(res.GetName(), categoryMarker) {
valid, err := isStructuredResult(res, categoryMarker)
if err != nil {
logger.Debugf("ExtractStructuredTargetFromResults: %v", err)
}
if valid {
logger.Debugf("Extracted Structured data from Result %s, %s", res.Value.ObjectVal["uri"], res.Value.ObjectVal["digest"])
objs = append(objs, &StructuredSignable{URI: res.Value.ObjectVal["uri"], Digest: res.Value.ObjectVal["digest"]})
logger.Debugf("Extracted Structured data from Result %v", res)
objs = append(objs, &StructuredSignable{URI: res.GetObjectValue("uri"), Digest: res.GetObjectValue("digest")})
}
}
}
return objs
}

func isStructuredResult(res objects.Result, categoryMarker string) (bool, error) {
if !strings.HasSuffix(res.Name, categoryMarker) {
func isStructuredResult(res objects.GenericResult, categoryMarker string) (bool, error) {
if !strings.HasSuffix(res.GetName(), categoryMarker) {
return false, nil
}
if res.Value.ObjectVal == nil {
return false, fmt.Errorf("%s should be an object: %v", res.Name, res.Value.ObjectVal)
if res.ObjectValueIsNil() {
return false, fmt.Errorf("%s should be an object: %v", res.GetName(), res)
}
if res.Value.ObjectVal["uri"] == "" {
return false, fmt.Errorf("%s should have uri field: %v", res.Name, res.Value.ObjectVal)
if res.GetObjectValue("uri") == "" {
return false, fmt.Errorf("%s should have uri field: %v", res.GetName(), res)
}
if res.Value.ObjectVal["digest"] == "" {
return false, fmt.Errorf("%s should have digest field: %v", res.Name, res.Value.ObjectVal)
if res.GetObjectValue("digest") == "" {
return false, fmt.Errorf("%s should have digest field: %v", res.GetName(), res)
}
if _, _, err := ParseDigest(res.Value.ObjectVal["digest"]); err != nil {
return false, fmt.Errorf("error getting digest %s: %v", res.Value.ObjectVal["digest"], err)
if _, _, err := ParseDigest(res.GetObjectValue("digest")); err != nil {
return false, fmt.Errorf("error getting digest %s: %v", res.GetObjectValue("digest"), err)
}
return true, nil
}
Expand Down
Loading

0 comments on commit a74698d

Please sign in to comment.