Skip to content

Commit c45c3e2

Browse files
committed
Rework options sets
This commit modifies the options sets to brake them into more logical options that can be used to init verifiers and pass to verification operations. Signed-off-by: Adolfo García Veytia (Puerco) <[email protected]>
1 parent 6aa841b commit c45c3e2

File tree

5 files changed

+171
-95
lines changed

5 files changed

+171
-95
lines changed

options/bundle.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-FileCopyrightText: Copyright 2025 Carabiner Systems, Inc
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package options
5+
6+
// SigstoreVerification configures how we verify signatures using a particular
7+
// instance.
8+
type SigstoreVerification struct {
9+
// ExpectedIssuer and ExpectedSan define the issuer and SAN to look for in
10+
// the fulcio cert. For a broader matching behavior, choose the *Regex
11+
// alternatives.
12+
//
13+
// Verification will fail if thse are not set. To skip the identity check
14+
// set SkipIdentityCheck to true.
15+
ExpectedIssuer string
16+
ExpectedIssuerRegex string
17+
ExpectedSan string
18+
ExpectedSanRegex string
19+
20+
// SkipIdentityCheck makes the verifier skip the identity check. This
21+
// will ignore any setting in ExpectedIssuer ExpectedIssuerRegex
22+
// ExpectedSan or ExpectedSanRegex
23+
SkipIdentityCheck bool
24+
25+
// Artifact digest to check when verifier in addition to the signature
26+
ArtifactDigestAlgo string
27+
ArtifactDigest string
28+
}
29+
30+
type BundleVerifier struct {
31+
// RootsFile path to roots file
32+
RootsFile string
33+
}

options/signer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ var DefaultSigstore = Sigstore{
2929

3030
var DefaultSigner = Signer{
3131
TufOptions: tuf.TufOptions{
32-
TufRootURL: tuf.SigstorePublicGoodBaseURL,
32+
// TufRootURL: tuf.SigstorePublicGoodBaseURL,
3333
TufRootPath: "",
3434
Fetcher: tuf.Defaultfetcher(),
3535
},

options/sigstore.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,39 +9,55 @@ import (
99
"net/url"
1010

1111
"github.com/spf13/cobra"
12+
13+
"github.com/carabiner-dev/signer/internal/tuf"
1214
)
1315

1416
// Sigstore options to control how signer handles signing with sigstore
1517
type Sigstore struct {
18+
// Embed the tuf options struct
19+
tuf.TufOptions
20+
1621
Timestamp bool
1722

1823
// AppendToRekor controls if the signing operation is recorded into the
1924
// transparency log.
20-
AppendToRekor bool
25+
AppendToRekor bool `json:"rekor-append"`
2126
DisableSTS bool
2227

2328
// FulcioURL url of the Fulcio CA (defaults to the public good instance)
24-
FulcioURL string
29+
FulcioURL string `json:"fulcio-url"`
2530

2631
// RekorURL url of the Rekor transparency log (defaults to the public good instance)
27-
RekorURL string
32+
RekorURL string `json:"rekor-url"`
2833

2934
// Hide the OIDC options in the CLI --help
3035
HideOIDCOptions bool
3136

3237
// OidcRedirectURL defines the URL that the browser will redirect to.
3338
// if the port is set to 0, bind will randomize it to a high number
3439
// port before starting the OIDC flow.
35-
OidcRedirectURL string
40+
OidcRedirectURL string `json:"oidc-redirect-url"`
3641

3742
// OIDC token issuer endpoint
38-
OidcIssuer string
43+
OidcIssuer string `json:"oidc-issuer"`
3944

4045
// Client ID to stamp on the tokens
41-
OidcClientID string
46+
OidcClientID string `json:"oidc-client-id"`
4247

4348
// Client secret to pass in OIDC calls
44-
OidcClientSecret string
49+
OidcClientSecret string `json:"oidc-client-secret"`
50+
51+
// Time stamp verification options
52+
53+
// Look for a signed timestamp in the cert and verify with the CTLog Auth
54+
RequireCTlog bool `json:"require-ct-log"`
55+
// Verify the cert validity in the transparency log
56+
RequireTlog bool `json:"require-tlog"`
57+
// Verify the certificate validity time with a signed timestamp
58+
RequireSignedTimestamps bool `json:"require-signed-timestamps"`
59+
// Allow no timestamp, for keys instead of certs
60+
RequireObserverTimestamp bool `json:"require-observer-timestamp"`
4561
}
4662

4763
// Verify checks the integrity of the sigstore options

options/verification.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-FileCopyrightText: Copyright 2025 Carabiner Systems, Inc
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package options
5+
6+
import (
7+
"crypto/sha256"
8+
"fmt"
9+
"regexp"
10+
)
11+
12+
type VerificationOptFunc func(*Verification) error
13+
14+
// Verification options are generic options that all the Verify* functions take
15+
type Verification struct {
16+
SigstoreVerification
17+
KeyVerification
18+
}
19+
20+
var DefaultVerification = Verification{}
21+
22+
// WithExpectedIdentity serts the ExpectedIssuer and ExptectedSan options
23+
// and unsets the regex alternatives
24+
func WithExpectedIdentity(issuer, san string) VerificationOptFunc {
25+
return func(v *Verification) error {
26+
if issuer != "" {
27+
v.ExpectedIssuerRegex = ""
28+
v.ExpectedIssuer = issuer
29+
}
30+
31+
if san != "" {
32+
v.ExpectedSanRegex = ""
33+
v.ExpectedSan = san
34+
}
35+
return nil
36+
}
37+
}
38+
39+
// WithExpectedIdentityRegex sets the ExpectedIssuerRegex and ExptectedSanRegex
40+
// options and unsets the non-regex alternatives.
41+
func WithExpectedIdentityRegex(issuer, san string) VerificationOptFunc {
42+
return func(v *Verification) error {
43+
if issuer != "" {
44+
if _, err := regexp.Compile(issuer); err != nil {
45+
return fmt.Errorf("compiling issuer regex: %w", err)
46+
}
47+
v.ExpectedIssuerRegex = issuer
48+
v.ExpectedIssuer = ""
49+
}
50+
51+
if san != "" {
52+
if _, err := regexp.Compile(san); err != nil {
53+
return fmt.Errorf("compiling SAN regex: %w", err)
54+
}
55+
v.ExpectedSanRegex = san
56+
v.ExpectedSan = ""
57+
}
58+
return nil
59+
}
60+
}
61+
62+
// WithSkipIdentityCheck instructs the verifier to not check the signature
63+
// identities, only the signed payload will be checked.
64+
func WithSkipIdentityCheck(yesno bool) VerificationOptFunc {
65+
return func(v *Verification) error {
66+
v.SkipIdentityCheck = yesno
67+
return nil
68+
}
69+
}
70+
71+
// WithArtifactData hashes the artifact data to verify along the signature.
72+
// This is required for message verifications
73+
func WithArtifactData(data []byte) VerificationOptFunc {
74+
return func(opts *Verification) error {
75+
s256 := sha256.New()
76+
s256.Write(data)
77+
hashedBytes := s256.Sum(nil)
78+
79+
opts.ArtifactDigest = fmt.Sprintf("%x", hashedBytes)
80+
opts.ArtifactDigestAlgo = "sha256"
81+
return nil
82+
}
83+
}

options/verifier.go

Lines changed: 31 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -5,107 +5,51 @@ package options
55

66
import (
77
"crypto"
8-
"crypto/sha256"
9-
"fmt"
10-
"regexp"
11-
12-
"github.com/carabiner-dev/signer/internal/tuf"
8+
_ "embed"
139
)
1410

15-
type VerifierOptFunc func(*Verifier) error
16-
17-
type Verifier struct {
18-
tuf.TufOptions
19-
// Artifact digest to check when verifier in addition to the signature
20-
ArtifactDigestAlgo string
21-
ArtifactDigest string
22-
23-
// ExpectedIssuer and ExpectedSan define the issuer and SAN to look for in
24-
// the fulcio cert. For a broader matching behavior, choose the *Regex
25-
// alternatives.
26-
// Verification will fail if thse are not set. To skip the identity check
27-
// set SkipIdentityCheck to true.
28-
ExpectedIssuer string
29-
ExpectedIssuerRegex string
30-
ExpectedSan string
31-
ExpectedSanRegex string
11+
//go:embed sigstore-roots.json
12+
var defaultRoots []byte
3213

33-
// SkipIdentityCheck makes the verifier skip the identity check. This
34-
// will ignore any setting in ExpectedIssuer ExpectedIssuerRegex
35-
// ExpectedSan or ExpectedSanRegex
36-
SkipIdentityCheck bool
14+
type VerifierOptFunc func(*Verifier)
3715

38-
RequireCTlog bool
39-
RequireTimestamp bool
40-
RequireTlog bool
41-
42-
// Public keys to verify DSSE envelopes
16+
// KeyVerification options
17+
type KeyVerification struct {
4318
PubKeys []crypto.PublicKey
4419
}
4520

46-
var DefaultVerifier = Verifier{
47-
TufOptions: tuf.TufOptions{
48-
TufRootURL: tuf.SigstorePublicGoodBaseURL,
49-
TufRootPath: "",
50-
Fetcher: tuf.Defaultfetcher(),
51-
},
52-
ArtifactDigestAlgo: "sha256",
53-
RequireCTlog: true,
54-
RequireTimestamp: true,
55-
RequireTlog: true,
56-
}
21+
// Verifier options
22+
type Verifier struct {
23+
// The verifier options embed a set of verification options. These are
24+
// treated as defaults when calling the sigstore/dsse verifiers
25+
Verification
5726

58-
// WithExpectedIdentity serts the ExpectedIssuer and ExptectedSan options
59-
// and unsets the regex alternatives
60-
func WithExpectedIdentity(issuer, san string) VerifierOptFunc {
61-
return func(v *Verifier) error {
62-
v.ExpectedIssuerRegex = ""
63-
v.ExpectedSanRegex = ""
64-
v.ExpectedIssuer = issuer
65-
v.ExpectedSan = san
66-
return nil
67-
}
68-
}
27+
// SigstoreRootsPath is the path to a sigstore roots file
28+
SigstoreRootsPath string
6929

70-
// WithExpectedIdentityRegex sets the ExpectedIssuerRegex and ExptectedSanRegex
71-
// options and unsets the non-regex alternatives.
72-
func WithExpectedIdentityRegex(issuer, san string) VerifierOptFunc {
73-
return func(v *Verifier) error {
74-
// Check the regular expressions
75-
if _, err := regexp.Compile(issuer); err != nil {
76-
return fmt.Errorf("compiling issuer regex: %w", err)
77-
}
78-
if _, err := regexp.Compile(san); err != nil {
79-
return fmt.Errorf("compiling SAN regex: %w", err)
80-
}
30+
// SigstoreRootsData holds raw json with data about the configured roots
31+
SigstoreRootsData []byte
8132

82-
v.ExpectedIssuerRegex = issuer
83-
v.ExpectedSanRegex = san
84-
v.ExpectedIssuer = ""
85-
v.ExpectedSan = ""
86-
return nil
87-
}
33+
// // Public keys to verify DSSE envelopes
34+
// PubKeys []crypto.PublicKey
8835
}
8936

90-
// WithSkipIdentityCheck instructs the verifier to not check the signature
91-
// identities, only the signed payload will be checked.
92-
func WithSkipIdentityCheck(yesno bool) VerifierOptFunc {
93-
return func(v *Verifier) error {
94-
v.SkipIdentityCheck = yesno
95-
return nil
96-
}
37+
// DefaultVerifier default options to configure the verifier
38+
var DefaultVerifier = Verifier{
39+
Verification: DefaultVerification,
40+
SigstoreRootsData: defaultRoots, // Embedded data from the file
9741
}
9842

99-
// WithArtifactData hashes the artifact data to verify along the signature.
100-
// This is required for message verifications
101-
func WithArtifactData(data []byte) VerifierOptFunc {
102-
return func(opts *Verifier) error {
103-
s256 := sha256.New()
104-
s256.Write(data)
105-
hashedBytes := s256.Sum(nil)
43+
// WithSigstoreRootsPath sets the path to the sigstore roots configuration file
44+
func WithSigstoreRootsPath(path string) VerifierOptFunc {
45+
return func(v *Verifier) {
46+
v.SigstoreRootsPath = path
47+
}
48+
}
10649

107-
opts.ArtifactDigest = fmt.Sprintf("%x", hashedBytes)
108-
opts.ArtifactDigestAlgo = "sha256"
109-
return nil
50+
// WithSigstoreRootsData sets the sigstore roots data from raw json
51+
func WithSigstoreRoots(raw []byte) VerifierOptFunc {
52+
return func(v *Verifier) {
53+
v.SigstoreRootsData = raw
11054
}
11155
}

0 commit comments

Comments
 (0)