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

support generating an additional SBOM file based on CycloneDX format #2808

Closed
2 tasks done
developer-guy opened this issue Jan 5, 2022 · 22 comments
Closed
2 tasks done
Assignees
Labels
enhancement New feature or request

Comments

@developer-guy
Copy link
Member

developer-guy commented Jan 5, 2022

Is your feature request related to a problem? Please describe.

No, it is not related to a problem.

Describe the solution you'd like

We have many tools that can allow us to generate an SBOM file based on CycloneDX format. So, let's add that support to GoReleaser. IMHO, when people specify command cyclonedx-gomod instead of syft, we can use that command to add arguments for it as we did for syft in line#55.

There is also a GitHub Action to download that tool that can help us quickly download and use it with the support that we think to add to GoReleaser.

👉 https://github.com/CycloneDX/gh-gomod-generate-sbom

Describe alternatives you've considered

Alternatively, Syft can generate CycloneDX format-based SBOM files, so, we can create an additional flag which we can accept a type of SBOM according to that we can override the --output argument of the Syft tool to let it generate a CycloneDX format based SBOM file.

Search

  • I did search for other open and closed issues before opening this.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Additional context

Please feel free to assign it to me @caarlos0. I'm willing to work on it 🙋🏻‍♂️

@developer-guy developer-guy added enhancement New feature or request triage Issue pending triage by one of the maintainers labels Jan 5, 2022
@dirien
Copy link
Contributor

dirien commented Jan 5, 2022

Sounds good!

@jonasagx
Copy link

jonasagx commented Jan 5, 2022

On alternatives:
Syft, as of v0.34.0, supports the following flags for output: json, text, table, cyclonedx (for xml), cyclonedx-json, spdx-tag-value, spdx-json.

There is also a Syft-based GitHub action to generate SBOMs https://github.com/marketplace/actions/anchore-sbom-action

@VinodAnandan
Copy link

