Skip to content

Commit

Permalink
adjust code to latest changes
Browse files Browse the repository at this point in the history
Signed-off-by: Hector Fernandez <hector@chainguard.dev>
  • Loading branch information
hectorj2f committed Nov 21, 2022
1 parent 07bf6f2 commit d7a28bd
Show file tree
Hide file tree
Showing 18 changed files with 249 additions and 69 deletions.
2 changes: 1 addition & 1 deletion cmd/cosign/cli/options/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type KeyOpts struct {
BundlePath string
SkipConfirmation bool
TSAServerURL string
TSABundlePath string
RFC3161TimestampPath string
TSACertChainPath string

// FulcioAuthFlow is the auth flow to use when authenticating against
Expand Down
34 changes: 17 additions & 17 deletions cmd/cosign/cli/options/signblob.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ import (
// SignBlobOptions is the top level wrapper for the sign-blob command.
// The new output-certificate flag is only in use when COSIGN_EXPERIMENTAL is enabled
type SignBlobOptions struct {
Key string
Base64Output bool
Output string // deprecated: TODO remove when the output flag is fully deprecated
OutputSignature string // TODO: this should be the root output file arg.
OutputCertificate string
SecurityKey SecurityKeyOptions
Fulcio FulcioOptions
Rekor RekorOptions
OIDC OIDCOptions
Registry RegistryOptions
BundlePath string
SkipConfirmation bool
TlogUpload bool
TSAServerURL string
TSABundlePath string
Key string
Base64Output bool
Output string // deprecated: TODO remove when the output flag is fully deprecated
OutputSignature string // TODO: this should be the root output file arg.
OutputCertificate string
SecurityKey SecurityKeyOptions
Fulcio FulcioOptions
Rekor RekorOptions
OIDC OIDCOptions
Registry RegistryOptions
BundlePath string
SkipConfirmation bool
TlogUpload bool
TSAServerURL string
RFC3161TimestampPath string
}

var _ Interface = (*SignBlobOptions)(nil)
Expand Down Expand Up @@ -80,7 +80,7 @@ func (o *SignBlobOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.TSAServerURL, "timestamp-server-url", "",
"url to the Timestamp RFC3161 server, default none")

cmd.Flags().StringVar(&o.TSABundlePath, "tsa-bundle", "",
cmd.Flags().StringVar(&o.RFC3161TimestampPath, "rfc3161-timestamp-bundle", "",
"write everything required to verify the blob to a FILE")
_ = cmd.Flags().SetAnnotation("tsa-bundle", cobra.BashCompFilenameExt, []string{})
_ = cmd.Flags().SetAnnotation("rfc3161-timestamp-bundle", cobra.BashCompFilenameExt, []string{})
}
4 changes: 2 additions & 2 deletions cmd/cosign/cli/options/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ type VerifyBlobOptions struct {
Registry RegistryOptions
CommonVerifyOptions CommonVerifyOptions

TSABundlePath string
RFC3161TimestampPath string
}

var _ Interface = (*VerifyBlobOptions)(nil)
Expand All @@ -164,7 +164,7 @@ func (o *VerifyBlobOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.BundlePath, "bundle", "",
"path to bundle FILE")

cmd.Flags().StringVar(&o.TSABundlePath, "tsa-bundle", "",
cmd.Flags().StringVar(&o.RFC3161TimestampPath, "rfc3161-timestamp-bundle", "",
"path to timestamp bundle FILE")
}

Expand Down
3 changes: 1 addition & 2 deletions cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ func SignCmd(ro *options.RootOptions, ko options.KeyOpts, signOpts options.SignO
return fmt.Errorf("computing digest: %w", err)
}
digest := ref.Context().Digest(d.String())

err = signDigest(ctx, digest, staticPayload, ko, regOpts, annotations, signOpts.Upload, signOpts.OutputSignature, signOpts.OutputCertificate, signOpts.Recursive, signOpts.TlogUpload, dd, sv, se)
if err != nil {
return fmt.Errorf("signing digest: %w", err)
Expand Down Expand Up @@ -243,7 +242,7 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko opti

s = tsa.NewSigner(s, clientTSA)
}
if ShouldUploadToTlog(ctx, ko, digest, ko.SkipConfirmation, tlogUpload) {
if (ko.TSAServerURL != "" && tlogUpload) && ShouldUploadToTlog(ctx, ko, digest, ko.SkipConfirmation, tlogUpload) {
rClient, err := rekor.NewClient(ko.RekorURL)
if err != nil {
return err
Expand Down
14 changes: 8 additions & 6 deletions cmd/cosign/cli/sign/sign_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, regOpts options.Re
return nil, err
}

signedPayload.TSABundle = cbundle.TimestampToTSABundle(respBytes)
signedPayload.RFC3161Timestamp = cbundle.TimestampToRFC3161Timestamp(respBytes)
}
if ShouldUploadToTlog(ctx, ko, nil, ko.SkipConfirmation, tlogUpload) {
if !tlogUpload && ko.TSAServerURL != "" {
fmt.Fprintln(os.Stderr, "\nWARNING: skipping transparency log upload")
} else if ShouldUploadToTlog(ctx, ko, nil, ko.SkipConfirmation, tlogUpload) {
rekorBytes, err = sv.Bytes(ctx)
if err != nil {
return nil, err
Expand All @@ -99,17 +101,17 @@ func SignBlobCmd(ro *options.RootOptions, ko options.KeyOpts, regOpts options.Re
}

// if bundle is specified, just do that and ignore the rest
if ko.TSABundlePath != "" {
if ko.RFC3161TimestampPath != "" {
signedPayload.Base64Signature = base64.StdEncoding.EncodeToString(sig)

contents, err := json.Marshal(signedPayload)
if err != nil {
return nil, err
}
if err := os.WriteFile(ko.TSABundlePath, contents, 0600); err != nil {
return nil, fmt.Errorf("create tsa bundle file: %w", err)
if err := os.WriteFile(ko.RFC3161TimestampPath, contents, 0600); err != nil {
return nil, fmt.Errorf("create rfc3161 timestamp file: %w", err)
}
fmt.Printf("TSA bundle wrote in the file %s\n", ko.TSABundlePath)
fmt.Printf("RF3161 timestamp bundle wrote in the file %s\n", ko.RFC3161TimestampPath)
}

// if bundle is specified, just do that and ignore the rest
Expand Down
2 changes: 1 addition & 1 deletion cmd/cosign/cli/signblob.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func SignBlob() *cobra.Command {
BundlePath: o.BundlePath,
SkipConfirmation: o.SkipConfirmation,
TSAServerURL: o.TSAServerURL,
TSABundlePath: o.TSABundlePath,
RFC3161TimestampPath: o.RFC3161TimestampPath,
}

for _, blob := range args {
Expand Down
15 changes: 7 additions & 8 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,13 @@ The blob may be specified as a path to a file or - for stdin.`,
PersistentPreRun: options.BindViper,
RunE: func(cmd *cobra.Command, args []string) error {
ko := options.KeyOpts{
KeyRef: o.Key,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
RekorURL: o.Rekor.URL,
BundlePath: o.BundlePath,
TSAServerURL: o.CommonVerifyOptions.TSAServerURL,
TSABundlePath: o.TSABundlePath,
TSACertChainPath: o.CommonVerifyOptions.TSACertChainPath,
KeyRef: o.Key,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
RekorURL: o.Rekor.URL,
BundlePath: o.BundlePath,
RFC3161TimestampPath: o.RFC3161TimestampPath,
TSACertChainPath: o.CommonVerifyOptions.TSACertChainPath,
}
verifyBlobCmd := &verify.VerifyBlobCmd{
KeyOpts: ko,
Expand Down
2 changes: 0 additions & 2 deletions cmd/cosign/cli/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ type VerifyCommand struct {
LocalImage bool
NameOptions []name.Option
Offline bool
TSAServerURL string
TSACertChainPath string
SkipTlogVerify bool
}
Expand Down Expand Up @@ -117,7 +116,6 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
IgnoreSCT: c.IgnoreSCT,
SignatureRef: c.SignatureRef,
Offline: c.Offline,
TSACertChainPath: c.TSACertChainPath,
SkipTlogVerify: c.SkipTlogVerify,
}
if c.CheckClaims {
Expand Down
73 changes: 62 additions & 11 deletions cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
opts := make([]static.Option, 0)

// Require a certificate/key OR a local bundle file that has the cert.
if options.NOf(c.KeyRef, c.CertRef, c.Sk, c.BundlePath) == 0 {
return fmt.Errorf("please provide a cert to verify against via --certificate or a bundle via --bundle")
if options.NOf(c.KeyRef, c.CertRef, c.Sk, c.BundlePath, c.RFC3161TimestampPath) == 0 {
return fmt.Errorf("please provide a cert to verify against via --certificate or a bundle via --bundle or --rfc3161-timestamp-bundle")
}

// Key, sk, and cert are mutually exclusive.
if options.NOf(c.KeyRef, c.Sk, c.CertRef) > 1 {
return &options.KeyParseError{}
}

sig, err := base64signature(c.SigRef, c.BundlePath)
sig, err := base64signature(c.SigRef, c.BundlePath, c.RFC3161TimestampPath)
if err != nil {
return err
}
Expand All @@ -102,17 +102,37 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
CertGithubWorkflowRef: c.CertGithubWorkflowRef,
IgnoreSCT: c.IgnoreSCT,
Offline: c.Offline,
TSACertChainPath: c.KeyOpts.TSACertChainPath,
}
if c.KeyOpts.TSAServerURL != "" {
co.TSAClient, err = tclient.GetTimestampClient(c.KeyOpts.TSAServerURL)
if c.RFC3161TimestampPath != "" && c.KeyOpts.TSACertChainPath == "" {
return fmt.Errorf("timestamp-cert-chain is required to validate a rfc3161 timestamp bundle")
}
if c.KeyOpts.TSACertChainPath != "" {
_, err := os.Stat(c.KeyOpts.TSACertChainPath)
if err != nil {
return fmt.Errorf("unable to open timestamp certificate chain file '%s: %w", c.KeyOpts.TSACertChainPath, err)
}
// TODO: Add support for TUF certificates.
pemBytes, err := os.ReadFile(filepath.Clean(c.KeyOpts.TSACertChainPath))
if err != nil {
return fmt.Errorf("failed to create TSA client: %w", err)
return fmt.Errorf("error reading certification chain path file: %w", err)
}
if c.KeyOpts.TSACertChainPath != "" {
_, err := os.Stat(c.KeyOpts.TSACertChainPath)
// TODO: Update this logic once https://github.com/sigstore/timestamp-authority/issues/121 gets merged.
// This relies on untrusted leaf certificate.
tsaCertPool := x509.NewCertPool()
ok := tsaCertPool.AppendCertsFromPEM(pemBytes)
if !ok {
return fmt.Errorf("error parsing response into Timestamp while appending certs from PEM")
}
co.TSACerts = tsaCertPool
// Use default TUF roots if a cert chain is not provided.
if c.CertChain == "" {
co.RootCerts, err = fulcio.GetRoots()
if err != nil {
return fmt.Errorf("getting Fulcio roots: %w", err)
}
co.IntermediateCerts, err = fulcio.GetIntermediates()
if err != nil {
return fmt.Errorf("unable to open timestamp certificate chain file '%s': %w", c.KeyOpts.TSACertChainPath, err)
return fmt.Errorf("getting Fulcio intermediates: %w", err)
}
}
}
Expand Down Expand Up @@ -194,6 +214,31 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
}
opts = append(opts, static.WithBundle(b.Bundle))
}
if c.RFC3161TimestampPath != "" {
b, err := cosign.FetchLocalSignedPayloadFromPath(c.RFC3161TimestampPath)
if err != nil {
return err
}
// Note: RFC3161 timestamp does not set the certificate.
// We have to condition on this because sign-blob may not output the signing
// key to the bundle when there is no tlog upload.
if b.Cert != "" {
// b.Cert can either be a certificate or public key
certBytes := []byte(b.Cert)
if isb64(certBytes) {
certBytes, _ = base64.StdEncoding.DecodeString(b.Cert)
}
cert, err = loadCertFromPEM(certBytes)
if err != nil {
// check if cert is actually a public key
co.SigVerifier, err = sigs.LoadPublicKeyRaw(certBytes, crypto.SHA256)
if err != nil {
return fmt.Errorf("loading verifier from rfc3161 timestamp bundle: %w", err)
}
}
}
opts = append(opts, static.WithRFC3161Timestamp(b.RFC3161Timestamp))
}
// Set an SCT if provided via the CLI.
if c.SCTRef != "" {
sct, err := os.ReadFile(filepath.Clean(c.SCTRef))
Expand Down Expand Up @@ -268,7 +313,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
}

// base64signature returns the base64 encoded signature
func base64signature(sigRef string, bundlePath string) (string, error) {
func base64signature(sigRef string, bundlePath, rfc3161TimestampPath string) (string, error) {
var targetSig []byte
var err error
switch {
Expand All @@ -287,6 +332,12 @@ func base64signature(sigRef string, bundlePath string) (string, error) {
return "", err
}
targetSig = []byte(b.Base64Signature)
case rfc3161TimestampPath != "":
b, err := cosign.FetchLocalSignedPayloadFromPath(rfc3161TimestampPath)
if err != nil {
return "", err
}
targetSig = []byte(b.Base64Signature)
default:
return "", fmt.Errorf("missing flag '--signature'")
}
Expand Down
Loading

0 comments on commit d7a28bd

Please sign in to comment.