Skip to content

Commit 7e1fae9

Browse files
authored
Merge pull request #3018 from joejstuart/fix-fallback-results
Results difference
2 parents 29f1630 + f2d11ed commit 7e1fae9

File tree

6 files changed

+15
-437
lines changed

6 files changed

+15
-437
lines changed

cmd/validate/vsa.go

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -452,32 +452,18 @@ func performVSAValidationForSingle(ctx context.Context, identifier string, data
452452
}
453453

454454
// handleFallbackValidation handles the fallback validation logic
455-
func handleFallbackValidation(ctx context.Context, identifier string, result *vsa.ValidationResult, data *validateVSAData, fs afero.Fs) error {
455+
func handleFallbackValidation(ctx context.Context, imageRef string, result *vsa.ValidationResult, data *validateVSAData, fs afero.Fs) error {
456456
printVSAInfo(os.Stdout, "Falling back to image validation...")
457-
458-
// Extract image reference from VSA identifier for fallback
459-
imageRef, extractErr := vsa.ExtractImageFromVSAIdentifier(identifier)
460-
if extractErr != nil {
461-
return fmt.Errorf("fallback validation not supported for file paths: %s", identifier)
462-
}
457+
printVSAInfo(os.Stdout, fmt.Sprintf("Image reference: %s", imageRef))
463458

464459
// Create worker context for fallback validation
465460
workerFallbackContext, workerErr := vsa.CreateWorkerFallbackContext(ctx, data.fallbackContext.FallbackPolicy)
466461
if workerErr != nil {
467462
return fmt.Errorf("failed to create fallback context: %w", workerErr)
468463
}
469464

470-
// Create fallback config
471-
fallbackConfig := &vsa.FallbackConfig{
472-
FallbackToImageValidation: data.fallbackToImageValidation,
473-
FallbackPublicKey: data.fallbackPublicKey,
474-
PolicyConfig: data.policyConfig,
475-
EffectiveTime: data.effectiveTime,
476-
Info: data.info,
477-
}
478-
479465
// Use the common fallback validation logic
480-
fallbackResult := vsa.PerformFallbackValidation(ctx, fallbackConfig, data.fallbackContext, imageRef, "single-vsa-component", result, "", workerFallbackContext)
466+
fallbackResult := vsa.PerformFallbackValidation(result, "")
481467
if fallbackResult.Error != nil {
482468
return fallbackResult.Error
483469
}
@@ -831,6 +817,7 @@ func validateImageFallbackWithWorkerContext(ctx context.Context, data *validateV
831817

832818
// Perform image validation using precomputed context and worker-specific evaluators
833819
log.Debugf("🔄 Fallback: Starting image validation...")
820+
log.Debugf("🔄 Fallback: Using fallback policy: %s", data.fallbackContext.FallbackPolicy)
834821
result, err := image.ValidateImage(ctx, comp, spec, data.fallbackContext.FallbackPolicy, workerFallbackContext.Evaluators, data.info)
835822
if err != nil {
836823
log.Debugf("🔄 Fallback: Image validation failed with error: %v", err)
@@ -910,17 +897,8 @@ func handleComponentFallback(ctx context.Context, component app.SnapshotComponen
910897
predicateStatus = result.PredicateOutcome
911898
}
912899

913-
// Create fallback config
914-
fallbackConfig := &vsa.FallbackConfig{
915-
FallbackToImageValidation: data.fallbackToImageValidation,
916-
FallbackPublicKey: data.fallbackPublicKey,
917-
PolicyConfig: data.policyConfig,
918-
EffectiveTime: data.effectiveTime,
919-
Info: data.info,
920-
}
921-
922900
// Use the common fallback validation logic
923-
fallbackResult := vsa.PerformFallbackValidation(ctx, fallbackConfig, data.fallbackContext, imageRef, component.Name, result, predicateStatus, workerFallbackContext)
901+
fallbackResult := vsa.PerformFallbackValidation(result, predicateStatus)
924902
if fallbackResult.Error != nil {
925903
return createErrorResult(component, fallbackResult.Error)
926904
}

cmd/validate/vsa_test.go

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535
"github.com/spf13/cobra"
3636
"github.com/stretchr/testify/assert"
3737

38-
"github.com/conforma/cli/internal/evaluator"
3938
"github.com/conforma/cli/internal/output"
4039
"github.com/conforma/cli/internal/validate/vsa"
4140
)
@@ -1779,25 +1778,15 @@ func (m *mockOutputFormatter) PrintText(writer io.Writer) error {
17791778

17801779
// TestPerformFallbackValidation tests the extracted fallback validation function
17811780
func TestPerformFallbackValidation(t *testing.T) {
1782-
ctx := context.Background()
1783-
1784-
// Create a mock worker fallback context
1785-
workerContext := &vsa.WorkerFallbackContext{
1786-
Evaluators: []evaluator.Evaluator{}, // Empty for testing
1787-
}
17881781

17891782
tests := []struct {
17901783
name string
1791-
imageRef string
1792-
componentName string
17931784
result *vsa.ValidationResult
17941785
predicateStatus string
17951786
expectError bool
17961787
}{
17971788
{
1798-
name: "successful fallback with VSA result",
1799-
imageRef: "test-image:latest",
1800-
componentName: "test-component",
1789+
name: "successful fallback with VSA result",
18011790
result: &vsa.ValidationResult{
18021791
Passed: false,
18031792
Message: "VSA validation failed",
@@ -1807,16 +1796,12 @@ func TestPerformFallbackValidation(t *testing.T) {
18071796
},
18081797
{
18091798
name: "successful fallback without VSA result",
1810-
imageRef: "test-image:latest",
1811-
componentName: "test-component",
18121799
result: nil,
18131800
predicateStatus: "failed",
18141801
expectError: false,
18151802
},
18161803
{
18171804
name: "fallback with empty predicate status",
1818-
imageRef: "test-image:latest",
1819-
componentName: "test-component",
18201805
result: nil,
18211806
predicateStatus: "",
18221807
expectError: false,
@@ -1827,16 +1812,7 @@ func TestPerformFallbackValidation(t *testing.T) {
18271812
t.Run(tt.name, func(t *testing.T) {
18281813
// Note: This test will fail in practice because it requires actual
18291814
// fallback context and evaluators, but it tests the function structure
1830-
// Create fallback config
1831-
fallbackConfig := &vsa.FallbackConfig{
1832-
FallbackToImageValidation: true,
1833-
FallbackPublicKey: "test-key",
1834-
PolicyConfig: "test-policy",
1835-
EffectiveTime: "2023-01-01T00:00:00Z",
1836-
Info: false,
1837-
}
1838-
1839-
fallbackResult := vsa.PerformFallbackValidation(ctx, fallbackConfig, nil, tt.imageRef, tt.componentName, tt.result, tt.predicateStatus, workerContext)
1815+
fallbackResult := vsa.PerformFallbackValidation(tt.result, tt.predicateStatus)
18401816

18411817
if tt.expectError {
18421818
assert.Error(t, fallbackResult.Error)
@@ -1852,19 +1828,8 @@ func TestPerformFallbackValidation(t *testing.T) {
18521828

18531829
// TestPerformFallbackValidation_ErrorHandling tests error handling in fallback validation
18541830
func TestPerformFallbackValidation_ErrorHandling(t *testing.T) {
1855-
ctx := context.Background()
1856-
18571831
// Test with nil worker context - should not cause error as function only handles VSA result logic
1858-
// Create fallback config
1859-
fallbackConfig := &vsa.FallbackConfig{
1860-
FallbackToImageValidation: true,
1861-
FallbackPublicKey: "test-key",
1862-
PolicyConfig: "test-policy",
1863-
EffectiveTime: "2023-01-01T00:00:00Z",
1864-
Info: false,
1865-
}
1866-
1867-
fallbackResult := vsa.PerformFallbackValidation(ctx, fallbackConfig, nil, "test-image:latest", "test-component", nil, "failed", nil)
1832+
fallbackResult := vsa.PerformFallbackValidation(nil, "failed")
18681833
// The function now only handles VSA result logic, so it should not return an error
18691834
assert.NoError(t, fallbackResult.Error)
18701835
assert.NotNil(t, fallbackResult.VSAResult)

internal/validate/vsa/fallback.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func ShouldTriggerFallback(err error, result *ValidationResult) bool {
8383

8484
// performFallbackValidation performs the common fallback validation logic
8585
// Note: This function now only handles the VSA result logic, image validation is handled in CLI layer
86-
func PerformFallbackValidation(ctx context.Context, config *FallbackConfig, fallbackContext *FallbackValidationContext, imageRef string, componentName string, result *ValidationResult, predicateStatus string, workerFallbackContext *WorkerFallbackContext) *FallbackResult {
86+
func PerformFallbackValidation(result *ValidationResult, predicateStatus string) *FallbackResult {
8787
// Use the actual VSA result for fallback case
8888
// If we have a result, use it; otherwise create a minimal result
8989
var vsaResult *ValidationResult

internal/validate/vsa/fallback_test.go

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -113,44 +113,22 @@ func TestShouldTriggerFallback(t *testing.T) {
113113
}
114114

115115
func TestPerformFallbackValidation(t *testing.T) {
116-
ctx := context.Background()
117-
118116
tests := []struct {
119-
name string
120-
config *FallbackConfig
121-
fallbackContext *FallbackValidationContext
122-
imageRef string
123-
componentName string
124-
result *ValidationResult
125-
predicateStatus string
126-
workerFallbackContext *WorkerFallbackContext
127-
expectedVSAResult *ValidationResult
128-
expectedError error
117+
name string
118+
result *ValidationResult
119+
predicateStatus string
120+
expectedVSAResult *ValidationResult
121+
expectedError error
129122
}{
130123
{
131124
name: "With VSA result - should use provided result",
132-
config: &FallbackConfig{
133-
FallbackToImageValidation: true,
134-
FallbackPublicKey: "test-key",
135-
PolicyConfig: "test-policy",
136-
EffectiveTime: "2023-01-01T00:00:00Z",
137-
Info: false,
138-
},
139-
fallbackContext: &FallbackValidationContext{
140-
PolicyConfiguration: "test-policy",
141-
},
142-
imageRef: "test-image:latest",
143-
componentName: "test-component",
144125
result: &ValidationResult{
145126
Passed: false,
146127
Message: "VSA validation failed",
147128
SignatureVerified: false,
148129
PredicateOutcome: "failed",
149130
},
150131
predicateStatus: "failed",
151-
workerFallbackContext: &WorkerFallbackContext{
152-
Evaluators: []evaluator.Evaluator{},
153-
},
154132
expectedVSAResult: &ValidationResult{
155133
Passed: false,
156134
Message: "VSA validation failed",
@@ -160,24 +138,9 @@ func TestPerformFallbackValidation(t *testing.T) {
160138
expectedError: nil,
161139
},
162140
{
163-
name: "Without VSA result - should create minimal result",
164-
config: &FallbackConfig{
165-
FallbackToImageValidation: true,
166-
FallbackPublicKey: "test-key",
167-
PolicyConfig: "test-policy",
168-
EffectiveTime: "2023-01-01T00:00:00Z",
169-
Info: false,
170-
},
171-
fallbackContext: &FallbackValidationContext{
172-
PolicyConfiguration: "test-policy",
173-
},
174-
imageRef: "test-image:latest",
175-
componentName: "test-component",
141+
name: "Without VSA result - should create minimal result",
176142
result: nil, // No VSA result
177143
predicateStatus: "failed",
178-
workerFallbackContext: &WorkerFallbackContext{
179-
Evaluators: []evaluator.Evaluator{},
180-
},
181144
expectedVSAResult: &ValidationResult{
182145
Passed: false,
183146
Message: "VSA validation failed",
@@ -188,28 +151,13 @@ func TestPerformFallbackValidation(t *testing.T) {
188151
},
189152
{
190153
name: "With successful VSA result - should use provided result",
191-
config: &FallbackConfig{
192-
FallbackToImageValidation: true,
193-
FallbackPublicKey: "test-key",
194-
PolicyConfig: "test-policy",
195-
EffectiveTime: "2023-01-01T00:00:00Z",
196-
Info: false,
197-
},
198-
fallbackContext: &FallbackValidationContext{
199-
PolicyConfiguration: "test-policy",
200-
},
201-
imageRef: "test-image:latest",
202-
componentName: "test-component",
203154
result: &ValidationResult{
204155
Passed: true,
205156
Message: "VSA validation passed",
206157
SignatureVerified: true,
207158
PredicateOutcome: "passed",
208159
},
209160
predicateStatus: "passed",
210-
workerFallbackContext: &WorkerFallbackContext{
211-
Evaluators: []evaluator.Evaluator{},
212-
},
213161
expectedVSAResult: &ValidationResult{
214162
Passed: true,
215163
Message: "VSA validation passed",
@@ -223,14 +171,8 @@ func TestPerformFallbackValidation(t *testing.T) {
223171
for _, tt := range tests {
224172
t.Run(tt.name, func(t *testing.T) {
225173
fallbackResult := PerformFallbackValidation(
226-
ctx,
227-
tt.config,
228-
tt.fallbackContext,
229-
tt.imageRef,
230-
tt.componentName,
231174
tt.result,
232175
tt.predicateStatus,
233-
tt.workerFallbackContext,
234176
)
235177

236178
// Verify the result structure
@@ -426,7 +368,6 @@ func TestShouldTriggerFallback_EdgeCases(t *testing.T) {
426368

427369
// Test PerformFallbackValidation with different predicate statuses
428370
func TestPerformFallbackValidation_PredicateStatuses(t *testing.T) {
429-
ctx := context.Background()
430371

431372
tests := []struct {
432373
name string
@@ -461,23 +402,9 @@ func TestPerformFallbackValidation_PredicateStatuses(t *testing.T) {
461402

462403
for _, tt := range tests {
463404
t.Run(tt.name, func(t *testing.T) {
464-
config := &FallbackConfig{
465-
FallbackToImageValidation: true,
466-
FallbackPublicKey: "test-key",
467-
PolicyConfig: "test-policy",
468-
EffectiveTime: "2023-01-01T00:00:00Z",
469-
Info: false,
470-
}
471-
472405
fallbackResult := PerformFallbackValidation(
473-
ctx,
474-
config,
475-
nil, // fallbackContext
476-
"test-image:latest",
477-
"test-component",
478406
tt.result,
479407
tt.predicateStatus,
480-
nil, // workerFallbackContext
481408
)
482409

483410
require.NotNil(t, fallbackResult)

internal/validate/vsa/vsa.go

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -931,36 +931,6 @@ func ExtractDigestFromImageRef(imageRef string) (string, error) {
931931
return imageRef, nil
932932
}
933933

934-
// ExtractImageFromVSAIdentifier extracts the image reference from VSA identifier
935-
// This function is used for fallback validation when VSA validation fails
936-
func ExtractImageFromVSAIdentifier(identifier string) (string, error) {
937-
// Handle empty identifier specially
938-
if identifier == "" {
939-
return "", nil
940-
}
941-
942-
identifierType := DetectIdentifierType(identifier)
943-
944-
switch identifierType {
945-
case IdentifierImageDigest:
946-
// Convert digest to image reference
947-
// e.g., registry/image@sha256:abc123 -> registry/image:tag
948-
return ConvertDigestToImageRef(identifier)
949-
case IdentifierImageReference:
950-
// Check if it's actually a file path that was incorrectly detected as image reference
951-
if IsFilePathLike(identifier) {
952-
return "", fmt.Errorf("fallback validation not supported for file paths: %s", identifier)
953-
}
954-
// Already an image reference
955-
return identifier, nil
956-
case IdentifierFile:
957-
// Cannot extract image from file path - fallback not supported
958-
return "", fmt.Errorf("fallback validation not supported for file paths: %s", identifier)
959-
default:
960-
return "", fmt.Errorf("fallback validation not supported for identifier type: %s", identifier)
961-
}
962-
}
963-
964934
// isFilePathLike checks if an identifier looks like a file path
965935
// This handles the case where name.ParseReference incorrectly accepts file paths as valid image references
966936
func IsFilePathLike(identifier string) bool {
@@ -987,28 +957,3 @@ func IsFilePathLike(identifier string) bool {
987957

988958
return false
989959
}
990-
991-
// ConvertDigestToImageRef converts a digest to an image reference
992-
// This is a simplified implementation that attempts to construct a reasonable image reference
993-
func ConvertDigestToImageRef(digest string) (string, error) {
994-
// If the digest is already in the format registry/image@sha256:abc123,
995-
// we can extract the repository part and construct a tag reference
996-
if strings.Contains(digest, "@") {
997-
parts := strings.Split(digest, "@")
998-
if len(parts) == 2 {
999-
repository := parts[0]
1000-
// Try to construct a reasonable tag reference
1001-
// This is a best-effort approach since we don't have the original tag
1002-
imageRef := repository + ":latest"
1003-
1004-
// Validate that the constructed reference is valid
1005-
if _, err := name.ParseReference(imageRef); err == nil {
1006-
return imageRef, nil
1007-
}
1008-
}
1009-
}
1010-
1011-
// If we can't convert the digest to an image reference,
1012-
// return an error as fallback is not supported for pure digests
1013-
return "", fmt.Errorf("fallback validation: cannot convert digest to image reference: %s", digest)
1014-
}

0 commit comments

Comments
 (0)