Skip to content

Commit

Permalink
add support for tsa signing and verification of images (#2460)
Browse files Browse the repository at this point in the history
* add support for tsa signing and verification of images

Signed-off-by: Hector Fernandez <hector@chainguard.dev>

* add tsa flag to cli docs

Signed-off-by: Hector Fernandez <hector@chainguard.dev>

* read tsa bundle from signatures

Signed-off-by: Hector Fernandez <hector@chainguard.dev>

* address reviewer comments

Signed-off-by: Hector Fernandez <hector@chainguard.dev>

* add TODOs to the code

Signed-off-by: Hector Fernandez <hector@chainguard.dev>

Signed-off-by: Hector Fernandez <hector@chainguard.dev>
  • Loading branch information
hectorj2f authored Nov 15, 2022
1 parent 3e870f9 commit ba5997b
Show file tree
Hide file tree
Showing 23 changed files with 616 additions and 13 deletions.
1 change: 1 addition & 0 deletions cmd/cosign/cli/options/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type KeyOpts struct {
OIDCProvider string // Specify which OIDC credential provider to use for keyless signer
BundlePath string
SkipConfirmation bool
TSAServerURL string

// FulcioAuthFlow is the auth flow to use when authenticating against
// Fulcio. See https://pkg.go.dev/github.com/sigstore/cosign/cmd/cosign/cli/fulcio#pkg-constants
Expand Down
4 changes: 4 additions & 0 deletions cmd/cosign/cli/options/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type SignOptions struct {
Attachment string
SkipConfirmation bool
TlogUpload bool
TSAServerURL string

Rekor RekorOptions
Fulcio FulcioOptions
Expand Down Expand Up @@ -94,4 +95,7 @@ func (o *SignOptions) AddFlags(cmd *cobra.Command) {

cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", false,
"whether or not to upload to the tlog")

cmd.Flags().StringVar(&o.TSAServerURL, "timestamp-server-url", "",
"url to the Timestamp RFC3161 server, default none")
}
11 changes: 10 additions & 1 deletion cmd/cosign/cli/options/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,20 @@ import (
)

type CommonVerifyOptions struct {
Offline bool // Force offline verification
Offline bool // Force offline verification
TSACertChainPath string
TSAServerURL string
}

func (o *CommonVerifyOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(&o.Offline, "offline", false,
"only allow offline verification")

cmd.Flags().StringVar(&o.TSAServerURL, "timestamp-server-url", "",
"url to a timestamp RFC3161 server, default none")

cmd.Flags().StringVar(&o.TSACertChainPath, "timestamp-cert-chain", "",
"path to certificate chain PEM file for the Timestamp Authority")
}

// VerifyOptions is the top level wrapper for the `verify` command.
Expand All @@ -43,6 +51,7 @@ type VerifyOptions struct {
Rekor RekorOptions
Registry RegistryOptions
SignatureDigest SignatureDigestOptions

AnnotationOptions
}

Expand Down
1 change: 1 addition & 0 deletions cmd/cosign/cli/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ race conditions or (worse) malicious tampering.
OIDCDisableProviders: o.OIDC.DisableAmbientProviders,
OIDCProvider: o.OIDC.Provider,
SkipConfirmation: o.SkipConfirmation,
TSAServerURL: o.TSAServerURL,
}
if err := sign.SignCmd(ro, ko, *o, args); err != nil {
if o.Attachment == "" {
Expand Down
14 changes: 13 additions & 1 deletion cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
ifulcio "github.com/sigstore/cosign/internal/pkg/cosign/fulcio"
ipayload "github.com/sigstore/cosign/internal/pkg/cosign/payload"
irekor "github.com/sigstore/cosign/internal/pkg/cosign/rekor"
"github.com/sigstore/cosign/internal/pkg/cosign/tsa"
"github.com/sigstore/cosign/pkg/cosign"
"github.com/sigstore/cosign/pkg/cosign/pivkey"
"github.com/sigstore/cosign/pkg/cosign/pkcs11key"
Expand All @@ -54,6 +55,8 @@ import (
signatureoptions "github.com/sigstore/sigstore/pkg/signature/options"
sigPayload "github.com/sigstore/sigstore/pkg/signature/payload"

tsaclient "github.com/sigstore/timestamp-authority/pkg/client"

// Loads OIDC providers
_ "github.com/sigstore/cosign/pkg/providers/all"
)
Expand Down Expand Up @@ -231,7 +234,16 @@ func signDigest(ctx context.Context, digest name.Digest, payload []byte, ko opti
if sv.Cert != nil {
s = ifulcio.NewSigner(s, sv.Cert, sv.Chain)
}
if ShouldUploadToTlog(ctx, ko, digest, ko.SkipConfirmation, tlogUpload) {

// TODO: For the moment you can only use the timestamped service OR the transparency log.
if ko.TSAServerURL != "" {
clientTSA, err := tsaclient.GetTimestampClient(ko.TSAServerURL)
if err != nil {
return fmt.Errorf("failed to create TSA client: %w", err)
}

s = tsa.NewSigner(s, clientTSA)
} else if ShouldUploadToTlog(ctx, ko, digest, ko.SkipConfirmation, tlogUpload) {
rClient, err := rekor.NewClient(ko.RekorURL)
if err != nil {
return err
Expand Down
2 changes: 2 additions & 0 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ against the transparency log.`,
SignatureRef: o.SignatureRef,
LocalImage: o.LocalImage,
Offline: o.CommonVerifyOptions.Offline,
TSAServerURL: o.CommonVerifyOptions.TSAServerURL,
TSACertChainPath: o.CommonVerifyOptions.TSACertChainPath,
}

if o.Registry.AllowInsecure {
Expand Down
23 changes: 23 additions & 0 deletions cmd/cosign/cli/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/payload"
tsaclient "github.com/sigstore/timestamp-authority/pkg/client"
)

// VerifyCommand verifies a signature on a supplied container image
Expand Down Expand Up @@ -75,6 +76,8 @@ type VerifyCommand struct {
LocalImage bool
NameOptions []name.Option
Offline bool
TSAServerURL string
TSACertChainPath string
}

// Exec runs the verification command
Expand Down Expand Up @@ -113,11 +116,25 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
IgnoreSCT: c.IgnoreSCT,
SignatureRef: c.SignatureRef,
Offline: c.Offline,
TSACertChainPath: c.TSACertChainPath,
}
if c.CheckClaims {
co.ClaimVerifier = cosign.SimpleClaimVerifier
}

if c.TSAServerURL != "" {
co.TSAClient, err = tsaclient.GetTimestampClient(c.TSAServerURL)
if err != nil {
return fmt.Errorf("failed to create TSA client: %w", err)
}
if c.TSACertChainPath != "" {
_, err := os.Stat(c.TSACertChainPath)
if err != nil {
return fmt.Errorf("unable to open timestamp certificate chain file: %w", err)
}
}
}

if keylessVerification(c.KeyRef, c.Sk) {
if c.RekorURL != "" {
rekorClient, err := rekor.NewClient(c.RekorURL)
Expand Down Expand Up @@ -356,6 +373,12 @@ func PrintVerification(imgRef string, verified []oci.Signature, output string) {
}
ss.Optional["Bundle"] = bundle
}
if tsaBundle, err := sig.TSABundle(); err == nil && tsaBundle != nil {
if ss.Optional == nil {
ss.Optional = make(map[string]interface{})
}
ss.Optional["TSABundle"] = tsaBundle
}

outputKeys = append(outputKeys, ss)
}
Expand Down
2 changes: 2 additions & 0 deletions doc/cosign_dockerfile_verify.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions doc/cosign_manifest_verify.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions doc/cosign_sign.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions doc/cosign_verify-attestation.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions doc/cosign_verify-blob.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions doc/cosign_verify.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 19 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/chrismellard/docker-credential-acr-env v0.0.0-20220119192733-fe33c00cee21
github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b
github.com/depcheck-test/depcheck-test v0.0.0-20220607135614-199033aaa936
github.com/digitorus/timestamp v0.0.0-20221019182153-ef3b63b79b31
github.com/go-openapi/runtime v0.24.2
github.com/go-openapi/strfmt v0.21.3
github.com/go-openapi/swag v0.22.3
Expand All @@ -28,6 +29,7 @@ require (
github.com/sigstore/fulcio v1.0.0
github.com/sigstore/rekor v1.0.1
github.com/sigstore/sigstore v1.4.5
github.com/sigstore/timestamp-authority v0.1.3-0.20221114113831-cf271cea5d83
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.14.0
Expand All @@ -53,7 +55,8 @@ require (
cloud.google.com/go/compute v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go/iam v0.6.0 // indirect
cloud.google.com/go/kms v1.5.0 // indirect
cloud.google.com/go/kms v1.6.0 // indirect
filippo.io/edwards25519 v1.0.0 // indirect
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 // indirect
github.com/Azure/azure-sdk-for-go v67.0.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
Expand Down Expand Up @@ -83,6 +86,7 @@ require (
github.com/armon/go-metrics v0.4.1 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/aws/aws-sdk-go v1.44.132 // indirect
github.com/aws/aws-sdk-go-v2 v1.16.16 // indirect
github.com/aws/aws-sdk-go-v2/config v1.17.8 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.12.21 // indirect
Expand All @@ -98,8 +102,10 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.16.19 // indirect
github.com/aws/smithy-go v1.13.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/clbanning/mxj/v2 v2.5.6 // indirect
github.com/cockroachdb/apd/v2 v2.0.1 // indirect
Expand All @@ -108,11 +114,13 @@ require (
github.com/coreos/go-oidc/v3 v3.4.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/digitorus/pkcs7 v0.0.0-20221019075359-21b8b40e6bb4 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/docker/cli v20.10.20+incompatible // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.20+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/proto v1.6.15 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
Expand All @@ -138,6 +146,7 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/tink/go v1.7.0 // indirect
github.com/google/trillian v1.5.1-0.20220819043421-0a389c4bb8d9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
Expand Down Expand Up @@ -176,6 +185,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
Expand All @@ -193,8 +203,13 @@ require (
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/protocolbuffers/txtpbfmt v0.0.0-20201118171849-f6a6b3f636fc // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rs/cors v1.8.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 // indirect
Expand All @@ -212,13 +227,15 @@ require (
github.com/thales-e-security/pool v0.0.2 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
github.com/urfave/negroni v1.0.0 // indirect
github.com/vbatts/tar-split v0.11.2 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.1.0 // indirect
github.com/zeebo/errs v1.2.2 // indirect
go.mongodb.org/mongo-driver v1.10.0 // indirect
go.mongodb.org/mongo-driver v1.10.1 // indirect
go.opencensus.io v0.24.0 // indirect
go.step.sm/crypto v0.23.1 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.23.0 // indirect
Expand Down
Loading

0 comments on commit ba5997b

Please sign in to comment.