Thank you @developer-guy , when I created the issue with the SBOM generation proposal ( #2597 ), it was primarily focused around CycloneDX SBOM support and the initial implementation from @caarlos0 ( #2618 ) was using CycloneDX official tools. But the final implementation is not compatible with CycloneDX, even when I tried to invoke cyclonedx-gomod as cmd, it wasn't working.

sboms:
  - id: cdx
    documents:
      - "${artifact}.cdx.sbom"
    artifacts: binary
    cmd: cyclonedx-gomod
    args: ["bin", "-version", "{{ .Tag }}", "-json", "-output", "$document", "$artifact"]

IMO, the cyclonedx-gomod "app" mode ( https://github.com/CycloneDX/cyclonedx-gomod#subcommands ) generates the best CycloneDX SBOM. It will help to have all the build information as well as the dependency graph in the SBOM.

@caarlos0
Copy link
Member

caarlos0 commented Jan 6, 2022

@VinodAnandan what do you mean don't work? what happens?

@VinodAnandan
Copy link

It is not generating a CycloneDX SBOM.

@wagoodman
Copy link
Contributor

wagoodman commented Jan 6, 2022

It seems to be related to #2798 which changes behavior for artifacts: binary. With the sample config:

builds:
  - binary: app
    env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
    goarch:
      - amd64
    mod_timestamp: '{{ .CommitTimestamp }}'
    ldflags: |
      -w
      -s
      -extldflags '-static'

archives:
  - format: tar.gz

sboms:
  - documents:
      - "${artifact}.cdx.sbom"
    artifacts: binary
    cmd: cyclonedx-gomod
    args: ["bin", "-version", "{{ .Tag }}", "-json", "-output", "$document", "$artifact"]

The artifact types seen when observing the catalogTask call are:

  • dist/app_darwin_amd64/app: Binary
  • dist/app_linux_amd64/app: Binary
  • dist/app_windows_amd64/app.exe: Binary
  • dist/app_0.0.0-SNAPSHOT-8bc4d32_darwin_amd64.tar.gz: UploadableArchive
  • dist/app_0.0.0-SNAPSHOT-8bc4d32_linux_amd64.tar.gz: UploadableArchive
  • dist/app_0.0.0-SNAPSHOT-8bc4d32_windows_amd64.tar.gz: UploadableArchive

Which means that the catalogTask function with the changes in #2798 will not include the binary.

@wagoodman
Copy link
Contributor

wagoodman commented Jan 6, 2022

Digging a little deeper, after allowing Binary type back in the SBOM Pipe, it looks like there is a problem with evaluating the ${artifact} variable --this looks to be an issue from my original PR in how the catalogArtifact function deals with templating the artifact path and ensuring that it is always within the dist directory.

Once both of these issues are fixed it looks like this would be cleared up. A workaround for the second problem would be to change the document template:

sboms:
  - documents:
      - "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.cdx.sbom"
    artifacts: binary
    cmd: cyclonedx-gomod
    args: ["bin", "-version", "{{ .Tag }}", "-json", "-output", "$document", "$artifact"]

(the first problem still would need to get fixed to try this out)

@caarlos0
Copy link
Member

caarlos0 commented Jan 6, 2022

It seems to be related to #2798 which changes behavior for artifacts: binary. With the sample config:

problem with leaving binary there is: if the user uses archives[0].format: binary, it'll have duplicated sboms.

Also its a bit weird that the sbom is for a binary but the release has only archives, imho.

doesn't cyclonedx-gomod needs to run within the context of a go.mod file? maybe that's part of the issue?

@wagoodman
Copy link
Contributor

problem with leaving binary there is: if the user uses archives[0].format: binary, it'll have duplicated sboms.

is this what the definition of an UploadableBinary type is? If so, maybe we can write a filter function that deduplicates Binary artifacts based on the existence of UploadableBinary artifacts?

@nscuro
Copy link

nscuro commented Jan 6, 2022

doesn't cyclonedx-gomod needs to run within the context of a go.mod file?

No, not in this case. The bin command expects a binary. It uses go version -m under the hood. See https://github.com/CycloneDX/cyclonedx-gomod#bin. In general, cdx-gomod is a tool specific to Go module projects. It doesn't deal with archives, containers, or other files outside Go modules and their binaries itself.

Also its a bit weird that the sbom is for a binary but the release has only archives, imho.

Agreed, but it's also weird to request binary and get an archive instead.

@VinodAnandan
Copy link

VinodAnandan commented Jan 6, 2022

@caarlos0 , the cyclonedx-gomod supports multiple subcommands ( app, bin, mod, etc. ) which helps to generate SBOMs for different use cases. More information can be found below.

"- SBOMs generated with "app" include only those modules that the target application
  actually depends on. Modules required by tests or packages that are not imported
  by the application are not included. Build constraints are evaluated, which enables
  a very detailed view of what's really compiled into an application's binary.
  
- SBOMs generated with "mod" include the aggregate of modules required by all 
  packages in the target module. This optionally includes modules required by
  tests and test packages. Build constraints are NOT evaluated, allowing for 
  a "whole picture" view on the target module's dependencies.

- "bin" offers support of generating rudimentary SBOMs from binaries built with Go modules.
"

Source: https://github.com/CycloneDX/cyclonedx-gomod#usage .

I prefer the app mode/subcommand as it can capture the build constraints and dependency graph information and it helps to produce accurate SBOMs. But with the current SBOM implementation, I couldn't figure out how to generate the SBOM with the app mode/build time. That is why I tried the bin command instead, which generates SBOM from binaries built with Go modules. The bin command utilises the "go version -m" under the hood and it may not be best for binaries that don't have this information.

Thank @wagoodman . I appreciate your help. With the current SBOM implementation, I couldn't figure out how to generate the SBOM during the build phase. Could you please help with the generation of CycloneDX SBOM during the build time ("app" subcommand/mode https://github.com/CycloneDX/cyclonedx-gomod#app )

@caarlos0
Copy link
Member

caarlos0 commented Jan 6, 2022

is this what the definition of an UploadableBinary type is?

yeah, maybe we should rename it... but basically:

  • if archives[*].format is binary, you'll get an UploadableBinary
  • otherwise, and UploadableArchive

@caarlos0
Copy link
Member

caarlos0 commented Jan 6, 2022

The bin command utilises the "go version -m" under the hood and it may not be best for binaries that don't have this information.

on goreleaser, if you enable the gomod.proxy setting it will have the info 🙏

@caarlos0
Copy link
Member

caarlos0 commented Jan 6, 2022

Agreed, but it's also weird to request binary and get an archive instead.

you shouldn't get archives when selecting binary... what might happen is getting nothing depending on your archive config

@VinodAnandan
Copy link

@caarlos0 How can we have the "go version -m" information for a universal binary? Is there any other config other than gomod.proxy?

IMO, we should prioritise the SBOM during the build phase ("cyclonedx-gomod app") over the pre-build or post-build ones. The build time can contain the most accurate and authentic data along with the build flags/attributes for an SBOM.

@caarlos0
Copy link
Member

caarlos0 commented Jan 6, 2022

How can we have the "go version -m" information for a universal binary?

I think its not possible, as the binary format is not recognized by go version

@wagoodman
Copy link
Contributor

wagoodman commented Jan 19, 2022

I've opened a PR that addresses some of the asks here #2839

@VinodAnandan I missed your earlier ask about getting app to work. As I understand it cyclonedx-gomod works by looking at a source directory, in which case there are a couple options:

  1. if you want to use the source directory that goreleaser is referencing:
sboms:
  - documents:
      - "{{ .ProjectName }}.cdx.sbom"
    artifacts: any
    cmd: cyclonedx-gomod
    args: ["app", "-json", "-output", "$document", "$PWD"]

This works by using artifacts: any, letting the SBOM tool make all of the decisions about what to catalog and how many SBOMs to generate. What's missing is any go-specific variables (GOOS, GOARCH, etc).

  1. if you want to reference the source that goreleaser has archived.
sboms:
  - documents:
      - "{{ .ProjectName }}.cdx.sbom"
    artifacts: source
    cmd: cyclonedx-gomod
    args: ["app",  "-json", "-output", "$document", "$artifact"]

I realize that cyclonedx-gomod does not support archives right now, but I wanted to point out an alternative in case it does one day support this.

The PR description references a 3rd more preferred approach since cyclonedx-gomod sits closer to the build process.

@VinodAnandan
Copy link

Thank you, @wagoodman . You are awesome as always :). I can't wait for the SBOM generated during the build process, I think it will contain the most accurate and authentic data. It will be nice to capture the build constraints as well.

@caarlos0 caarlos0 removed the triage Issue pending triage by one of the maintainers label Jan 31, 2022
@caarlos0
Copy link
Member

I think this should be fixed, correct?

@wagoodman
Copy link
Contributor

I think so 🙌 what's your take @VinodAnandan and @developer-guy ?

@caarlos0
Copy link
Member

nice, will close, please reopen/ping if needed 🙏

thanks everyone :)

@VinodAnandan
Copy link

@wagoodman sorry for the late reply, it is fixed !! thanks a lot for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants