mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 02:26:42 +01:00
1465 attestation with private key (#1502)
1465 attestation with private key (#1502) Signed-off-by: Christopher Phillips <christopher.phillips@anchore.com>
This commit is contained in:
parent
4c0aef09b8
commit
8c91605541
@ -20,8 +20,7 @@ const (
|
|||||||
attestHelp = attestExample + attestSchemeHelp
|
attestHelp = attestExample + attestSchemeHelp
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:dupl
|
func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions, ao *options.AttestOptions) *cobra.Command {
|
||||||
func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions, po *options.PackagesOptions) *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "attest --output [FORMAT] <IMAGE>",
|
Use: "attest --output [FORMAT] <IMAGE>",
|
||||||
Short: "Generate an SBOM as an attestation for the given [SOURCE] container image",
|
Short: "Generate an SBOM as an attestation for the given [SOURCE] container image",
|
||||||
@ -50,11 +49,17 @@ func Attest(v *viper.Viper, app *config.Application, ro *options.RootOptions, po
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// syft attest is an enhancment of the packages command, so it should have the same flags
|
// syft attest is an enhancement of the packages command, so it should have the same flags
|
||||||
err := po.AddFlags(cmd, v)
|
err := po.AddFlags(cmd, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// syft attest has its own options not included as part of the packages command
|
||||||
|
err = ao.AddFlags(cmd, v)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,6 +97,7 @@ func buildSBOM(app *config.Application, si source.Input, writer sbom.Writer, err
|
|||||||
return sBytes, nil
|
return sBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:funlen
|
||||||
func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-chan error {
|
func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-chan error {
|
||||||
errs := make(chan error)
|
errs := make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
@ -131,9 +132,18 @@ func execWorker(app *config.Application, si source.Input, writer sbom.Writer) <-
|
|||||||
}
|
}
|
||||||
|
|
||||||
args := []string{"attest", si.UserInput, "--type", "custom", "--predicate", f.Name()}
|
args := []string{"attest", si.UserInput, "--type", "custom", "--predicate", f.Name()}
|
||||||
|
if app.Attest.Key != "" {
|
||||||
|
args = append(args, "--key", app.Attest.Key)
|
||||||
|
}
|
||||||
|
|
||||||
execCmd := exec.Command(cmd, args...)
|
execCmd := exec.Command(cmd, args...)
|
||||||
execCmd.Env = os.Environ()
|
execCmd.Env = os.Environ()
|
||||||
|
if app.Attest.Key != "" {
|
||||||
|
execCmd.Env = append(execCmd.Env, fmt.Sprintf("COSIGN_PASSWORD=%s", app.Attest.Password))
|
||||||
|
} else {
|
||||||
|
// no key provided, use cosign's keyless mode
|
||||||
execCmd.Env = append(execCmd.Env, "COSIGN_EXPERIMENTAL=1")
|
execCmd.Env = append(execCmd.Env, "COSIGN_EXPERIMENTAL=1")
|
||||||
|
}
|
||||||
|
|
||||||
// bus adapter for ui to hook into stdout via an os pipe
|
// bus adapter for ui to hook into stdout via an os pipe
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
|
|||||||
@ -45,12 +45,13 @@ func New() (*cobra.Command, error) {
|
|||||||
// we also need the command to have information about the `root` options because of this alias
|
// we also need the command to have information about the `root` options because of this alias
|
||||||
ro := &options.RootOptions{}
|
ro := &options.RootOptions{}
|
||||||
po := &options.PackagesOptions{}
|
po := &options.PackagesOptions{}
|
||||||
|
ao := &options.AttestOptions{}
|
||||||
packagesCmd := Packages(v, app, ro, po)
|
packagesCmd := Packages(v, app, ro, po)
|
||||||
|
|
||||||
// root options are also passed to the attestCmd so that a user provided config location can be discovered
|
// root options are also passed to the attestCmd so that a user provided config location can be discovered
|
||||||
poweruserCmd := PowerUser(v, app, ro)
|
poweruserCmd := PowerUser(v, app, ro)
|
||||||
convertCmd := Convert(v, app, ro, po)
|
convertCmd := Convert(v, app, ro, po)
|
||||||
attestCmd := Attest(v, app, ro, po)
|
attestCmd := Attest(v, app, ro, po, ao)
|
||||||
|
|
||||||
// rootCmd is currently an alias for the packages command
|
// rootCmd is currently an alias for the packages command
|
||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
|
|||||||
25
cmd/syft/cli/options/attest.go
Normal file
25
cmd/syft/cli/options/attest.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package options
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AttestOptions struct {
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Interface = (*AttestOptions)(nil)
|
||||||
|
|
||||||
|
func (o AttestOptions) AddFlags(cmd *cobra.Command, v *viper.Viper) error {
|
||||||
|
cmd.Flags().StringVarP(&o.Key, "key", "k", "", "the key to use for the attestation")
|
||||||
|
return bindAttestConfigOptions(cmd.Flags(), v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindAttestConfigOptions(flags *pflag.FlagSet, v *viper.Viper) error {
|
||||||
|
if err := v.BindPFlag("attest.key", flags.Lookup("key")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -47,6 +47,7 @@ type Application struct {
|
|||||||
Log logging `yaml:"log" json:"log" mapstructure:"log"` // all logging-related options
|
Log logging `yaml:"log" json:"log" mapstructure:"log"` // all logging-related options
|
||||||
Catalogers []string `yaml:"catalogers" json:"catalogers" mapstructure:"catalogers"`
|
Catalogers []string `yaml:"catalogers" json:"catalogers" mapstructure:"catalogers"`
|
||||||
Package pkg `yaml:"package" json:"package" mapstructure:"package"`
|
Package pkg `yaml:"package" json:"package" mapstructure:"package"`
|
||||||
|
Attest attest `yaml:"attest" json:"attest" mapstructure:"attest"`
|
||||||
FileMetadata FileMetadata `yaml:"file-metadata" json:"file-metadata" mapstructure:"file-metadata"`
|
FileMetadata FileMetadata `yaml:"file-metadata" json:"file-metadata" mapstructure:"file-metadata"`
|
||||||
FileClassification fileClassification `yaml:"file-classification" json:"file-classification" mapstructure:"file-classification"`
|
FileClassification fileClassification `yaml:"file-classification" json:"file-classification" mapstructure:"file-classification"`
|
||||||
FileContents fileContents `yaml:"file-contents" json:"file-contents" mapstructure:"file-contents"`
|
FileContents fileContents `yaml:"file-contents" json:"file-contents" mapstructure:"file-contents"`
|
||||||
|
|||||||
13
internal/config/attest.go
Normal file
13
internal/config/attest.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import "github.com/spf13/viper"
|
||||||
|
|
||||||
|
type attest struct {
|
||||||
|
Key string `yaml:"key" json:"key" mapstructure:"key"`
|
||||||
|
Password string `yaml:"password" json:"password" mapstructure:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cfg attest) loadDefaultValues(v *viper.Viper) {
|
||||||
|
v.SetDefault("attest.key", "")
|
||||||
|
v.SetDefault("attest.password", "")
|
||||||
|
}
|
||||||
@ -618,6 +618,9 @@ func AttestationStartedHandler(ctx context.Context, fr *frame.Frame, event party
|
|||||||
text := s.Text()
|
text := s.Text()
|
||||||
if strings.Contains(text, "tlog entry created with index") {
|
if strings.Contains(text, "tlog entry created with index") {
|
||||||
tlogEntry = text
|
tlogEntry = text
|
||||||
|
} else {
|
||||||
|
// no tlog entry create so user used personal PKI
|
||||||
|
tlogEntry = "signed attestation using provided key"
|
||||||
}
|
}
|
||||||
_, err = line.Write([]byte(fmt.Sprintf(" %s %s", auxInfoFormat.Sprintf("░░"), text)))
|
_, err = line.Write([]byte(fmt.Sprintf(" %s %s", auxInfoFormat.Sprintf("░░"), text)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user