Skip to content

Commit

Permalink
resolves #516 adds support for private rekor instances for gitsign at…
Browse files Browse the repository at this point in the history
…test

Signed-off-by: Ahmed Alsabag <[email protected]>
  • Loading branch information
aalsabag committed Jun 2, 2024
1 parent 2818752 commit bb1bd3e
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 20 deletions.
26 changes: 18 additions & 8 deletions internal/attest/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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),
Expand All @@ -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
}
Expand Down
19 changes: 11 additions & 8 deletions internal/attest/attest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"),
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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"),
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions internal/commands/attest/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Check failure on line 85 in internal/commands/attest/attest.go

View workflow job for this annotation

GitHub Actions / lint

SA5001: should check returned error before deferring sv.Close() (staticcheck)

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
}
Expand Down
7 changes: 7 additions & 0 deletions internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"crypto/sha1" // #nosec G505
"crypto/x509"
"encoding/hex"
"net/url"
)

// certHexFingerprint calculated the hex SHA1 fingerprint of a certificate.
Expand All @@ -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) {

Check failure on line 41 in internal/utils.go

View workflow job for this annotation

GitHub Actions / lint

var-naming: func StripUrl should be StripURL (revive)

Check failure on line 41 in internal/utils.go

View workflow job for this annotation

GitHub Actions / lint

ST1003: func StripUrl should be StripURL (stylecheck)
u, _ := url.Parse(endpoint)
return u.Host, u.Path
}
27 changes: 27 additions & 0 deletions internal/utils_test.go
Original file line number Diff line number Diff line change
@@ -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")
}
}

0 comments on commit bb1bd3e

Please sign in to comment.