Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions cmd/cosign/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,45 @@
package cli

import (
"context"
"fmt"
"net/http"
"os"

cranecmd "github.com/google/go-containerregistry/cmd/crane/cmd"
"github.com/google/go-containerregistry/pkg/logs"
"github.com/sigstore/cosign/v3/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v3/cmd/cosign/cli/templates"
itracing "github.com/sigstore/cosign/v3/internal/tracing"
"github.com/sigstore/model-validation-operator/pkg/tracing"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
cobracompletefig "github.com/withfig/autocomplete-tools/integrations/cobra"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/trace"
"sigs.k8s.io/release-utils/version"
)

var (
ro = &options.RootOptions{}
)

// tracingTransport injects the active trace context into outgoing HTTP requests
// that were created without context (http.NewRequest instead of http.NewRequestWithContext).
type tracingTransport struct {
base http.RoundTripper
}

func (t *tracingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
if itracing.ActiveCtx != nil {
// Inject the active span into the request context so otelhttp
// creates child spans under the root operation span.
// Preserve any deadline/values from the original request context.
req = req.WithContext(trace.ContextWithSpan(req.Context(), trace.SpanFromContext(itracing.ActiveCtx)))
}
return t.base.RoundTrip(req)
}

func normalizeCertificateFlags(_ *pflag.FlagSet, name string) pflag.NormalizedName {
switch name {
case "cert":
Expand All @@ -53,7 +75,8 @@ func normalizeCertificateFlags(_ *pflag.FlagSet, name string) pflag.NormalizedNa

func New() *cobra.Command {
var (
out, stdout *os.File
out, stdout *os.File
tracingShutdown func(context.Context) error
)

cmd := &cobra.Command{
Expand All @@ -77,9 +100,38 @@ func New() *cobra.Command {
logs.Debug.SetOutput(os.Stderr)
}

if ro.TracingEnabled {
var tracingOpts []tracing.Option
tracingOpts = append(tracingOpts, tracing.WithServiceName("cosign"))
if ro.TracingEndpoint != "" {
tracingOpts = append(tracingOpts, tracing.WithEndpoint(ro.TracingEndpoint))
}
tracingOpts = append(tracingOpts, tracing.WithInsecure(ro.TracingInsecure))
if ro.TracingStdout {
tracingOpts = append(tracingOpts, tracing.WithStdoutExporter())
}

shutdown, err := tracing.SetupTracing(cmd.Context(), tracingOpts...)
if err != nil {
return fmt.Errorf("setting up tracing: %w", err)
}
tracingShutdown = shutdown

// Wrap http.DefaultTransport so all outgoing HTTP requests
// (to Fulcio, Rekor, TSA, etc.) propagate trace context.
// The tracingTransport injects the active span context into
// requests created without context (e.g. inside sigstore-go).
http.DefaultTransport = &tracingTransport{
base: otelhttp.NewTransport(http.DefaultTransport),
}
}

return nil
},
PersistentPostRun: func(_ *cobra.Command, _ []string) {
PersistentPostRun: func(cmd *cobra.Command, _ []string) {
if tracingShutdown != nil {
_ = tracingShutdown(cmd.Context())
}
if out != nil {
_ = out.Close()
}
Expand Down
14 changes: 14 additions & 0 deletions cmd/cosign/cli/options/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ type RootOptions struct {
OutputFile string
Verbose bool
Timeout time.Duration

TracingEnabled bool
TracingEndpoint string
TracingInsecure bool
TracingStdout bool
}

// DefaultTimeout specifies the default timeout for commands.
Expand All @@ -51,6 +56,15 @@ func (o *RootOptions) AddFlags(cmd *cobra.Command) {

cmd.PersistentFlags().DurationVarP(&o.Timeout, "timeout", "t", DefaultTimeout,
"timeout for commands")

cmd.PersistentFlags().BoolVar(&o.TracingEnabled, "tracing-enabled", false,
"enable OpenTelemetry tracing")
cmd.PersistentFlags().StringVar(&o.TracingEndpoint, "tracing-endpoint", "",
"OTLP gRPC collector endpoint (e.g. host:4317)")
cmd.PersistentFlags().BoolVar(&o.TracingInsecure, "tracing-insecure", true,
"use insecure gRPC connection for tracing")
cmd.PersistentFlags().BoolVar(&o.TracingStdout, "tracing-stdout", false,
"export traces to stdout instead of OTLP")
}

func BindViper(cmd *cobra.Command, args []string) {
Expand Down
6 changes: 6 additions & 0 deletions cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
ipayload "github.com/sigstore/cosign/v3/internal/pkg/cosign/payload"
irekor "github.com/sigstore/cosign/v3/internal/pkg/cosign/rekor"
"github.com/sigstore/cosign/v3/internal/pkg/cosign/tsa"
"github.com/sigstore/cosign/v3/internal/pkg/cosign/tsa/client"

Check failure on line 39 in cmd/cosign/cli/sign/sign.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (goimports)

Check failure on line 39 in cmd/cosign/cli/sign/sign.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gofmt)
"github.com/sigstore/cosign/v3/internal/ui"
"github.com/sigstore/cosign/v3/pkg/cosign"
cremote "github.com/sigstore/cosign/v3/pkg/cosign/remote"
Expand All @@ -45,7 +45,9 @@
ociremote "github.com/sigstore/cosign/v3/pkg/oci/remote"
"github.com/sigstore/cosign/v3/pkg/oci/walk"
"github.com/sigstore/cosign/v3/pkg/types"
itracing "github.com/sigstore/cosign/v3/internal/tracing"
sigPayload "github.com/sigstore/sigstore/pkg/signature/payload"
"go.opentelemetry.io/otel"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"

Expand All @@ -65,6 +67,10 @@

// nolint
func SignCmd(ctx context.Context, ro *options.RootOptions, ko options.KeyOpts, signOpts options.SignOptions, imgs []string) error {
ctx, span := otel.Tracer("cosign").Start(ctx, "sign")
defer span.End()
itracing.ActiveCtx = ctx

if options.NOf(ko.KeyRef, ko.Sk) > 1 {
return &options.KeyParseError{}
}
Expand Down
6 changes: 6 additions & 0 deletions cmd/cosign/cli/sign/sign_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/sigstore/cosign/v3/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v3/cmd/cosign/cli/signcommon"
internal "github.com/sigstore/cosign/v3/internal/pkg/cosign"
itracing "github.com/sigstore/cosign/v3/internal/tracing"
"github.com/sigstore/cosign/v3/internal/ui"
"github.com/sigstore/cosign/v3/pkg/cosign"
cbundle "github.com/sigstore/cosign/v3/pkg/cosign/bundle"
Expand All @@ -43,6 +44,7 @@ import (
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
signatureoptions "github.com/sigstore/sigstore/pkg/signature/options"
"go.opentelemetry.io/otel"
)

func getPayload(ctx context.Context, payloadPath string, hashFunction crypto.Hash) (internal.HashReader, func() error, error) {
Expand All @@ -59,6 +61,10 @@ func getPayload(ctx context.Context, payloadPath string, hashFunction crypto.Has

// nolint
func SignBlobCmd(ctx context.Context, ro *options.RootOptions, ko options.KeyOpts, payloadPath, certPath, certChainPath string, b64 bool, outputSignature string, outputCertificate string, tlogUpload bool) ([]byte, error) {
ctx, span := otel.Tracer("cosign").Start(ctx, "sign-blob")
defer span.End()
itracing.ActiveCtx = ctx

var payload internal.HashReader

ctx, cancel := context.WithTimeout(ctx, ro.Timeout)
Expand Down
12 changes: 9 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
github.com/open-policy-agent/opa v1.15.0
github.com/secure-systems-lab/go-securesystemslib v0.11.0
github.com/sigstore/fulcio v1.8.5
github.com/sigstore/model-validation-operator/pkg/tracing v0.0.0-20260613122948-a36fd5feae2c
github.com/sigstore/protobuf-specs v0.5.1
github.com/sigstore/rekor v1.5.2
github.com/sigstore/rekor-tiles/v2 v2.2.2-0.20260601073857-5d098a2b6443
Expand All @@ -53,6 +54,9 @@ require (
github.com/transparency-dev/merkle v0.0.2
github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1
gitlab.com/gitlab-org/api/client-go v1.23.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0
go.opentelemetry.io/otel v1.44.0
go.opentelemetry.io/otel/trace v1.44.0
golang.org/x/crypto v0.52.0
golang.org/x/oauth2 v0.36.0
golang.org/x/sync v0.20.0
Expand Down Expand Up @@ -271,10 +275,12 @@ require (
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
go.opentelemetry.io/otel v1.44.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 // indirect
go.opentelemetry.io/otel/metric v1.44.0 // indirect
go.opentelemetry.io/otel/trace v1.44.0 // indirect
go.opentelemetry.io/otel/sdk v1.44.0 // indirect
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.28.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
Expand Down
18 changes: 14 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@ github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/sigstore/fulcio v1.8.5 h1:HYTD1/L5wlBp8JxsWxUf8hmfaNBBF/x3r3p5l6tZwbA=
github.com/sigstore/fulcio v1.8.5/go.mod h1:tSLYK3JsKvJpDW1BsIsVHZgHj+f8TjXARzqIUWSsSPQ=
github.com/sigstore/model-validation-operator/pkg/tracing v0.0.0-20260613122948-a36fd5feae2c h1:l3y3OnGVK5kd3xUOvHjxW6JwYpDXaOphSm0zDO2wTUU=
github.com/sigstore/model-validation-operator/pkg/tracing v0.0.0-20260613122948-a36fd5feae2c/go.mod h1:hhrzef9B/mFrTuu3QUohVWCE/YAlGh2y5dX+kDv0Ytg=
github.com/sigstore/protobuf-specs v0.5.1 h1:/5OPaNuolRJmQfeZLayJGFXMpsRJEdgC6ah1/+7Px7U=
github.com/sigstore/protobuf-specs v0.5.1/go.mod h1:DRBzpFuE+LnvQMN10/dU6nBeKwVLGEQ6o2FovN2Rats=
github.com/sigstore/rekor v1.5.2 h1:k6pX4o1zFAzAvDbXiVIp5IHj1b0wcDaxsbsbNpuRO8o=
Expand Down Expand Up @@ -755,18 +757,26 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 h1:yI1/OhfEPy7J9eoa6Sj051C7n5dvpj0QX8g4sRchg04=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0/go.mod h1:NoUCKYWK+3ecatC4HjkRktREheMeEtrXoQxrqYFeHSc=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0 h1:DvJDOPmSWQHWywQS6lKL+pb8s3gBLOZUtw4N+mavW1I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.40.0/go.mod h1:EtekO9DEJb4/jRyN4v4Qjc2yA7AtfCBuz2FynRUWTXs=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0 h1:mS47AX77OtFfKG4vtp+84kuGSFZHTyxtXIN269vChY0=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.43.0/go.mod h1:PJnsC41lAGncJlPUniSwM81gc80GkgWJWr3cu2nKEtU=
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
go.step.sm/crypto v0.77.7 h1:6azC+pD678Vjju8yXnMDHCZJ+HzFaEmL3sCryiezTIA=
go.step.sm/crypto v0.77.7/go.mod h1:OW/2sEHwTtDKq70PvSQ5B0JGy/CrLyDKOiVy3YvZMTQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
Expand Down
7 changes: 7 additions & 0 deletions internal/tracing/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tracing

import "context"

// ActiveCtx holds the context with the active span so that HTTP requests
// created without context (e.g. inside sigstore-go) can inherit trace context.
var ActiveCtx context.Context
Loading