Skip to content

Commit

Permalink
Merge pull request #1575 from rsteube/add-syft
Browse files Browse the repository at this point in the history
added syft
  • Loading branch information
rsteube authored Mar 19, 2023
2 parents d539fd1 + 81379bd commit 79f5efc
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 0 deletions.
25 changes: 25 additions & 0 deletions completers/syft_completer/cmd/attest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/syft"
"github.com/spf13/cobra"
)

var attestCmd = &cobra.Command{
Use: "attest --output [FORMAT] <IMAGE>",
Short: "Generate an SBOM as an attestation for the given [SOURCE] container image",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(attestCmd).Standalone()
attestCmd.Flags().StringP("key", "k", "", "the key to use for the attestation")
addCommonFlags(attestCmd)

rootCmd.AddCommand(attestCmd)

carapace.Gen(attestCmd).PositionalCompletion(
syft.ActionSources(),
)
}
22 changes: 22 additions & 0 deletions completers/syft_completer/cmd/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var convertCmd = &cobra.Command{
Use: "convert [SOURCE-SBOM] -o [FORMAT]",
Short: "Convert between SBOM formats",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(convertCmd).Standalone()
addCommonFlags(convertCmd)
rootCmd.AddCommand(convertCmd)

carapace.Gen(convertCmd).PositionalCompletion(
carapace.ActionFiles(),
)
}
21 changes: 21 additions & 0 deletions completers/syft_completer/cmd/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var loginCmd = &cobra.Command{
Use: "login [OPTIONS] [SERVER]",
Short: "Log in to a registry",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(loginCmd).Standalone()

loginCmd.Flags().StringP("password", "p", "", "Password")
loginCmd.Flags().Bool("password-stdin", false, "Take the password from stdin")
loginCmd.Flags().StringP("username", "u", "", "Username")
rootCmd.AddCommand(loginCmd)
}
23 changes: 23 additions & 0 deletions completers/syft_completer/cmd/packages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/syft"
"github.com/spf13/cobra"
)

var packagesCmd = &cobra.Command{
Use: "packages [SOURCE]",
Short: "Generate a package SBOM",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(packagesCmd).Standalone()
addCommonFlags(packagesCmd)
rootCmd.AddCommand(packagesCmd)

carapace.Gen(packagesCmd).PositionalCompletion(
syft.ActionSources(),
)
}
65 changes: 65 additions & 0 deletions completers/syft_completer/cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/syft"
"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
Use: "syft",
Short: "Generate a package SBOM",
Long: "https://github.com/anchore/syft",
Run: func(cmd *cobra.Command, args []string) {},
}

func Execute() error {
return rootCmd.Execute()
}

func init() {
carapace.Gen(rootCmd).Standalone()

rootCmd.PersistentFlags().StringP("config", "c", "", "application config file")
rootCmd.PersistentFlags().BoolP("quiet", "q", false, "suppress all logging output")
rootCmd.PersistentFlags().CountP("verbose", "v", "increase verbosity (-v = info, -vv = debug)")
addCommonFlags(rootCmd)

// TODO platform, catalogers
carapace.Gen(rootCmd).FlagCompletion(carapace.ActionMap{
"config": carapace.ActionFiles(),
})

carapace.Gen(rootCmd).PositionalCompletion(
syft.ActionSources(),
)
}

func addCommonFlags(cmd *cobra.Command) {
cmd.Flags().StringArray("catalogers", []string{}, "enable one or more package catalogers")
cmd.Flags().StringArray("exclude", []string{}, "exclude paths from being scanned using a glob expression")
cmd.Flags().String("file", "", "file to write the default report output to (default is STDOUT)")
cmd.Flags().String("name", "", "set the name of the target being analyzed")
cmd.Flags().StringArrayP("output", "o", []string{"syft-table"}, "report output format, options=[syft-json cyclonedx-xml cyclonedx-json github-json spdx-tag-value spdx-json syft-table syft-text template]")
cmd.Flags().String("platform", "", "an optional platform specifier for container image sources (e.g. 'linux/arm64', 'linux/arm64/v8', 'arm64', 'linux')")
cmd.Flags().StringP("scope", "s", "Squashed", "selection of layers to catalog, options=[Squashed AllLayers]")
cmd.Flags().StringP("template", "t", "", "specify the path to a Go template file")

carapace.Gen(cmd).FlagCompletion(carapace.ActionMap{
"file": carapace.ActionFiles(),
"output": carapace.ActionMultiParts("=", func(c carapace.Context) carapace.Action {
switch len(c.Parts) {
case 0:
return syft.ActionOutputFormats()

case 1:
return carapace.ActionFiles()

default:
return carapace.ActionValues()
}
}),
"scope": carapace.ActionValues("Squashed", "AllLayers"),
"template": carapace.ActionFiles(),
})
}
23 changes: 23 additions & 0 deletions completers/syft_completer/cmd/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cmd

