diff --git a/Makefile b/Makefile index f1a5da23..043033be 100644 --- a/Makefile +++ b/Makefile @@ -12,21 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -VERSION := `git describe --tags` -LDFLAGS = -ldflags "-X main.Version=$(VERSION)" - .PHONY: all all: build build-examples .PHONY: build build: - go build $(LDFLAGS) ./cmd/sigstore-go - go build $(LDFLAGS) -o conformance ./cmd/conformance + go build ./cmd/sigstore-go + go build -o conformance ./cmd/conformance .PHONY: build-examples build-examples: - go build -C ./examples/oci-image-verification $(LDFLAGS) -o oci-image-verification . - go build -C ./examples/sigstore-go-signing $(LDFLAGS) -o sigstore-go-signing . + go build -C ./examples/oci-image-verification -o oci-image-verification . + go build -C ./examples/sigstore-go-signing -o sigstore-go-signing . .PHONY: test test: diff --git a/cmd/conformance/main.go b/cmd/conformance/main.go index 332f9216..4a7031ca 100644 --- a/cmd/conformance/main.go +++ b/cmd/conformance/main.go @@ -36,7 +36,6 @@ import ( "github.com/sigstore/sigstore-go/pkg/verify" ) -var Version string var bundlePath *string var certPath *string var certOIDC *string @@ -63,7 +62,7 @@ func getTrustedRoot(staging bool) root.TrustedMaterial { } else { opts := tuf.DefaultOptions() fetcher := fetcher.DefaultFetcher{} - fetcher.SetHTTPUserAgent(util.ConstructUserAgent(Version)) + fetcher.SetHTTPUserAgent(util.ConstructUserAgent()) opts.Fetcher = &fetcher if staging { @@ -137,9 +136,8 @@ func signBundle(withRekor bool) (*protobundle.Bundle, error) { } fulcioOpts := &sign.FulcioOptions{ - BaseURL: fmt.Sprintf("https://fulcio.%s.dev", instance), - Timeout: timeout, - LibraryVersion: Version, + BaseURL: fmt.Sprintf("https://fulcio.%s.dev", instance), + Timeout: timeout, } signingOptions.CertificateProvider = sign.NewFulcio(fulcioOpts) signingOptions.CertificateProviderOptions = &sign.CertificateProviderOptions{ @@ -148,9 +146,8 @@ func signBundle(withRekor bool) (*protobundle.Bundle, error) { if withRekor { rekorOpts := &sign.RekorOptions{ - BaseURL: fmt.Sprintf("https://rekor.%s.dev", instance), - Timeout: timeout, - LibraryVersion: Version, + BaseURL: fmt.Sprintf("https://rekor.%s.dev", instance), + Timeout: timeout, } signingOptions.TransparencyLogs = append(signingOptions.TransparencyLogs, sign.NewRekor(rekorOpts)) } @@ -300,7 +297,7 @@ func main() { tr := getTrustedRoot(staging) verifierConfig := []verify.VerifierOption{} - verifierConfig = append(verifierConfig, verify.WithVersionString(Version), verify.WithoutAnyObserverTimestampsUnsafe(), verify.WithSignedCertificateTimestamps(1)) + verifierConfig = append(verifierConfig, verify.WithoutAnyObserverTimestampsUnsafe(), verify.WithSignedCertificateTimestamps(1)) if len(tr.RekorLogs()) > 0 { verifierConfig = append(verifierConfig, verify.WithOnlineVerification()) } @@ -349,7 +346,7 @@ func main() { tr := getTrustedRoot(staging) verifierConfig := []verify.VerifierOption{} - verifierConfig = append(verifierConfig, verify.WithVersionString(Version), verify.WithSignedCertificateTimestamps(1)) + verifierConfig = append(verifierConfig, verify.WithSignedCertificateTimestamps(1)) // Check bundle and trusted root for signed timestamp information bundleTimestamps, err := b.Timestamps() diff --git a/cmd/sigstore-go/main.go b/cmd/sigstore-go/main.go index cd103a3c..21abc587 100644 --- a/cmd/sigstore-go/main.go +++ b/cmd/sigstore-go/main.go @@ -37,7 +37,6 @@ import ( "github.com/sigstore/sigstore-go/pkg/verify" ) -var Version string var artifact *string var artifactDigest *string var artifactDigestAlgorithm *string @@ -105,8 +104,6 @@ func run() error { identityPolicies := []verify.PolicyOption{} var artifactPolicy verify.ArtifactPolicyOption - verifierConfig = append(verifierConfig, verify.WithVersionString(Version)) - if *requireCTlog { verifierConfig = append(verifierConfig, verify.WithSignedCertificateTimestamps(1)) } @@ -136,7 +133,7 @@ func run() error { opts := tuf.DefaultOptions() opts.RepositoryBaseURL = *tufRootURL fetcher := fetcher.DefaultFetcher{} - fetcher.SetHTTPUserAgent(util.ConstructUserAgent(Version)) + fetcher.SetHTTPUserAgent(util.ConstructUserAgent()) opts.Fetcher = &fetcher // Load the tuf root.json if provided, if not use public good diff --git a/examples/sigstore-go-signing/main.go b/examples/sigstore-go-signing/main.go index dad5c037..6548aa65 100644 --- a/examples/sigstore-go-signing/main.go +++ b/examples/sigstore-go-signing/main.go @@ -30,7 +30,6 @@ import ( "github.com/sigstore/sigstore-go/pkg/util" ) -var Version string var idToken *string var intoto *bool var tsa *bool @@ -86,7 +85,7 @@ func main() { // Get trusted_root.json fetcher := fetcher.DefaultFetcher{} - fetcher.SetHTTPUserAgent(util.ConstructUserAgent(Version)) + fetcher.SetHTTPUserAgent(util.ConstructUserAgent()) tufOptions := &tuf.Options{ Root: tuf.StagingRoot(), @@ -115,7 +114,6 @@ func main() { BaseURL: "https://fulcio.sigstage.dev", Timeout: time.Duration(30 * time.Second), Retries: 1, - LibraryVersion: Version, } opts.CertificateProvider = sign.NewFulcio(fulcioOpts) opts.CertificateProviderOptions = &sign.CertificateProviderOptions{ @@ -128,7 +126,6 @@ func main() { URL: "https://timestamp.githubapp.com/api/v1/timestamp", Timeout: time.Duration(30 * time.Second), Retries: 1, - LibraryVersion: Version, } opts.TimestampAuthorities = append(opts.TimestampAuthorities, sign.NewTimestampAuthority(tsaOpts)) @@ -141,7 +138,6 @@ func main() { BaseURL: "https://rekor.sigstage.dev", Timeout: time.Duration(90 * time.Second), Retries: 1, - LibraryVersion: Version, } opts.TransparencyLogs = append(opts.TransparencyLogs, sign.NewRekor(rekorOpts)) } diff --git a/pkg/sign/certificate.go b/pkg/sign/certificate.go index 9b897101..75ba7a6e 100644 --- a/pkg/sign/certificate.go +++ b/pkg/sign/certificate.go @@ -52,8 +52,6 @@ type FulcioOptions struct { Timeout time.Duration // Optional number of times to retry on HTTP 5XX Retries uint - // Optional version string for user agent - LibraryVersion string // Optional Transport (for dependency injection) Transport http.RoundTripper } @@ -171,7 +169,7 @@ func (f *Fulcio) GetCertificate(ctx context.Context, keypair Keypair, opts *Cert } request.Header.Add("Authorization", "Bearer "+opts.IDToken) request.Header.Add("Content-Type", "application/json") - request.Header.Add("User-Agent", util.ConstructUserAgent(f.options.LibraryVersion)) + request.Header.Add("User-Agent", util.ConstructUserAgent()) response, err = f.client.Do(request) if err != nil { diff --git a/pkg/sign/timestamping.go b/pkg/sign/timestamping.go index 5c2b8b58..55f25fa4 100644 --- a/pkg/sign/timestamping.go +++ b/pkg/sign/timestamping.go @@ -37,8 +37,6 @@ type TimestampAuthorityOptions struct { Timeout time.Duration // Optional number of times to retry on HTTP 5XX Retries uint - // Optional version string for user agent - LibraryVersion string // Optional Transport (for dependency injection) Transport http.RoundTripper } @@ -85,7 +83,7 @@ func (ta *TimestampAuthority) GetTimestamp(ctx context.Context, signature []byte return nil, err } request.Header.Add("Content-Type", "application/timestamp-query") - request.Header.Add("User-Agent", util.ConstructUserAgent(ta.options.LibraryVersion)) + request.Header.Add("User-Agent", util.ConstructUserAgent()) response, err = ta.client.Do(request) if err != nil { diff --git a/pkg/sign/transparency.go b/pkg/sign/transparency.go index 8f8a1a0f..f8cc1ec5 100644 --- a/pkg/sign/transparency.go +++ b/pkg/sign/transparency.go @@ -59,8 +59,6 @@ type RekorOptions struct { Timeout time.Duration // Optional number of times to retry Retries uint - // Optional version string for user agent - LibraryVersion string // Optional client (for dependency injection) Client RekorClient } @@ -128,7 +126,7 @@ func (r *Rekor) GetTransparencyLogEntry(pubKeyPEM []byte, b *protobundle.Bundle) params.SetProposedEntry(proposedEntry) if r.options.Client == nil { - client, err := client.GetRekorClient(r.options.BaseURL, client.WithUserAgent(util.ConstructUserAgent(r.options.LibraryVersion)), client.WithRetryCount(r.options.Retries)) + client, err := client.GetRekorClient(r.options.BaseURL, client.WithUserAgent(util.ConstructUserAgent()), client.WithRetryCount(r.options.Retries)) if err != nil { return err } diff --git a/pkg/tuf/client.go b/pkg/tuf/client.go index 2f37962d..134b2d73 100644 --- a/pkg/tuf/client.go +++ b/pkg/tuf/client.go @@ -61,7 +61,7 @@ func New(opts *Options) (*Client, error) { c.cfg.Fetcher = opts.Fetcher } else { fetcher := fetcher.DefaultFetcher{} - fetcher.SetHTTPUserAgent(util.ConstructUserAgent("")) + fetcher.SetHTTPUserAgent(util.ConstructUserAgent()) c.cfg.Fetcher = &fetcher } diff --git a/pkg/util/util.go b/pkg/util/util.go index 617b1b7d..4ab68528 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -14,11 +14,23 @@ package util -func ConstructUserAgent(version string) string { +import ( + "runtime/debug" +) + +func ConstructUserAgent() string { userAgent := "sigstore-go" - if version != "" { - userAgent += "/" - userAgent += version + + buildInfo, ok := debug.ReadBuildInfo() + if !ok { + return userAgent + } + + for _, eachDep := range buildInfo.Deps { + if eachDep.Path == "github.com/sigstore/sigstore-go" { + userAgent += "/" + userAgent += eachDep.Version + } } return userAgent diff --git a/pkg/verify/signed_entity.go b/pkg/verify/signed_entity.go index 90046de5..45bc014d 100644 --- a/pkg/verify/signed_entity.go +++ b/pkg/verify/signed_entity.go @@ -70,8 +70,6 @@ type VerifierConfig struct { // nolint: revive // rather than a provided signed or log timestamp. Most workflows will // not use this option weDoNotExpectAnyObserverTimestamps bool - // optional sigstore-go version to use in user agent for outbound requests - version string } type VerifierOption func(*VerifierConfig) error @@ -204,15 +202,6 @@ func WithoutAnyObserverTimestampsUnsafe() VerifierOption { } } -// WithVersionString is used to optionally specify a specific version of -// sigstore-go, to use in user agent for outbound requests -func WithVersionString(version string) VerifierOption { - return func(c *VerifierConfig) error { - c.version = version - return nil - } -} - func (c *VerifierConfig) Validate() error { if !c.requireObserverTimestamps && !c.weExpectSignedTimestamps && !c.requireIntegratedTimestamps && !c.weDoNotExpectAnyObserverTimestamps { return errors.New("when initializing a new SignedEntityVerifier, you must specify at least one of " + @@ -627,7 +616,7 @@ func (v *SignedEntityVerifier) VerifyTransparencyLogInclusion(entity SignedEntit if v.config.weExpectTlogEntries { // log timestamps should be verified if with WithIntegratedTimestamps or WithObserverTimestamps is used verifiedTlogTimestamps, err := VerifyArtifactTransparencyLog(entity, v.trustedMaterial, v.config.tlogEntriesThreshold, - v.config.requireIntegratedTimestamps || v.config.requireObserverTimestamps, v.config.performOnlineVerification, v.config.version) + v.config.requireIntegratedTimestamps || v.config.requireObserverTimestamps, v.config.performOnlineVerification) if err != nil { return nil, err } diff --git a/pkg/verify/tlog.go b/pkg/verify/tlog.go index ff125d26..7cc82751 100644 --- a/pkg/verify/tlog.go +++ b/pkg/verify/tlog.go @@ -42,7 +42,7 @@ import ( // that must be verified. // // If online is true, the log entry is verified against the Rekor server. -func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.TrustedMaterial, logThreshold int, trustIntegratedTime, online bool, version string) ([]time.Time, error) { //nolint:revive +func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.TrustedMaterial, logThreshold int, trustIntegratedTime, online bool) ([]time.Time, error) { //nolint:revive entries, err := entity.TlogEntries() if err != nil { return nil, err @@ -121,7 +121,7 @@ func VerifyArtifactTransparencyLog(entity SignedEntity, trustedMaterial root.Tru continue } - client, err := getRekorClient(tlogVerifier.BaseURL, version) + client, err := getRekorClient(tlogVerifier.BaseURL) if err != nil { return nil, err } @@ -199,8 +199,8 @@ func getVerifier(publicKey crypto.PublicKey, hashFunc crypto.Hash) (*signature.V return &verifier, nil } -func getRekorClient(baseURL, version string) (*rekorGeneratedClient.Rekor, error) { - client, err := rekorClient.GetRekorClient(baseURL, rekorClient.WithUserAgent(util.ConstructUserAgent(version))) +func getRekorClient(baseURL string) (*rekorGeneratedClient.Rekor, error) { + client, err := rekorClient.GetRekorClient(baseURL, rekorClient.WithUserAgent(util.ConstructUserAgent())) if err != nil { return nil, err } diff --git a/pkg/verify/tlog_test.go b/pkg/verify/tlog_test.go index ae708712..3ff4845c 100644 --- a/pkg/verify/tlog_test.go +++ b/pkg/verify/tlog_test.go @@ -36,12 +36,12 @@ func TestTlogVerifier(t *testing.T) { assert.NoError(t, err) var ts []time.Time - ts, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, true, false, "") + ts, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, true, false) assert.NoError(t, err) // 1 verified timestamp assert.Len(t, ts, 1) - ts, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, false, false, "") + ts, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, false, false) assert.NoError(t, err) // 0 verified timestamps, since integrated timestamps are ignored assert.Len(t, ts, 0) @@ -49,7 +49,7 @@ func TestTlogVerifier(t *testing.T) { virtualSigstore2, err := ca.NewVirtualSigstore() assert.NoError(t, err) - _, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore2, 1, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore2, 1, true, false) assert.Error(t, err) // different sigstore instance should fail to verify // Attempt to use tlog with integrated time outside certificate validity. @@ -59,7 +59,7 @@ func TestTlogVerifier(t *testing.T) { entity, err = virtualSigstore.AttestAtTime("foo@fighters.com", "issuer", statement, time.Now().Add(30*time.Minute)) assert.NoError(t, err) - _, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(entity, virtualSigstore, 1, true, false) assert.Error(t, err) } @@ -96,11 +96,11 @@ func TestIgnoredTLogEntries(t *testing.T) { assert.NoError(t, err) // success: entry that cannot be verified is ignored - _, err = verify.VerifyArtifactTransparencyLog(&oneTrustedOneUntrustedLogEntry{entity, untrustedEntity}, virtualSigstore, 1, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(&oneTrustedOneUntrustedLogEntry{entity, untrustedEntity}, virtualSigstore, 1, true, false) assert.NoError(t, err) // failure: threshold of 2 is not met since 1 untrusted entry is ignored - _, err = verify.VerifyArtifactTransparencyLog(&oneTrustedOneUntrustedLogEntry{entity, untrustedEntity}, virtualSigstore, 2, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(&oneTrustedOneUntrustedLogEntry{entity, untrustedEntity}, virtualSigstore, 2, true, false) assert.Error(t, err) } @@ -138,7 +138,7 @@ func TestInvalidTLogEntries(t *testing.T) { assert.NoError(t, err) // failure: threshold of 1 is not met with invalid entry - _, err = verify.VerifyArtifactTransparencyLog(&invalidTLogEntity{entity}, virtualSigstore, 1, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(&invalidTLogEntity{entity}, virtualSigstore, 1, true, false) assert.Error(t, err) if err.Error() != "entry must contain an inclusion proof and/or promise" { t.Errorf("expected error with missing proof/promises, got: %v", err.Error()) @@ -162,7 +162,7 @@ func TestNoTLogEntries(t *testing.T) { assert.NoError(t, err) // failure: threshold of 1 is not met with no entries - _, err = verify.VerifyArtifactTransparencyLog(&noTLogEntity{entity}, virtualSigstore, 1, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(&noTLogEntity{entity}, virtualSigstore, 1, true, false) assert.Error(t, err) if !strings.Contains(err.Error(), "not enough verified log entries from transparency log") { t.Errorf("expected error with timestamp threshold, got: %v", err.Error()) @@ -190,6 +190,6 @@ func TestDuplicateTlogEntries(t *testing.T) { entity, err := virtualSigstore.Attest("foofighters@example.com", "issuer", statement) assert.NoError(t, err) - _, err = verify.VerifyArtifactTransparencyLog(&dupTlogEntity{entity}, virtualSigstore, 1, true, false, "") + _, err = verify.VerifyArtifactTransparencyLog(&dupTlogEntity{entity}, virtualSigstore, 1, true, false) assert.Error(t, err) // duplicate tlog entries should fail to verify }