Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SBOM attestations #730

Closed
wants to merge 3 commits into from
Closed

Conversation

lcarva
Copy link
Contributor

@lcarva lcarva commented Mar 1, 2023

Changes

The idea is a TaskRun produces an unsigned SBOM and pushes it to the OCI registry. The reference to the SBOM is then added to the result IMAGE_SBOM_URL. When Chains sees this result, it downloads the SBOM from the OCI registry, signs it, then adds to the image attestations with an SBOM-specific predicate.

This is also possible when using the IMAGES result, and the corresponding SBOMS result. Both must have the exact number of items.

It's a draft because it's still missing important things like unit tests and documentation. Some of the TODOs also need to be addressed. Looking for early feedback on the overall approach.

This commit teaches Chains to create SBOM attestations based on type hinting results from TaskRuns.

The general idea is that a Task generates the SBOM, then uploads it as a blob to an OCI registry. Chains then downloads the blob and uses it as the payload when creating the SBOM in-toto attestation.

Multiple SBOMs per image are allowed. They may be of different formats.

Submitter Checklist

As the author of this PR, please check off the items in this checklist:

  • Has Docs included if any changes are user facing
  • Has Tests included if any functionality added or changed
  • Follows the commit message standard
  • Meets the Tekton contributor standards (including
    functionality, content, code)
  • Release notes block below has been updated with any user facing changes (API changes, bug fixes, changes requiring upgrade notices or deprecation warnings)
  • Release notes contains the string "action required" if the change requires additional action from users switching to the new release

Release Notes

* Added support for signing SBOMs

@tekton-robot
Copy link

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@tekton-robot tekton-robot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Mar 1, 2023
@lcarva lcarva force-pushed the sbom branch 2 times, most recently from d58b3e6 to 2924f10 Compare March 7, 2023 18:12
@lcarva lcarva force-pushed the sbom branch 2 times, most recently from 38d972f to 61d022a Compare March 8, 2023 18:50
@lcarva lcarva force-pushed the sbom branch 5 times, most recently from 401193c to c8ab778 Compare March 29, 2023 13:58
@tekton-robot tekton-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Mar 29, 2023
@tekton-robot tekton-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 18, 2023
@tekton-robot tekton-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Apr 19, 2023
@lcarva lcarva marked this pull request as ready for review April 19, 2023 20:35
@tekton-robot tekton-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Apr 19, 2023
@tekton-robot
Copy link

The following is the coverage report on the affected files.
Say /test pull-tekton-chains-go-coverage to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/artifacts/signable.go 74.1% 74.7% 0.6
pkg/chains/formats/sbom/sbom.go Do not exist 70.3%
pkg/chains/formats/slsa/v1/intotoite6.go 88.9% 80.0% -8.9
pkg/chains/objects/objects.go 40.5% 51.0% 10.5

@imjasonh
Copy link
Member