import (
"github.com/rsteube/carapace"
"github.com/spf13/cobra"
)

var versionCmd = &cobra.Command{
Use: "version",
Short: "show the version",
Run: func(cmd *cobra.Command, args []string) {},
}

func init() {
carapace.Gen(versionCmd).Standalone()

versionCmd.Flags().StringP("output", "o", "text", "format to show version information")
rootCmd.AddCommand(versionCmd)

carapace.Gen(versionCmd).FlagCompletion(carapace.ActionMap{
"output": carapace.ActionValues("text", "json"),
})
}
7 changes: 7 additions & 0 deletions completers/syft_completer/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "github.com/rsteube/carapace-bin/completers/syft_completer/cmd"

func main() {
cmd.Execute()
}
21 changes: 21 additions & 0 deletions pkg/actions/tools/syft/format.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package syft

import "github.com/rsteube/carapace"

// ActionOutputFormats completes output formats
//
// syft-json
// template
func ActionOutputFormats() carapace.Action {
return carapace.ActionValues(
"syft-json",
"cyclonedx-xml",
"cyclonedx-json",
"github-json",
"spdx-tag-value",
"spdx-json",
"syft-table",
"syft-text",
"template",
)
}
63 changes: 63 additions & 0 deletions pkg/actions/tools/syft/source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package syft

import (
"strings"

"github.com/rsteube/carapace"
"github.com/rsteube/carapace-bin/pkg/actions/tools/docker"
"github.com/rsteube/carapace-bin/pkg/util"
)

// ActionSources completes sources
//
// ./local/file
// alpine:3.6
func ActionSources() carapace.Action {
return carapace.Batch(
carapace.ActionCallback(func(c carapace.Context) carapace.Action {
if util.HasPathPrefix(c.CallbackValue) {
return carapace.ActionFiles()
}
return docker.ActionRepositoryTags()
}),
carapace.ActionCallback(func(c carapace.Context) carapace.Action {
splitted := strings.SplitN(c.CallbackValue, ":", 2)
switch len(splitted) {
case 1:
return carapace.ActionValuesDescribed(
"docker", "use images from the Docker daemon",
"podman", "use images from the Podman daemon",
"docker-archive", "use a tarball from disk for archives created from \"docker save\"",
"oci-archive", "use a tarball from disk for OCI archives (from Skopeo or otherwise)",
"oci-dir", "read directly from a path on disk for OCI layout directories (from Skopeo or otherwise)",
"singularity", "read directly from a Singularity Image Format (SIF) container on disk",
"dir", "read directly from a path on disk (any directory)",
"file", "read directly from a path on disk (any single file)",
"registry", "pull image directly from a registry (no container runtime required)",
).Suffix(":").Tag("sources")
case 2:
prefix := splitted[0] + ":"
c.CallbackValue = strings.TrimPrefix(c.CallbackValue, prefix)
return carapace.ActionCallback(func(c carapace.Context) carapace.Action {
// TODO podman, registry
switch splitted[0] {
case "docker":
return docker.ActionRepositoryTags()

case "docker-archive", "oci-archive", "singularity", "file":
return carapace.ActionFiles()

case "oci-dir", "dir":
return carapace.ActionDirectories()

default:
return carapace.ActionValues()
}
}).Invoke(c).Prefix(prefix).ToA()

default:
return carapace.ActionValues()
}
}),
).ToA()
}

0 comments on commit 79f5efc

Please sign in to comment.