Skip to content

Commit 4add04d

Browse files
committed
Add sigstore bundle support for creation artifact's evidences
1 parent 084c3ca commit 4add04d

20 files changed

+1910
-67
lines changed

evidence/cli/command_build.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ func NewEvidenceBuildCommand(ctx *components.Context, execute execCommandFunc) E
2121
}
2222

2323
func (ebc *evidenceBuildCommand) CreateEvidence(ctx *components.Context, serverDetails *config.ServerDetails) error {
24+
// Check if sigstore-bundle is provided (currently not supported for build evidence)
25+
if ebc.ctx.GetStringFlagValue(sigstoreBundle) != "" {
26+
return errorutils.CheckErrorf("--sigstore-bundle is currently not supported for build evidence. This feature may be supported in future releases.")
27+
}
28+
2429
err := ebc.validateEvidenceBuildContext(ctx)
2530
if err != nil {
2631
return err

evidence/cli/command_build_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package cli
2+
3+
import (
4+
"flag"
5+
"testing"
6+
7+
"github.com/jfrog/jfrog-cli-core/v2/common/commands"
8+
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
9+
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/urfave/cli"
12+
)
13+
14+
func TestEvidenceBuildCommand_CreateEvidence_SigstoreBundle(t *testing.T) {
15+
tests := []struct {
16+
name string
17+
flags []components.Flag
18+
expectError bool
19+
errorContains string
20+
}{
21+
{
22+
name: "Invalid_SigstoreBundle_Not_Supported",
23+
flags: []components.Flag{
24+
setDefaultValue(sigstoreBundle, "/path/to/bundle.json"),
25+
setDefaultValue(buildName, "test-build"),
26+
setDefaultValue(buildNumber, "123"),
27+
},
28+
expectError: true,
29+
errorContains: "--sigstore-bundle is currently not supported for build evidence. This feature may be supported in future releases.",
30+
},
31+
{
32+
name: "Valid_Without_SigstoreBundle",
33+
flags: []components.Flag{
34+
setDefaultValue(buildName, "test-build"),
35+
setDefaultValue(buildNumber, "123"),
36+
setDefaultValue(predicate, "/path/to/predicate.json"),
37+
setDefaultValue(predicateType, "test-type"),
38+
setDefaultValue(key, "/path/to/key.pem"),
39+
},
40+
expectError: false,
41+
},
42+
}
43+
44+
for _, tt := range tests {
45+
t.Run(tt.name, func(t *testing.T) {
46+
app := cli.NewApp()
47+
app.Commands = []cli.Command{{Name: "create"}}
48+
set := flag.NewFlagSet("test", 0)
49+
cliCtx := cli.NewContext(app, set, nil)
50+
51+
ctx, err := components.ConvertContext(cliCtx, tt.flags...)
52+
assert.NoError(t, err)
53+
54+
mockExec := func(cmd commands.Command) error {
55+
// Mock successful execution
56+
return nil
57+
}
58+
59+
cmd := NewEvidenceBuildCommand(ctx, mockExec)
60+
serverDetails := &config.ServerDetails{}
61+
62+
err = cmd.CreateEvidence(ctx, serverDetails)
63+
64+
if tt.expectError {
65+
assert.Error(t, err)
66+
if tt.errorContains != "" {
67+
assert.Contains(t, err.Error(), tt.errorContains)
68+
}
69+
} else {
70+
assert.NoError(t, err)
71+
}
72+
})
73+
}
74+
}

evidence/cli/command_cli.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package cli
33
import (
44
"errors"
55
"fmt"
6+
"os"
7+
"strings"
8+
69
"github.com/jfrog/jfrog-cli-artifactory/evidence/cli/docs/create"
710
"github.com/jfrog/jfrog-cli-artifactory/evidence/cli/docs/verify"
811
jfrogArtClient "github.com/jfrog/jfrog-cli-artifactory/evidence/utils"
@@ -15,8 +18,6 @@ import (
1518
"github.com/jfrog/jfrog-client-go/utils"
1619
"github.com/jfrog/jfrog-client-go/utils/errorutils"
1720
"golang.org/x/exp/slices"
18-
"os"
19-
"strings"
2021
)
2122

2223
func GetCommands() []components.Command {
@@ -118,6 +119,15 @@ func validateCreateEvidenceCommonContext(ctx *components.Context) error {
118119
return pluginsCommon.WrongNumberOfArgumentsHandler(ctx)
119120
}
120121

122+
// If sigstore-bundle is provided, validate conflicting parameters
123+
// We check both IsFlagSet and assertValueProvided to ensure the flag is both set and has a value
124+
if ctx.IsFlagSet(sigstoreBundle) && assertValueProvided(ctx, sigstoreBundle) == nil {
125+
if err := validateSigstoreBundleConflicts(ctx); err != nil {
126+
return err
127+
}
128+
return nil
129+
}
130+
121131
if (!ctx.IsFlagSet(predicate) || assertValueProvided(ctx, predicate) != nil) && !ctx.IsFlagSet(typeFlag) {
122132
return errorutils.CheckErrorf("'predicate' is a mandatory field for creating evidence: --%s", predicate)
123133
}
@@ -136,6 +146,34 @@ func validateCreateEvidenceCommonContext(ctx *components.Context) error {
136146
return nil
137147
}
138148

149+
// validateSigstoreBundleConflicts checks if conflicting parameters are provided when using sigstore-bundle.
150+
// When --sigstore-bundle is used, the following parameters cannot be provided:
151+
// --key, --key-alias, --predicate, --predicate-type
152+
// Returns an error if any conflicting parameters are found.
153+
func validateSigstoreBundleConflicts(ctx *components.Context) error {
154+
var conflictingParams []string
155+
156+
// Check each conflicting parameter
157+
if ctx.IsFlagSet(key) && ctx.GetStringFlagValue(key) != "" {
158+
conflictingParams = append(conflictingParams, "--key")
159+
}
160+
if ctx.IsFlagSet(keyAlias) && ctx.GetStringFlagValue(keyAlias) != "" {
161+
conflictingParams = append(conflictingParams, "--key-alias")
162+
}
163+
if ctx.IsFlagSet(predicate) && ctx.GetStringFlagValue(predicate) != "" {
164+
conflictingParams = append(conflictingParams, "--predicate")
165+
}
166+
if ctx.IsFlagSet(predicateType) && ctx.GetStringFlagValue(predicateType) != "" {
167+
conflictingParams = append(conflictingParams, "--predicate-type")
168+
}
169+
170+
if len(conflictingParams) > 0 {
171+
return errorutils.CheckErrorf("The following parameters cannot be used with --sigstore-bundle: %s. When using --sigstore-bundle, these values are extracted from the bundle itself.", strings.Join(conflictingParams, ", "))
172+
}
173+
174+
return nil
175+
}
176+
139177
func ensureKeyExists(ctx *components.Context, key string) error {
140178
if ctx.IsFlagSet(key) && assertValueProvided(ctx, key) == nil {
141179
return nil
@@ -165,6 +203,10 @@ func getAndValidateSubject(ctx *components.Context) ([]string, error) {
165203
}
166204

167205
if len(foundSubjects) == 0 {
206+
// If sigstore-bundle is provided, subject will be extracted from bundle
207+
if ctx.IsFlagSet(sigstoreBundle) && assertValueProvided(ctx, sigstoreBundle) == nil {
208+
return []string{subjectRepoPath}, nil // Return subjectRepoPath as the type for routing
209+
}
168210
// If we have no subject - we will try to create EVD on build
169211
if !attemptSetBuildNameAndNumber(ctx) {
170212
return nil, errorutils.CheckErrorf("subject must be one of the fields: [%s]", strings.Join(subjectTypes, ", "))

0 commit comments

Comments
 (0)