* add attestation cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add codeowners
Signed-off-by: Meredith Lancaster <malancas@github.com>
* update args passed to the attestation cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* rename file
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use gh-attestation branch for passing iostreams from the root
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add package security team entry to codeowners
Signed-off-by: Meredith Lancaster <malancas@github.com>
* start moving over verify cmd and general verification code
Signed-off-by: Meredith Lancaster <malancas@github.com>
* clean up common and verify specific policy code
Signed-off-by: Meredith Lancaster <malancas@github.com>
* move artifact package over
Signed-off-by: Meredith Lancaster <malancas@github.com>
* start pulling in the github api client wrapper
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix imports
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add logger and test packages
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add additional packages to support verify command
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix mock api client
Signed-off-by: Meredith Lancaster <malancas@github.com>
* clean up mock api client
Signed-off-by: Meredith Lancaster <malancas@github.com>
* include missing fields
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use correct owner
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add more mock api client options
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add download cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add inspect cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* pass factory object to inspect cmd, add inspect sub cmd to attestation cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add verify-tuf-root cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* pass iostream struct from command
Signed-off-by: Meredith Lancaster <malancas@github.com>
* rename logger pkg to logger
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix path in codeowners
Signed-off-by: Meredith Lancaster <malancas@github.com>
* formatter
Signed-off-by: Meredith Lancaster <malancas@github.com>
* go mod tidy
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix printf linter issue
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix printf linter issue
Signed-off-by: Meredith Lancaster <malancas@github.com>
* check user's GH host for compatibility
Signed-off-by: Meredith Lancaster <malancas@github.com>
* pass oci client to commands directly
Signed-off-by: Meredith Lancaster <malancas@github.com>
* rename command
Signed-off-by: Meredith Lancaster <malancas@github.com>
* mark tuf-root-verify cmd hidden
Signed-off-by: Meredith Lancaster <malancas@github.com>
* move client initialization back to subcommands
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add more verbose options and logging
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add missing logger
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add testing around OCI and API client
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add integration test
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix file path
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix command
Signed-off-by: Meredith Lancaster <malancas@github.com>
* build executable before integration test
Signed-off-by: Meredith Lancaster <malancas@github.com>
* split integration tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* remove integration test steps
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix flag value
Signed-off-by: Meredith Lancaster <malancas@github.com>
* run integration tests on ubuntu for now
Signed-off-by: Meredith Lancaster <malancas@github.com>
* pull over doc updates
Signed-off-by: Meredith Lancaster <malancas@github.com>
* delete unused test data
Signed-off-by: Meredith Lancaster <malancas@github.com>
* remove Go patch version
Signed-off-by: Meredith Lancaster <malancas@github.com>
* switch assert to require
Signed-off-by: Meredith Lancaster <malancas@github.com>
* rename file
Signed-off-by: Meredith Lancaster <malancas@github.com>
* move integration tests to prexisting test workflow
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use platform matrix for integration tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* simplify build step
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use StringEnumFlag handling
Signed-off-by: Meredith Lancaster <malancas@github.com>
* typo
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use the iostreams.Test helper func
Signed-off-by: Meredith Lancaster <malancas@github.com>
* create interface for oci client
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add tests for oci client
Signed-off-by: Meredith Lancaster <malancas@github.com>
* rename files
Signed-off-by: Meredith Lancaster <malancas@github.com>
* format file
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix shellcheck issues
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use testing TempDir method
Signed-off-by: Meredith Lancaster <malancas@github.com>
* cleanup unused tempdir handling
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use table driven tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* check correct cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* support repo option in download sub cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* switch over to using RunE
Signed-off-by: Meredith Lancaster <malancas@github.com>
* unexport top level subcommand funcs
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add comment around keychain option
Signed-off-by: Meredith Lancaster <malancas@github.com>
* update comments
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix inconsistent naming
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add tests for CLI commands
Signed-off-by: Meredith Lancaster <malancas@github.com>
* check for noattestationsfound err
Signed-off-by: Meredith Lancaster <malancas@github.com>
* try out metadata abstraction instead
Signed-off-by: Meredith Lancaster <malancas@github.com>
* switch to using MetadataStore abstraction
Signed-off-by: Meredith Lancaster <malancas@github.com>
* include test case with failing metadata store
Signed-off-by: Meredith Lancaster <malancas@github.com>
* look for err specific to file write
Signed-off-by: Meredith Lancaster <malancas@github.com>
* unexport fields
Signed-off-by: Meredith Lancaster <malancas@github.com>
* return err when an unsupported hash alg is provided
Signed-off-by: Meredith Lancaster <malancas@github.com>
* PrintTableToStdOut returns err when rendering fails
Signed-off-by: Meredith Lancaster <malancas@github.com>
* start adding sigstore verifier unit tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add more sigstore verifier specific tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use cli table printer
Signed-off-by: Meredith Lancaster <malancas@github.com>
* return JSON results in slice instead of table
Signed-off-by: Meredith Lancaster <malancas@github.com>
* move mock client to test file
Signed-off-by: Meredith Lancaster <malancas@github.com>
* remove unneeded table printer method
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add initial tests for tufrootverify cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* formatting
Signed-off-by: Meredith Lancaster <malancas@github.com>
* cleanup method
Signed-off-by: Meredith Lancaster <malancas@github.com>
* close file in error handling branch
Signed-off-by: Meredith Lancaster <malancas@github.com>
* normalize artifact path
Signed-off-by: Meredith Lancaster <malancas@github.com>
* remove unneeded embedded file system
Signed-off-by: Meredith Lancaster <malancas@github.com>
* include image name reference err
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use GH_DEBUG value for io handling
Signed-off-by: Meredith Lancaster <malancas@github.com>
* remove quiet and verbose flags
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add more tufrootveriify tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* GitHubTUFOptions no longer needs to return error
Signed-off-by: Meredith Lancaster <malancas@github.com>
* remove unneeded slice
Signed-off-by: Meredith Lancaster <malancas@github.com>
* normalize all relative paths
Signed-off-by: Meredith Lancaster <malancas@github.com>
* clean up nil client checks
Signed-off-by: Meredith Lancaster <malancas@github.com>
* set api server based on host
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add comment about http client
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use format flag to handle json output in verify cmd
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use format flag to handle json output
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use normalized path for cli test arg
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add tests for json output
Signed-off-by: Meredith Lancaster <malancas@github.com>
* cleanup error wrapping
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use test fixtures correctly by normalizing path
Signed-off-by: Meredith Lancaster <malancas@github.com>
* dont clean
Signed-off-by: Meredith Lancaster <malancas@github.com>
* escape backwards slash for windows files with replace
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use strings.Split func
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use strings.Replace for all command tests
Signed-off-by: Meredith Lancaster <malancas@github.com>
* use CLI cache dir to store tuf metadata
Signed-off-by: Meredith Lancaster <malancas@github.com>
* Tweaked docstrings for gh attestation download
* Tweaked docstrings for gh attestation verify
* Fix for bug in gh attestation where the wrong hostname was being passed to the API client.
* lets hide tuf-root-verify eh?
* Forgot verify's short str.
* add remote verification test
Signed-off-by: Meredith Lancaster <malancas@github.com>
* Revert "add remote verification test"
This reverts commit c0ceb99ca8.
* update json result handling
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add json tags to struct returned by command
Signed-off-by: Meredith Lancaster <malancas@github.com>
* fix how json results are handled
Signed-off-by: Meredith Lancaster <malancas@github.com>
* add test to ensure JSON output is valid
Signed-off-by: Meredith Lancaster <malancas@github.com>
---------
Signed-off-by: Meredith Lancaster <malancas@github.com>
Co-authored-by: Phill MV <phillmv@github.com>
162 lines
5.1 KiB
Go
162 lines
5.1 KiB
Go
package inspect
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/cli/cli/v2/internal/tableprinter"
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact"
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact/oci"
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/auth"
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/io"
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/verification"
|
|
"github.com/cli/cli/v2/pkg/cmdutil"
|
|
|
|
"github.com/MakeNowJust/heredoc"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func NewInspectCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Command {
|
|
opts := &Options{}
|
|
inspectCmd := &cobra.Command{
|
|
Use: "inspect [<file path> | oci://<OCI image URI>] --bundle <path-to-bundle>",
|
|
Args: cobra.ExactArgs(1),
|
|
Hidden: true,
|
|
Short: "Inspect a sigstore bundle",
|
|
Long: heredoc.Docf(`
|
|
Inspect a downloaded Sigstore bundle for a given artifact.
|
|
|
|
The command requires either:
|
|
* a relative path to a local artifact, or
|
|
* a container image URI (e.g. %[1]soci://<my-OCI-image-URI>%[1]s)
|
|
|
|
Note that if you provide an OCI URI for the artifact you must already
|
|
be authenticated with a container registry.
|
|
|
|
The command also requires the %[1]s--bundle%[1]s flag, which provides a file
|
|
path to a previously downloaded Sigstore bundle. (See also the %[1]sdownload%[1]s
|
|
command).
|
|
|
|
By default, the command will print information about the bundle in a table format.
|
|
If the %[1]s--json-result%[1]s flag is provided, the command will print the
|
|
information in JSON format.
|
|
`, "`"),
|
|
Example: heredoc.Doc(`
|
|
# Inspect a Sigstore bundle and print the results in table format
|
|
$ gh attestation inspect <my-artifact> --bundle <path-to-bundle>
|
|
|
|
# Inspect a Sigstore bundle and print the results in JSON format
|
|
$ gh attestation inspect <my-artifact> --bundle <path-to-bundle> --json-result
|
|
|
|
# Inspect a Sigsore bundle for an OCI artifact, and print the results in table format
|
|
$ gh attestation inspect oci://<my-OCI-image> --bundle <path-to-bundle>
|
|
`),
|
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
|
// Create a logger for use throughout the inspect command
|
|
opts.Logger = io.NewHandler(f.IOStreams)
|
|
|
|
// set the artifact path
|
|
opts.ArtifactPath = args[0]
|
|
|
|
// Clean file path options
|
|
// opts.Clean()
|
|
|
|
return nil
|
|
},
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
opts.OCIClient = oci.NewLiveClient()
|
|
|
|
if err := auth.IsHostSupported(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if runF != nil {
|
|
return runF(opts)
|
|
}
|
|
|
|
if err := runInspect(opts); err != nil {
|
|
return fmt.Errorf("Failed to inspect the artifact and bundle: %w", err)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
inspectCmd.Flags().StringVarP(&opts.BundlePath, "bundle", "b", "", "Path to bundle on disk, either a single bundle in a JSON file or a JSON lines file with multiple bundles")
|
|
inspectCmd.MarkFlagRequired("bundle") //nolint:errcheck
|
|
cmdutil.StringEnumFlag(inspectCmd, &opts.DigestAlgorithm, "digest-alg", "d", "sha256", []string{"sha256", "sha512"}, "The algorithm used to compute a digest of the artifact")
|
|
cmdutil.AddFormatFlags(inspectCmd, &opts.exporter)
|
|
|
|
return inspectCmd
|
|
}
|
|
|
|
func runInspect(opts *Options) error {
|
|
artifact, err := artifact.NewDigestedArtifact(opts.OCIClient, opts.ArtifactPath, opts.DigestAlgorithm)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to digest artifact: %s", err)
|
|
}
|
|
|
|
opts.Logger.Printf("Verifying attestations for the artifact found at %s\n\n", artifact.URL)
|
|
|
|
attestations, err := verification.GetLocalAttestations(opts.BundlePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read attestations for subject: %s", artifact.DigestWithAlg())
|
|
}
|
|
|
|
config := verification.SigstoreConfig{
|
|
Logger: opts.Logger,
|
|
}
|
|
|
|
policy, err := buildPolicy(*artifact)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to build policy: %v", err)
|
|
}
|
|
|
|
sigstore, err := verification.NewSigstoreVerifier(config, policy)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
res := sigstore.Verify(attestations)
|
|
if res.Error != nil {
|
|
return fmt.Errorf("at least one attestation failed to verify against Sigstore: %v", res.Error)
|
|
}
|
|
|
|
opts.Logger.VerbosePrint(opts.Logger.ColorScheme.Green(
|
|
"Successfully verified all attestations against Sigstore!\n\n",
|
|
))
|
|
|
|
// If the user provides the --format=json flag, print the results in JSON format
|
|
if opts.exporter != nil {
|
|
details, err := getAttestationDetails(res.VerifyResults)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get attestation detail: %v", err)
|
|
}
|
|
|
|
// print the results to the terminal as an array of JSON objects
|
|
if err = opts.exporter.Write(opts.Logger.IO, details); err != nil {
|
|
return fmt.Errorf("failed to write JSON output")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// otherwise, print results in a table
|
|
details, err := getDetailsAsSlice(res.VerifyResults)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parse attestation details: %v", err)
|
|
}
|
|
|
|
headers := []string{"Repo Name", "Repo ID", "Org Name", "Org ID", "Workflow ID"}
|
|
t := tableprinter.New(opts.Logger.IO, tableprinter.WithHeader(headers...))
|
|
|
|
for _, row := range details {
|
|
for _, field := range row {
|
|
t.AddField(field, tableprinter.WithTruncate(nil))
|
|
}
|
|
t.EndRow()
|
|
}
|
|
|
|
if err = t.Render(); err != nil {
|
|
return fmt.Errorf("failed to print output: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|