Skip to content

Commit

Permalink
Add options for Rekor client, make public key fetcher configurable. (#…
Browse files Browse the repository at this point in the history
…399)

Also makes the default public key fetcher match the behavior of cosign,
which also fixes a bug where verify was getting keys from Rekor
directly.

Signed-off-by: Billy Lynch <billy@chainguard.dev>
  • Loading branch information
wlynch committed Nov 9, 2023
1 parent 26b5e0e commit cd66ccb
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 21 deletions.
2 changes: 1 addition & 1 deletion internal/commands/root/sign.go
Expand Up @@ -73,7 +73,7 @@ func commandSign(o *options, s *gsio.Streams, args ...string) error {
return fmt.Errorf("failed to read message from stdin: %w", err)
}

rekor, err := rekor.NewClient(o.Config.Rekor)
rekor, err := rekor.NewClientContext(ctx, o.Config.Rekor)
if err != nil {
return fmt.Errorf("failed to create rekor client: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/gitsign/gitsign.go
Expand Up @@ -74,7 +74,7 @@ func NewVerifierWithCosignOpts(ctx context.Context, cfg *config.Config, opts *co
return nil, fmt.Errorf("error creating Git verifier: %w", err)
}

rekor, err := rekorinternal.NewClient(cfg.Rekor)
rekor, err := rekorinternal.NewClientContext(ctx, cfg.Rekor)
if err != nil {
return nil, fmt.Errorf("failed to create rekor client: %w", err)
}
Expand Down
10 changes: 9 additions & 1 deletion internal/rekor/client.go
Expand Up @@ -15,11 +15,19 @@
package rekor

import (
"context"

gitrekor "github.com/sigstore/gitsign/pkg/rekor"
rekor "github.com/sigstore/rekor/pkg/client"
)

// NewClient returns a new Rekor client with common client options set.
// Deprecated: Use NewClientContext instead.
func NewClient(url string) (*gitrekor.Client, error) {
return gitrekor.New(url, rekor.WithUserAgent("gitsign"))
return NewClientContext(context.TODO(), url)
}

// NewClientContext returns a new Rekor client with common client options set.
func NewClientContext(ctx context.Context, url string) (*gitrekor.Client, error) {
return gitrekor.NewWithOptions(ctx, url, gitrekor.WithClientOption(rekor.WithUserAgent("gitsign")))
}
45 changes: 45 additions & 0 deletions pkg/rekor/option.go
@@ -0,0 +1,45 @@
//
// Copyright 2023 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 rekor

import (
"context"

"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/rekor/pkg/client"
)

type Option func(*options)

type options struct {
rekorPublicKeys CosignRekorKeyProvider
clientOpts []client.Option
}

// CosignRekorKeyProvider is a function that returns the Rekor public keys in cosign's specialized format.
type CosignRekorKeyProvider func(ctx context.Context) (*cosign.TrustedTransparencyLogPubKeys, error)

func WithCosignRekorKeyProvider(f CosignRekorKeyProvider) Option {
return func(o *options) {
o.rekorPublicKeys = f
}
}

func WithClientOption(opts ...client.Option) Option {
return func(o *options) {
o.clientOpts = opts
}
}
34 changes: 16 additions & 18 deletions pkg/rekor/rekor.go
Expand Up @@ -43,7 +43,6 @@ import (
hashedrekord_v001 "github.com/sigstore/rekor/pkg/types/hashedrekord/v0.0.1"
rekord_v001 "github.com/sigstore/rekor/pkg/types/rekord/v0.0.1"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/tuf"
)

// Verifier represents a mechanism to get and verify Rekor entries for the given Git data.
Expand All @@ -64,12 +63,26 @@ type Client struct {
publicKeys *cosign.TrustedTransparencyLogPubKeys
}

// Deprecated: Use NewWithOptions instead.
func New(url string, opts ...rekor.Option) (*Client, error) {
c, err := rekor.GetRekorClient(url, opts...)
return NewWithOptions(context.TODO(), url, WithClientOption(opts...))
}

func NewWithOptions(ctx context.Context, url string, opts ...Option) (*Client, error) {
// Defaults
o := &options{
rekorPublicKeys: cosign.GetRekorPubs,
}
for _, f := range opts {
f(o)
}

c, err := rekor.GetRekorClient(url, o.clientOpts...)
if err != nil {
return nil, err
}
pubs, err := rekorPubsFromClient(c)

pubs, err := o.rekorPublicKeys(ctx)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -158,21 +171,6 @@ func (c *Client) findTLogEntriesByPayloadAndPK(ctx context.Context, payload, pub
return searchIndex.GetPayload(), nil
}

// rekorPubsFromClient returns a RekorPubKey keyed by the log ID from the Rekor client.
// NOTE: This **must not** be used in the verification path, but may be used in the
// sign path to validate return responses are consistent from Rekor.
func rekorPubsFromClient(rekorClient *client.Rekor) (*cosign.TrustedTransparencyLogPubKeys, error) {
publicKeys := cosign.NewTrustedTransparencyLogPubKeys()
pubOK, err := rekorClient.Pubkey.GetPublicKey(nil)
if err != nil {
return nil, fmt.Errorf("unable to fetch rekor public key from rekor: %w", err)
}
if err := publicKeys.AddTransparencyLogPubKey([]byte(pubOK.Payload), tuf.Active); err != nil {
return nil, fmt.Errorf("constructRekorPubKey: %w", err)
}
return &publicKeys, nil
}

// Verify verifies a commit using online verification.
//
// This is done by:
Expand Down

0 comments on commit cd66ccb

Please sign in to comment.