add json format

This commit is contained in:
ejahnGithub 2025-05-22 12:31:45 -04:00
parent e9fbe9d8b8
commit ca0f9847db
4 changed files with 46 additions and 10 deletions

4
.github/CODEOWNERS vendored
View file

@ -5,6 +5,10 @@ internal/codespaces/ @cli/codespaces
# Limit Package Security team ownership to the attestation command package and related integration tests
pkg/cmd/attestation/ @cli/package-security
pkg/cmd/release/attestation @cli/package-security
pkg/cmd/release/verify @cli/package-security
pkg/cmd/release/verify-asset @cli/package-security
test/integration/attestation-cmd @cli/package-security
pkg/cmd/attestation/verification/embed/tuf-repo.github.com/ @cli/tuf-root-reviewers

View file

@ -3,6 +3,7 @@ package attestation
import (
"fmt"
"net/http"
"path/filepath"
"strings"
"github.com/cli/cli/v2/internal/gh"
@ -47,8 +48,15 @@ type AttestOptions struct {
Hostname string
EC verification.EnforcementCriteria
// Tenant is only set when tenancy is used
Tenant string
FilePath string
Tenant string
AssetFilePath string
}
// Clean cleans the file path option values
func (opts *AttestOptions) Clean() {
if opts.AssetFilePath != "" {
opts.AssetFilePath = filepath.Clean(opts.AssetFilePath)
}
}
// AreFlagsValid checks that the provided flag combination is valid

View file

@ -31,8 +31,8 @@ func NewCmdVerifyAsset(f *cmdutil.Factory, runF func(*attestation.AttestOptions)
return cmdutil.FlagErrorf("You must specify a tag and a file path")
}
opts.TagName = args[0]
opts.FilePath = args[1]
tagName := args[0]
assetFilePath := args[1]
httpClient, err := f.HttpClient()
if err != nil {
@ -46,8 +46,8 @@ func NewCmdVerifyAsset(f *cmdutil.Factory, runF func(*attestation.AttestOptions)
hostname, _ := ghauth.DefaultHost()
*opts = attestation.AttestOptions{
TagName: opts.TagName,
FilePath: opts.FilePath,
TagName: tagName,
AssetFilePath: assetFilePath,
Repo: baseRepo.RepoOwner() + "/" + baseRepo.RepoName(),
APIClient: api.NewLiveClient(httpClient, hostname, logger),
Limit: 10,
@ -93,15 +93,17 @@ func NewCmdVerifyAsset(f *cmdutil.Factory, runF func(*attestation.AttestOptions)
return verifyAssetRun(opts)
},
}
cmdutil.AddFormatFlags(cmd, &opts.Exporter)
return cmd
}
func verifyAssetRun(opts *attestation.AttestOptions) error {
ctx := context.Background()
fileName := getFileName(opts.FilePath)
fileName := getFileName(opts.AssetFilePath)
// calculate the digest of the file
fileDigest, err := artifact.NewDigestedArtifact(nil, opts.FilePath, "sha256")
fileDigest, err := artifact.NewDigestedArtifact(nil, opts.AssetFilePath, "sha256")
if err != nil {
opts.Logger.Println(opts.Logger.ColorScheme.Red("✗ Failed to calculate file digest"))
return err
@ -141,7 +143,7 @@ func verifyAssetRun(opts *attestation.AttestOptions) error {
}
if len(filteredAttestations) == 0 {
opts.Logger.Printf(opts.Logger.ColorScheme.Red("Release %s does not contain %s (%s)\n"), opts.TagName, opts.FilePath, fileDigest.DigestWithAlg())
opts.Logger.Printf(opts.Logger.ColorScheme.Red("Release %s does not contain %s (%s)\n"), opts.TagName, opts.AssetFilePath, fileDigest.DigestWithAlg())
return nil
}
@ -152,10 +154,20 @@ func verifyAssetRun(opts *attestation.AttestOptions) error {
if err != nil {
opts.Logger.Println(opts.Logger.ColorScheme.Red(errMsg))
opts.Logger.Printf(opts.Logger.ColorScheme.Red("Release %s does not contain %s (%s)\n"), opts.TagName, opts.FilePath, fileDigest.DigestWithAlg())
opts.Logger.Printf(opts.Logger.ColorScheme.Red("Release %s does not contain %s (%s)\n"), opts.TagName, opts.AssetFilePath, fileDigest.DigestWithAlg())
return err
}
// If an exporter is provided with the --json flag, write the results to the terminal in JSON format
if opts.Exporter != nil {
// print the results to the terminal as an array of JSON objects
if err = opts.Exporter.Write(opts.Logger.IO, verified); err != nil {
opts.Logger.Println(opts.Logger.ColorScheme.Red("✗ Failed to write JSON output"))
return err
}
return nil
}
opts.Logger.Printf("The following %s matched the policy criteria\n\n", text.Pluralize(len(verified), "attestation"))
opts.Logger.Println(opts.Logger.ColorScheme.Green("✓ Verification succeeded!\n"))
opts.Logger.Printf("Attestation found matching release %s (%s)\n", opts.TagName, releaseRefDigest.DigestWithAlg())

View file

@ -94,6 +94,8 @@ func NewCmdVerify(f *cmdutil.Factory, runF func(*attestation.AttestOptions) erro
return verifyRun(opts)
},
}
cmdutil.AddFormatFlags(cmd, &opts.Exporter)
return cmd
}
@ -137,6 +139,16 @@ func verifyRun(opts *attestation.AttestOptions) error {
return err
}
// If an exporter is provided with the --json flag, write the results to the terminal in JSON format
if opts.Exporter != nil {
// print the results to the terminal as an array of JSON objects
if err = opts.Exporter.Write(opts.Logger.IO, verified); err != nil {
opts.Logger.Println(opts.Logger.ColorScheme.Red("✗ Failed to write JSON output"))
return err
}
return nil
}
opts.Logger.Printf("The following %s matched the policy criteria\n\n", text.Pluralize(len(verified), "attestation"))
opts.Logger.Println(opts.Logger.ColorScheme.Green("✓ Verification succeeded!\n"))