diff --git a/internal/attest/attest.go b/internal/attest/attest.go index 7a32db04..8e9476b6 100644 --- a/internal/attest/attest.go +++ b/internal/attest/attest.go @@ -26,15 +26,18 @@ import ( "sort" "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/config" + gitconfig "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/storage" + "github.com/go-openapi/strfmt" "github.com/jonboulle/clockwork" "github.com/sigstore/cosign/v2/cmd/cosign/cli/sign" "github.com/sigstore/cosign/v2/pkg/cosign/attestation" "github.com/sigstore/cosign/v2/pkg/types" + utils "github.com/sigstore/gitsign/internal" + gitsignconfig "github.com/sigstore/gitsign/internal/config" rekorclient "github.com/sigstore/rekor/pkg/generated/client" "github.com/sigstore/rekor/pkg/generated/models" dssesig "github.com/sigstore/sigstore/pkg/signature/dsse" @@ -68,14 +71,14 @@ func NewAttestor(repo *git.Repository, sv *sign.SignerVerifier, rekorFn rekorUpl } // WriteFile is a convenience wrapper around WriteAttestation that takes in a filepath rather than an io.Reader. -func (a *Attestor) WriteFile(ctx context.Context, refName string, sha plumbing.Hash, path, attType string) (plumbing.Hash, error) { +func (a *Attestor) WriteFile(ctx context.Context, refName string, sha plumbing.Hash, path, attType string, config *gitsignconfig.Config) (plumbing.Hash, error) { f, err := os.Open(path) if err != nil { return plumbing.ZeroHash, err } defer f.Close() - return a.WriteAttestation(ctx, refName, sha, f, attType) + return a.WriteAttestation(ctx, refName, sha, f, attType, config) } type Reader interface { @@ -107,7 +110,7 @@ func NewNamedReader(r io.Reader, name string) Reader { // sha: Commit SHA you are attesting to. // input: Attestation file input. // attType: Attestation type. See [attestation.GenerateStatement] for allowed values. -func (a *Attestor) WriteAttestation(ctx context.Context, refName string, sha plumbing.Hash, input Reader, attType string) (plumbing.Hash, error) { +func (a *Attestor) WriteAttestation(ctx context.Context, refName string, sha plumbing.Hash, input Reader, attType string, config *gitsignconfig.Config) (plumbing.Hash, error) { b, err := io.ReadAll(input) if err != nil { return plumbing.ZeroHash, err @@ -123,7 +126,7 @@ func (a *Attestor) WriteAttestation(ctx context.Context, refName string, sha plu // Step 1: Write the files // Create the DSSE, sign it, store it. - sig, err := a.signPayload(ctx, sha, b, attType) + sig, err := a.signPayload(ctx, sha, b, attType, config) if err != nil { return plumbing.ZeroHash, err } @@ -175,7 +178,7 @@ func (a *Attestor) WriteAttestation(ctx context.Context, refName string, sha plu // Step 3: Make the commit // Grab the user from the repository config so we know who to attribute the commit to. - cfg, err := a.repo.ConfigScoped(config.GlobalScope) + cfg, err := a.repo.ConfigScoped(gitconfig.GlobalScope) if err != nil { return plumbing.ZeroHash, err } @@ -221,7 +224,7 @@ func encode(store storage.Storer, enc Encoder) (plumbing.Hash, error) { return store.SetEncodedObject(obj) } -func (a *Attestor) signPayload(ctx context.Context, sha plumbing.Hash, b []byte, attType string) ([]byte, error) { +func (a *Attestor) signPayload(ctx context.Context, sha plumbing.Hash, b []byte, attType string, config *gitsignconfig.Config) ([]byte, error) { // Generate attestation sh, err := attestation.GenerateStatement(attestation.GenerateOpts{ Predicate: bytes.NewBuffer(b), @@ -242,8 +245,15 @@ func (a *Attestor) signPayload(ctx context.Context, sha plumbing.Hash, b []byte, return nil, err } + rekorHost, rekorBasePath := utils.StripUrl(config.Rekor) + tc := &rekorclient.TransportConfig{ + Host: rekorHost, + BasePath: rekorBasePath, + } + rcfg := rekorclient.NewHTTPClientWithConfig(strfmt.Default, tc) + // Upload to rekor - entry, err := a.rekorFn(ctx, rekorclient.Default, envelope, a.sv.Cert) + entry, err := a.rekorFn(ctx, rcfg, envelope, a.sv.Cert) if err != nil { return nil, err } diff --git a/internal/attest/attest_test.go b/internal/attest/attest_test.go index 55c7daf6..19480b01 100644 --- a/internal/attest/attest_test.go +++ b/internal/attest/attest_test.go @@ -37,6 +37,7 @@ import ( "github.com/jonboulle/clockwork" "github.com/secure-systems-lab/go-securesystemslib/dsse" "github.com/sigstore/cosign/v2/cmd/cosign/cli/sign" + gitsignconfig "github.com/sigstore/gitsign/internal/config" "github.com/sigstore/rekor/pkg/generated/client" "github.com/sigstore/rekor/pkg/generated/models" "github.com/sigstore/sigstore/pkg/signature" @@ -72,7 +73,7 @@ func TestAttestCommitRef(t *testing.T) { content := readFile(t, filepath.Join("testdata/", name)) attestor := NewAttestor(repo, sv, fakeRekor) - + cfg, _ := gitsignconfig.Get() fc := []fileContent{ { Name: filepath.Join(sha.String(), "test.json"), @@ -84,7 +85,7 @@ func TestAttestCommitRef(t *testing.T) { }, } t.Run("base", func(t *testing.T) { - attest1, err := attestor.WriteAttestation(ctx, CommitRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest1, err := attestor.WriteAttestation(ctx, CommitRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } @@ -93,7 +94,7 @@ func TestAttestCommitRef(t *testing.T) { t.Run("noop", func(t *testing.T) { // Write same attestation to the same commit - should be a no-op. - attest2, err := attestor.WriteAttestation(ctx, CommitRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest2, err := attestor.WriteAttestation(ctx, CommitRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } @@ -111,7 +112,7 @@ func TestAttestCommitRef(t *testing.T) { t.Fatal(err) } - attest3, err := attestor.WriteAttestation(ctx, CommitRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest3, err := attestor.WriteAttestation(ctx, CommitRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } @@ -151,6 +152,8 @@ func TestAttestTreeRef(t *testing.T) { attestor := NewAttestor(repo, sv, fakeRekor) + cfg, _ := gitsignconfig.Get() + fc := []fileContent{ { Name: filepath.Join(sha.String(), "test.json"), @@ -162,7 +165,7 @@ func TestAttestTreeRef(t *testing.T) { }, } t.Run("base", func(t *testing.T) { - attest1, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest1, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } @@ -171,7 +174,7 @@ func TestAttestTreeRef(t *testing.T) { t.Run("noop", func(t *testing.T) { // Write same attestation to the same commit - should be a no-op. - attest2, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest2, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } @@ -189,7 +192,7 @@ func TestAttestTreeRef(t *testing.T) { } sha = resolveTree(t, repo, sha) - attest3, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest3, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } @@ -200,7 +203,7 @@ func TestAttestTreeRef(t *testing.T) { // Make a new commit, write new attestation. sha = resolveTree(t, repo, writeRepo(t, w, fs, "testdata/bar.txt")) - attest3, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom") + attest3, err := attestor.WriteAttestation(ctx, TreeRef, sha, NewNamedReader(bytes.NewBufferString(content), name), "custom", cfg) if err != nil { t.Fatalf("WriteAttestation: %v", err) } diff --git a/internal/commands/attest/attest.go b/internal/commands/attest/attest.go index a940ffda..f4273e5e 100644 --- a/internal/commands/attest/attest.go +++ b/internal/commands/attest/attest.go @@ -79,14 +79,14 @@ func (o *options) Run(ctx context.Context) error { OIDCIssuer: o.Config.Issuer, OIDCClientID: o.Config.ClientID, }) - if err != nil { - return fmt.Errorf("getting signer: %w", err) - } + // if err != nil { + // return fmt.Errorf("getting signer: %w", err) + // } defer sv.Close() attestor := attest.NewAttestor(repo, sv, cosign.TLogUploadInTotoAttestation) - out, err := attestor.WriteFile(ctx, refName, sha, o.FlagPath, o.FlagAttestationType) + out, err := attestor.WriteFile(ctx, refName, sha, o.FlagPath, o.FlagAttestationType, o.Config) if err != nil { return err } diff --git a/internal/utils.go b/internal/utils.go index 57761a91..136b5036 100644 --- a/internal/utils.go +++ b/internal/utils.go @@ -19,6 +19,7 @@ import ( "crypto/sha1" // #nosec G505 "crypto/x509" "encoding/hex" + "net/url" ) // certHexFingerprint calculated the hex SHA1 fingerprint of a certificate. @@ -35,3 +36,9 @@ func certFingerprint(cert *x509.Certificate) []byte { fpr := sha1.Sum(cert.Raw) // nolint:gosec return fpr[:] } + +// StripUrl returns the baseHost with the basePath given a full endpoint +func StripUrl(endpoint string) (string, string) { + u, _ := url.Parse(endpoint) + return u.Host, u.Path +} diff --git a/internal/utils_test.go b/internal/utils_test.go new file mode 100644 index 00000000..3e3a18fd --- /dev/null +++ b/internal/utils_test.go @@ -0,0 +1,27 @@ +// Copyright 2022 The Sigstore Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import ( + "testing" +) + +func TestStripUrl(t *testing.T) { + endpoint := "https://private.rekor.com/rekor" + host, basePath := StripUrl(endpoint) + if host != "private.rekor.com" || basePath != "/rekor" { + t.Fatalf("Host and/or BasePath are not correct") + } +}