(Mostly a drive-by comment, didn't review the code) I love it! If you're interested in getting ko to integrate with this I'd be happy to help in any way I can. ko currently only produces unsigned SBOMs but it'd be great if they got signed by Chains along the way. 👍

@tekton-robot tekton-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 25, 2023
@tekton-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
To complete the pull request process, please ask for approval from chitrangpatel after the PR has been reviewed.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@tekton-robot tekton-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Aug 3, 2023
@lcarva lcarva force-pushed the sbom branch 2 times, most recently from e9676f4 to 59f6a5c Compare August 11, 2023 15:31
@lcarva lcarva changed the title Add support for signing SBOMs Add support for SBOM attestations Aug 11, 2023
@lcarva lcarva marked this pull request as ready for review August 11, 2023 16:08
@tekton-robot tekton-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 11, 2023
@lcarva
Copy link
Contributor Author

lcarva commented Aug 11, 2023

It's been a while. I've re-worked this PR to address the comments and to focus more on SBOM attestations (instead of SBOM attachments). I updated the description to reflect these changes. It is now out of draft.

It also now includes a tutorial, docs/tutorials/signed-sbom.md, which will, obviously, be useful to users, but may also help reviewers.

I think this PR is pretty complete right now, but let me know if there's something missing!

(Apologies for the huge PR. I could not find a reasonable way to break it up.)

@tekton-robot
Copy link

The following is the coverage report on the affected files.
Say /test pull-tekton-chains-go-coverage to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/artifacts/sbom.go Do not exist 77.2%
pkg/artifacts/signable.go 73.8% 70.2% -3.6
pkg/artifacts/structured.go Do not exist 100.0%
pkg/chains/formats/sbom/sbom.go Do not exist 71.9%
pkg/chains/formats/slsa/v1/intotoite6.go 88.9% 72.7% -16.2
pkg/chains/objects/objects.go 66.0% 67.2% 1.2
pkg/chains/signing.go 73.7% 73.8% 0.0
pkg/config/config.go 91.8% 91.5% -0.3
pkg/reconciler/pipelinerun/controller.go 95.0% 95.5% 0.5
pkg/reconciler/taskrun/controller.go 94.1% 94.7% 0.6

This commit teaches Chains to create SBOM attestations based on type
hinting results from TaskRuns.

The general idea is that a Task generates the SBOM, then uploads it as a
blob to an OCI registry. Chains then downloads the blob and uses it as
the payload when creating the SBOM in-toto attestation.

Multiple SBOMs per image are allowed. They may be of different formats.

Signed-off-by: Luiz Carvalho <lucarval@redhat.com>
@tekton-robot
Copy link

The following is the coverage report on the affected files.
Say /test pull-tekton-chains-go-coverage to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/artifacts/sbom.go Do not exist 77.2%
pkg/artifacts/signable.go 73.8% 70.2% -3.6
pkg/artifacts/structured.go Do not exist 100.0%
pkg/chains/formats/sbom/sbom.go Do not exist 71.9%
pkg/chains/formats/slsa/v1/intotoite6.go 88.9% 72.7% -16.2
pkg/chains/objects/objects.go 66.0% 67.2% 1.2
pkg/chains/signing.go 73.7% 73.8% 0.0
pkg/config/config.go 91.8% 91.5% -0.3
pkg/reconciler/pipelinerun/controller.go 95.0% 95.5% 0.5
pkg/reconciler/taskrun/controller.go 94.1% 94.7% 0.6

@chitrangpatel
Copy link
Contributor

Thanks for adding the examples and tutorials. I'm wondering if we might benefit from an e2e test here (our e2e tests are already taking ~45 mins 😅).

@lcarva
Copy link
Contributor Author

lcarva commented Aug 29, 2023

Thanks for adding the examples and tutorials. I'm wondering if we might benefit from an e2e test here (our e2e tests are already taking ~45 mins 😅).

Yeah, for sure! Is this something that should be part of this PR or a follow up? I'm happy with either way. Just trying to not make this PR even harder to review.

@chitrangpatel
Copy link
Contributor

Thanks for adding the examples and tutorials. I'm wondering if we might benefit from an e2e test here (our e2e tests are already taking ~45 mins 😅).

Yeah, for sure! Is this something that should be part of this PR or a follow up? I'm happy with either way. Just trying to not make this PR even harder to review.

I think it can definitely be in a follow up PR.

@@ -33,9 +33,19 @@ The list of images can be separated by commas or by newlines.
value: img1@sha256:digest1, img2@sha256:digest2
```

When processing a `TaskRun`, Chains will parse through the list, then sign and attest each image.
Chains also suports signing SBOMs. If using the `IMAGE_URL` and `IMAGE_DIGEST` combination, the
`TaskRun` can also emit the `IMAGE_SBOM_URL` and the `IMAGE_SBOM_FORMAT` results. The first contains
Copy link
Contributor

@chitrangpatel chitrangpatel Aug 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be in a separate PR but we should probably also add support for Object Results, like we have for Artifact Inputs.

xxxARTIFACTS_SBOM:
    url:...
    format:... 

pkg/artifacts/sbom.go Outdated Show resolved Hide resolved
pkg/artifacts/signable.go Show resolved Hide resolved
pkg/chains/formats/slsa/v1/intotoite6_test.go Outdated Show resolved Hide resolved
@@ -44,6 +45,15 @@ type ObjectSigner struct {
Backends map[string]storage.Backend
SecretPath string
Pipelineclientset versioned.Interface
appContext context.Context
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to attach contexts to the signer like this - this would prevent us from reusing the signer for multiple requests if there's a deadline attached to it. We already plumb through a context with Sign - we should reuse that if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The context here has a different purpose (which is probably a code smell).

The SBOM formater needs access to the OCI registry so it can read the SBOM (consider a private repo). To do this, we need a kube client to initialize the k8schain.

One way to get a kube client is to get it from the context, e.g. kubeclient.Get(ctx). This, however, does not work with the context given to a reconcile iteration - the one ObjectSigner.Sign gets. It only works for the "application" context - the one NewController gets.

Instead of storing the application context, we could store the kube client directly in the ObjectSigner. That might make things more obvious.

@wlynch, wdyt?

pkg/chains/formats/sbom/sbom.go Show resolved Hide resolved
@@ -65,6 +68,7 @@ type TektonObject interface {
SupportsTaskRunArtifact() bool
SupportsPipelineRunArtifact() bool
SupportsOCIArtifact() bool
SupportsSBOMArtifact() bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is following the pattern of existing funcs, but does this make sense to add to the Object interface? 🤔

I don't know if "whether SBOM artifacts are supported" is a property of an Object we want to enforce on all implementations. Should this be broken out into its own interface?

if _, err := name.NewDigest(trimmed); err != nil {
logger.Errorf("error getting digest for SBOM image %s: %v", trimmed, err)
continue
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything until here is completely the same as the above case. Wrap it into a func?

The IMAGES type-hinting result allows a TaskRun to provide a dynamically
sized list of images to be processed by Chains. In the case of SLSA
Provenance, one statement is created which contains in its list of
subjects all the images from the result. This makes sense as these
images do share provenance.

The SBOMS type-hinting result was meant to add support for SBOM when
the IMAGES result is used. However, unlike SLSA Provenance, an SBOM is
usually descriptive of a single image. This means that the order of the
items in the SBOMS result must match the order of the images in the
IMAGES result. This can be problematic.

This commit drops support for the SBOMS type-hinting result, and the
corresponding SBOMS_FORMAT, to avoid confusion. If we want to
re-introduce it, let's make sure that Chains can provide some sort of
assurance regarding the order of the SBOMs matching the order of the
images.

Signed-off-by: Luiz Carvalho <lucarval@redhat.com>
@tekton-robot
Copy link

The following is the coverage report on the affected files.
Say /test pull-tekton-chains-go-coverage to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/artifacts/sbom.go Do not exist 60.9%
pkg/artifacts/signable.go 73.8% 70.2% -3.6
pkg/artifacts/structured.go Do not exist 100.0%
pkg/chains/formats/sbom/sbom.go Do not exist 71.9%
pkg/chains/formats/slsa/v1/intotoite6.go 88.9% 72.7% -16.2
pkg/chains/objects/objects.go 66.0% 67.2% 1.2
pkg/chains/signing.go 73.7% 73.8% 0.0
pkg/config/config.go 91.8% 91.5% -0.3
pkg/reconciler/pipelinerun/controller.go 95.0% 95.5% 0.5
pkg/reconciler/taskrun/controller.go 94.1% 94.7% 0.6

Signed-off-by: Luiz Carvalho <lucarval@redhat.com>
@@ -33,9 +33,18 @@ The list of images can be separated by commas or by newlines.
value: img1@sha256:digest1, img2@sha256:digest2
```

When processing a `TaskRun`, Chains will parse through the list, then sign and attest each image.
Chains also suports signing SBOMs. If using the `IMAGE_URL` and `IMAGE_DIGEST` combination, the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am trying to consolidating type hinting docs in #913. Not sure which PR will be merged first. But this section may be better to live in the new "how to chain with pipeline" doc?

| Key | Description | Supported Values | Default |
| :--- | :--- | :--- | :--- |
| `artifacts.sbom.format` | The statement format to store `SBOM` payloads in. | `in-toto` | `in-toto` |
| `artifacts.sbom.storage` | The storage backend to store `SBOM` payloads in. Multiple backends can be specified with comma-separated list ("oci,tekton"). To disable the `OCI` artifact input an empty string ("").| `tekton`, `oci`, `gcs`, `docdb`, `grafeas` | `oci` |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we support all the storage backend for sbom currently? If not, should we limit this list to what we currently support?

Comment on lines +32 to +40
- name: IMAGE_URL
description: Reference to the image the SBOM will be generated for.
- name: IMAGE_DIGEST
description: Digest of the image the SBOM will be generated for.
- name: IMAGE_SBOM_URL
description: Reference, including digest, to the SBOM blob.
- name: IMAGE_SBOM_FORMAT
description: The SBOM format.
type: string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Chains takes this approach, I am curious if we should work with catalog team to make sure the syft task can produce right results so that chains can sign? https://github.com/tektoncd/catalog/tree/main/task/syft/0.1

@@ -33,9 +33,18 @@ The list of images can be separated by commas or by newlines.
value: img1@sha256:digest1, img2@sha256:digest2
```

When processing a `TaskRun`, Chains will parse through the list, then sign and attest each image.
Chains also suports signing SBOMs. If using the `IMAGE_URL` and `IMAGE_DIGEST` combination, the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chains supports multiple images type hinting by just appending a prefix before IMAGE_URL and IMAGE_DIGEST. Does SBOM generation support this? If so, can we mention this in the doc as well?

"k8s.io/client-go/kubernetes"
)

func GenerateAttestation(ctx context.Context, kc kubernetes.Interface, builderID string, maxBytes int64, sbom *objects.SBOMObject) (interface{}, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this sbom formatter implement the Payloader interface?

Comment on lines +45 to +46
func (b *structuredSignableExtractor) extract(ctx context.Context, obj objects.TektonObject) []StructuredSignable {
logger := logging.FromContext(ctx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great refactor. Thanks Luiz. 2 things

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted the StructuredSignable piece to #924. Hopefully, this will make it easier to also do this for the object param/results.

@tekton-robot
Copy link

@lcarva: PR needs rebase.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@tekton-robot tekton-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Sep 15, 2023
@tekton-robot
Copy link

@lcarva: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-tekton-chains-integration-tests c6069f5 link true /test pull-tekton-chains-integration-tests
pull-tekton-chains-go-coverage c6069f5 link false /test pull-tekton-chains-go-coverage
pull-tekton-chains-unit-tests c6069f5 link true /test pull-tekton-chains-unit-tests
pull-tekton-chains-build-tests c6069f5 link true /test pull-tekton-chains-build-tests

Full PR test history. Your PR dashboard.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@lcarva
Copy link
Contributor Author

lcarva commented Oct 4, 2023

The changes in this PR means that Chains would sign any SBOM mentioned in the results of a TaskRun.

In a system where users are able to run their own Tasks, this can be easily abused. It turns out that that's the use case I was trying to address. Thus, I have been struggling in accepting this is a good approach.

After some further reflection, I'm going to abandon this PR.

I don't plan on removing the branch nor my fork, so if you want to take a shot at this and address the security concerns, you are welcome to do so.

If you're curious, for my particular case, I'm going with an approach that relies on the information from the SLSA Provenance since that's already signed (and generated!) by Chains. A task that produces the sbom will use something like oras to push the SBOM to the registry as an OCI blob and record the digest reference as a Task result. On the verification side, we can assert that the task that produced the SBOM is trusted, fetch the SBOM given the reference, and process it as needed.

@lcarva lcarva closed this Oct 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants