Skip to content

Commit

Permalink
Merge branch 'main' into patch-1
Browse files Browse the repository at this point in the history
* main:
  add distroless debug image to published release (anchore#1106)
  update help formatting (anchore#1105)
  feat: implement haskell support (anchore#1096)
  Add the -r argument for gnu xargs (anchore#1103)
  fix: -o output option to include formats (anchore#1102)

Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
  • Loading branch information
spiffcs committed Jul 20, 2022
2 parents 71f7679 + 7bae9d4 commit 9541fdc
Show file tree
Hide file tree
Showing 34 changed files with 1,068 additions and 48 deletions.
93 changes: 53 additions & 40 deletions .goreleaser.yaml
Expand Up @@ -99,16 +99,12 @@ brews:

dockers:
- image_templates:
- "anchore/syft:latest"
- "anchore/syft:{{ .Tag }}-amd64"
- "anchore/syft:v{{ .Major }}-amd64"
- "anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64"
- "ghcr.io/anchore/syft:latest"
- "ghcr.io/anchore/syft:{{ .Tag }}-amd64"
- "ghcr.io/anchore/syft:v{{ .Major }}-amd64"
- "ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64"
- anchore/syft:debug
- anchore/syft:{{.Tag}}-debug
- ghcr.io/anchore/syft:debug
- ghcr.io/anchore/syft:{{.Tag}}-debug
goarch: amd64
dockerfile: Dockerfile
dockerfile: Dockerfile.debug
use: buildx
build_flag_templates:
- "--platform=linux/amd64"
Expand All @@ -118,57 +114,74 @@ dockers:
- "--build-arg=VCS_URL={{.GitURL}}"

- image_templates:
- "anchore/syft:{{ .Tag }}-arm64v8"
- "anchore/syft:v{{ .Major }}-arm64v8"
- "anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8"
- "ghcr.io/anchore/syft:{{ .Tag }}-arm64v8"
- "ghcr.io/anchore/syft:v{{ .Major }}-arm64v8"
- "ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8"
- anchore/syft:debug-arm64v8
- anchore/syft:{{.Tag}}-debug-arm64v8
- ghcr.io/anchore/syft:debug-arm64v8
- ghcr.io/anchore/syft:{{.Tag}}-debug-arm64v8
goarch: arm64
dockerfile: Dockerfile
dockerfile: Dockerfile.debug
use: buildx
build_flag_templates:
- "--platform=linux/arm64/v8"
- "--build-arg=BUILD_DATE={{.Date}}"
- "--build-arg=BUILD_VERSION={{.Version}}"
- "--build-arg=VCS_REF={{.FullCommit}}"
- "--build-arg=VCS_URL={{.GitURL}}"


- image_templates:
- anchore/syft:latest
- anchore/syft:{{.Tag}}
- ghcr.io/anchore/syft:latest
- ghcr.io/anchore/syft:{{.Tag}}
goarch: amd64
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- "--platform=linux/amd64"
- "--build-arg=BUILD_DATE={{.Date}}"
- "--build-arg=BUILD_VERSION={{.Version}}"
- "--build-arg=VCS_REF={{.FullCommit}}"
- "--build-arg=VCS_URL={{.GitURL}}"

- image_templates:
- "anchore/syft:{{ .Tag }}-ppc64le"
- "anchore/syft:v{{ .Major }}-ppc64le"
- "anchore/syft:v{{ .Major }}.{{ .Minor }}-ppc64le"
- "ghcr.io/anchore/syft:{{ .Tag }}-ppc64le"
- "ghcr.io/anchore/syft:v{{ .Major }}-ppc64le"
- "ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-ppc64le"
goarch: ppc64le
- anchore/syft:{{.Tag}}-arm64v8
- ghcr.io/anchore/syft:{{.Tag}}-arm64v8
goarch: arm64
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- "--platform=linux/ppc64le"
- "--platform=linux/arm64/v8"
- "--build-arg=BUILD_DATE={{.Date}}"
- "--build-arg=BUILD_VERSION={{.Version}}"
- "--build-arg=VCS_REF={{.FullCommit}}"
- "--build-arg=VCS_URL={{.GitURL}}"

docker_manifests:
- name_template: anchore/syft:{{ .Tag }}
image_templates:
- anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64
- anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8
- anchore/syft:v{{ .Major }}.{{ .Minor }}-ppc64le
- name_template: anchore/syft:latest
image_templates:
- anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64
- anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8
- anchore/syft:v{{ .Major }}.{{ .Minor }}-ppc64le
- name_template: ghcr.io/anchore/syft:{{ .Tag }}
- anchore/syft:{{.Tag}}
- anchore/syft:{{.Tag}}-arm64v8

- name_template: anchore/syft:debug
- anchore/syft:{{.Tag}}-debug
- anchore/syft:{{.Tag}}-debug-arm64v8

- name_template: anchore/syft:{{.Tag}}
image_templates:
- ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64
- ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8
- ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-ppc64le
- anchore/syft:{{.Tag}}
- anchore/syft:{{.Tag}}-arm64v8

- name_template: ghcr.io/anchore/syft:latest
image_templates:
- ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-amd64
- ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-arm64v8
- ghcr.io/anchore/syft:v{{ .Major }}.{{ .Minor }}-ppc64le
- anchore/syft:{{.Tag}}
- anchore/syft:{{.Tag}}-arm64v8

- name_template: ghcr.io/anchore/syft:debug
image_templates:
- ghcr.io/anchore/syft:{{.Tag}}-debug
- ghcr.io/anchore/syft:{{.Tag}}-debug-arm64v8

- name_template: ghcr.io/anchore/syft:{{.Tag}}
image_templates:
- ghcr.io/anchore/syft:{{.Tag}}
- ghcr.io/anchore/syft:{{.Tag}}-arm64v8
5 changes: 1 addition & 4 deletions Dockerfile
@@ -1,6 +1,4 @@
FROM alpine:latest AS build

RUN apk --no-cache add ca-certificates
FROM gcr.io/distroless/static-debian11:debug AS build

FROM scratch
# needed for version check HTTPS request
Expand All @@ -27,6 +25,5 @@ LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL io.artifacthub.package.readme-url="https://raw.githubusercontent.com/anchore/syft/main/README.md"
LABEL io.artifacthub.package.logo-url="https://user-images.githubusercontent.com/5199289/136844524-1527b09f-c5cb-4aa9-be54-5aa92a6086c1.png"
LABEL io.artifacthub.package.license="Apache-2.0"


ENTRYPOINT ["/syft"]
25 changes: 25 additions & 0 deletions Dockerfile.debug
@@ -0,0 +1,25 @@
FROM gcr.io/distroless/static-debian11:debug

# create the /tmp dir, which is needed for image content cache
WORKDIR /tmp

COPY syft /

ARG BUILD_DATE
ARG BUILD_VERSION
ARG VCS_REF
ARG VCS_URL

LABEL org.opencontainers.image.created=$BUILD_DATE
LABEL org.opencontainers.image.title="syft"
LABEL org.opencontainers.image.description="CLI tool and library for generating a Software Bill of Materials from container images and filesystems"
LABEL org.opencontainers.image.source=$VCS_URL
LABEL org.opencontainers.image.revision=$VCS_REF
LABEL org.opencontainers.image.vendor="Anchore, Inc."
LABEL org.opencontainers.image.version=$BUILD_VERSION
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL io.artifacthub.package.readme-url="https://raw.githubusercontent.com/anchore/syft/main/README.md"
LABEL io.artifacthub.package.logo-url="https://user-images.githubusercontent.com/5199289/136844524-1527b09f-c5cb-4aa9-be54-5aa92a6086c1.png"
LABEL io.artifacthub.package.license="Apache-2.0"

ENTRYPOINT ["/syft"]
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -369,7 +369,7 @@ clean-test-image-tar-cache: ## Delete all test cache (built docker image tars)

.PHONY: clear-test-image-docker-cache
clean-test-image-docker-cache: ## Purge all test docker images
docker images --format '{{.ID}} {{.Repository}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs docker rmi --force
docker images --format '{{.ID}} {{.Repository}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs -r docker rmi --force

.PHONY: show-test-image-cache
show-test-image-cache: ## Show all docker and image tar cache
Expand Down
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -37,6 +37,7 @@ A CLI tool and Go library for generating a Software Bill of Materials (SBOM) fro
- Dotnet (deps.json)
- Objective-C (cocoapods)
- Go (go.mod, Go binaries)
- Haskell (cabal, stack)
- Java (jar, ear, war, par, sar)
- JavaScript (npm, yarn)
- Jenkins Plugins (jpi, hpi)
Expand Down
2 changes: 1 addition & 1 deletion cmd/syft/cli/options/writer.go
Expand Up @@ -53,7 +53,7 @@ func parseOutputs(outputs []string, defaultFile, templateFilePath string) (out [

format := syft.FormatByName(name)
if format == nil {
errs = multierror.Append(errs, fmt.Errorf("bad output format: '%s'", name))
errs = multierror.Append(errs, fmt.Errorf(`unsupported output format "%s", supported formats are: %+v`, name, FormatAliases(syft.FormatIDs()...)))
continue
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/syft/cli/options/writer_test.go
Expand Up @@ -22,7 +22,7 @@ func TestIsSupportedFormat(t *testing.T) {
{
outputs: []string{"unknown"},
wantErr: func(t assert.TestingT, err error, bla ...interface{}) bool {
return assert.ErrorContains(t, err, "bad output format: 'unknown'")
return assert.ErrorContains(t, err, `unsupported output format "unknown", supported formats are: [`)
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/syft/cli/packages.go
Expand Up @@ -13,7 +13,7 @@ import (
)

const (
packagesExample = ` {{.appName}} {{.command}} alpine:latest a summary of discovered packages
packagesExample = ` {{.appName}} {{.command}} alpine:latest a summary of discovered packages
{{.appName}} {{.command}} alpine:latest -o json show all possible cataloging details
{{.appName}} {{.command}} alpine:latest -o cyclonedx show a CycloneDX formatted SBOM
{{.appName}} {{.command}} alpine:latest -o cyclonedx-json show a CycloneDX JSON formatted SBOM
Expand Down
3 changes: 3 additions & 0 deletions internal/formats/common/spdxhelpers/source_info.go
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/anchore/syft/syft/pkg"
)

//nolint:funlen
func SourceInfo(p pkg.Package) string {
answer := ""
switch p.Type {
Expand Down Expand Up @@ -41,6 +42,8 @@ func SourceInfo(p pkg.Package) string {
answer = "acquired package info from conan manifest"
case pkg.PortagePkg:
answer = "acquired package info from portage DB"
case pkg.HackagePkg:
answer = "acquired package info from cabal or stack manifest files"
default:
answer = "acquired package info from the following paths"
}
Expand Down
8 changes: 8 additions & 0 deletions internal/formats/common/spdxhelpers/source_info_test.go
Expand Up @@ -174,6 +174,14 @@ func Test_SourceInfo(t *testing.T) {
"from portage DB",
},
},
{
input: pkg.Package{
Type: pkg.HackagePkg,
},
expected: []string{
"from cabal or stack manifest files",
},
},
}
var pkgTypes []pkg.Type
for _, test := range tests {
Expand Down
6 changes: 6 additions & 0 deletions internal/formats/syftjson/model/package.go
Expand Up @@ -169,6 +169,12 @@ func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error {
return err
}
p.Metadata = payload
case pkg.HackageMetadataType:
var payload pkg.HackageMetadata
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
return err
}
p.Metadata = payload
default:
log.Warnf("unknown package metadata type=%q for packageID=%q", p.MetadataType, p.ID)
}
Expand Down
3 changes: 3 additions & 0 deletions syft/pkg/cataloger/cataloger.go
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/anchore/syft/syft/pkg/cataloger/deb"
"github.com/anchore/syft/syft/pkg/cataloger/dotnet"
"github.com/anchore/syft/syft/pkg/cataloger/golang"
"github.com/anchore/syft/syft/pkg/cataloger/haskell"
"github.com/anchore/syft/syft/pkg/cataloger/java"
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
"github.com/anchore/syft/syft/pkg/cataloger/php"
Expand Down Expand Up @@ -82,6 +83,7 @@ func DirectoryCatalogers(cfg Config) []Cataloger {
swift.NewCocoapodsCataloger(),
cpp.NewConanfileCataloger(),
portage.NewPortageCataloger(),
haskell.NewHackageCataloger(),
}, cfg.Catalogers)
}

Expand Down Expand Up @@ -110,6 +112,7 @@ func AllCatalogers(cfg Config) []Cataloger {
swift.NewCocoapodsCataloger(),
cpp.NewConanfileCataloger(),
portage.NewPortageCataloger(),
haskell.NewHackageCataloger(),
}, cfg.Catalogers)
}

Expand Down
15 changes: 15 additions & 0 deletions syft/pkg/cataloger/haskell/cataloger.go
@@ -0,0 +1,15 @@
package haskell

import (
"github.com/anchore/syft/syft/pkg/cataloger/common"
)

// NewHackageCataloger returns a new Haskell cataloger object.
func NewHackageCataloger() *common.GenericCataloger {
globParsers := map[string]common.ParserFn{
"**/stack.yaml": parseStackYaml,
"**/stack.yaml.lock": parseStackLock,
"**/cabal.project.freeze": parseCabalFreeze,
}
return common.NewGenericCataloger(nil, globParsers, "hackage-cataloger")
}
53 changes: 53 additions & 0 deletions syft/pkg/cataloger/haskell/parse_cabal_freeze.go
@@ -0,0 +1,53 @@
package haskell

import (
"bufio"
"errors"
"fmt"
"io"
"strings"

"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/common"
)

// integrity check
var _ common.ParserFn = parseCabalFreeze

// parseCabalFreeze is a parser function for cabal.project.freeze contents, returning all packages discovered.
func parseCabalFreeze(_ string, reader io.Reader) ([]*pkg.Package, []artifact.Relationship, error) {
r := bufio.NewReader(reader)
pkgs := []*pkg.Package{}
for {
line, err := r.ReadString('\n')
switch {
case errors.Is(io.EOF, err):
return pkgs, nil, nil
case err != nil:
return nil, nil, fmt.Errorf("failed to parse cabal.project.freeze file: %w", err)
}

if !strings.Contains(line, "any.") {
continue
}

line = strings.TrimSpace(line)
startPkgEncoding, endPkgEncoding := strings.Index(line, "any.")+4, strings.Index(line, ",")
line = line[startPkgEncoding:endPkgEncoding]
splits := strings.Split(line, " ==")

pkgName, pkgVersion := splits[0], splits[1]
pkgs = append(pkgs, &pkg.Package{
Name: pkgName,
Version: pkgVersion,
Language: pkg.Haskell,
Type: pkg.HackagePkg,
MetadataType: pkg.HackageMetadataType,
Metadata: pkg.HackageMetadata{
Name: pkgName,
Version: pkgVersion,
},
})
}
}

0 comments on commit 9541fdc

Please sign in to comment.