@@ -139,3 +139,204 @@ deny contains result if {
139139 require .NoError (t , err )
140140 assert .NotNil (t , result )
141141}
142+
143+ func TestConftestEvaluatorIntegrationWithComponentNames (t * testing.T ) {
144+ ctx := context .Background ()
145+
146+ // Create a temporary directory for the test
147+ tmpDir := t .TempDir ()
148+ policyDir := filepath .Join (tmpDir , "policy" )
149+ err := os .MkdirAll (policyDir , 0o755 )
150+ require .NoError (t , err )
151+
152+ // Create policies that will be filtered by ComponentNames
153+ policyContent := `package test
154+
155+ import rego.v1
156+
157+ # METADATA
158+ # title: Check A
159+ # custom:
160+ # short_name: check_a
161+ deny contains result if {
162+ result := {
163+ "code": "test.check_a",
164+ "msg": "Check A always fails"
165+ }
166+ }
167+
168+ # METADATA
169+ # title: Check B
170+ # custom:
171+ # short_name: check_b
172+ deny contains result if {
173+ result := {
174+ "code": "test.check_b",
175+ "msg": "Check B always fails"
176+ }
177+ }
178+ `
179+ err = os .WriteFile (filepath .Join (policyDir , "policy.rego" ), []byte (policyContent ), 0o600 )
180+ require .NoError (t , err )
181+
182+ // Create policy source
183+ policySource := & source.PolicyUrl {
184+ Url : "file://" + policyDir ,
185+ Kind : source .PolicyKind ,
186+ }
187+
188+ // Create config provider with ComponentNames filter
189+ configProvider := & mockConfigProvider {}
190+ configProvider .On ("EffectiveTime" ).Return (time .Date (2024 , 6 , 1 , 0 , 0 , 0 , 0 , time .UTC ))
191+ configProvider .On ("SigstoreOpts" ).Return (policy.SigstoreOpts {}, nil )
192+ configProvider .On ("Spec" ).Return (ecc.EnterpriseContractPolicySpec {
193+ Sources : []ecc.Source {
194+ {
195+ Policy : []string {"file://" + policyDir },
196+ },
197+ },
198+ })
199+
200+ // Create evaluator with VolatileConfig that excludes check_a for comp1
201+ evaluator , err := NewConftestEvaluator (ctx , []source.PolicySource {policySource }, configProvider , ecc.Source {
202+ VolatileConfig : & ecc.VolatileSourceConfig {
203+ Exclude : []ecc.VolatileCriteria {
204+ {
205+ Value : "test.check_a" ,
206+ ComponentNames : []string {"comp1" },
207+ EffectiveOn : "2024-01-01T00:00:00Z" ,
208+ EffectiveUntil : "2025-01-01T00:00:00Z" ,
209+ },
210+ },
211+ },
212+ })
213+ require .NoError (t , err )
214+ defer evaluator .Destroy ()
215+
216+ // Debug: Check exclude criteria
217+ conftestEval := evaluator .(conftestEvaluator )
218+ t .Logf ("Exclude componentItems: %+v" , conftestEval .exclude .componentItems )
219+ t .Logf ("Exclude defaultItems: %+v" , conftestEval .exclude .defaultItems )
220+ t .Logf ("Exclude digestItems: %+v" , conftestEval .exclude .digestItems )
221+
222+ // Create test input
223+ inputData := map [string ]interface {}{
224+ "test" : "value" ,
225+ }
226+ inputBytes , err := json .Marshal (inputData )
227+ require .NoError (t , err )
228+ inputPath := filepath .Join (tmpDir , "input.json" )
229+ err = os .WriteFile (inputPath , inputBytes , 0o600 )
230+ require .NoError (t , err )
231+
232+ // Test comp1 - check_a should be excluded
233+ target1 := EvaluationTarget {
234+ Inputs : []string {inputPath },
235+ Target : "quay.io/repo/img@sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" ,
236+ ComponentName : "comp1" ,
237+ }
238+
239+ result1 , err := evaluator .Evaluate (ctx , target1 )
240+ require .NoError (t , err )
241+ require .NotNil (t , result1 )
242+
243+ // Debug: Print all failures
244+ t .Logf ("comp1 results: %d outcomes" , len (result1 ))
245+ for i , outcome := range result1 {
246+ t .Logf (" Outcome %d: %d failures, %d successes" , i , len (outcome .Failures ), len (outcome .Successes ))
247+ for _ , failure := range outcome .Failures {
248+ t .Logf (" Failure: %s" , failure .Metadata ["code" ])
249+ }
250+ for _ , success := range outcome .Successes {
251+ t .Logf (" Success: %s" , success .Metadata ["code" ])
252+ }
253+ }
254+
255+ // Verify check_a is excluded, check_b is not
256+ hasCheckA := false
257+ hasCheckB := false
258+ for _ , outcome := range result1 {
259+ for _ , failure := range outcome .Failures {
260+ if codeStr , ok := failure .Metadata ["code" ].(string ); ok {
261+ if codeStr == "test.check_a" {
262+ hasCheckA = true
263+ }
264+ if codeStr == "test.check_b" {
265+ hasCheckB = true
266+ }
267+ }
268+ }
269+ }
270+ assert .False (t , hasCheckA , "Expected check_a to be excluded for comp1" )
271+ assert .True (t , hasCheckB , "Expected check_b to be evaluated for comp1" )
272+
273+ // Test comp2 - check_a should NOT be excluded
274+ target2 := EvaluationTarget {
275+ Inputs : []string {inputPath },
276+ Target : "quay.io/repo/img@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890" ,
277+ ComponentName : "comp2" ,
278+ }
279+
280+ result2 , err := evaluator .Evaluate (ctx , target2 )
281+ require .NoError (t , err )
282+ require .NotNil (t , result2 )
283+
284+ // Verify both checks are evaluated for comp2
285+ hasCheckA2 := false
286+ hasCheckB2 := false
287+ for _ , outcome := range result2 {
288+ for _ , failure := range outcome .Failures {
289+ if codeStr , ok := failure .Metadata ["code" ].(string ); ok {
290+ if codeStr == "test.check_a" {
291+ hasCheckA2 = true
292+ }
293+ if codeStr == "test.check_b" {
294+ hasCheckB2 = true
295+ }
296+ }
297+ }
298+ }
299+ assert .True (t , hasCheckA2 , "Expected check_a to be evaluated for comp2" )
300+ assert .True (t , hasCheckB2 , "Expected check_b to be evaluated for comp2" )
301+
302+ // Test same image with different components - monorepo scenario
303+ sameImage := "quay.io/monorepo@sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321"
304+
305+ target3 := EvaluationTarget {
306+ Inputs : []string {inputPath },
307+ Target : sameImage ,
308+ ComponentName : "comp1" ,
309+ }
310+
311+ result3 , err := evaluator .Evaluate (ctx , target3 )
312+ require .NoError (t , err )
313+
314+ hasCheckA3 := false
315+ for _ , outcome := range result3 {
316+ for _ , failure := range outcome .Failures {
317+ if codeStr , ok := failure .Metadata ["code" ].(string ); ok && codeStr == "test.check_a" {
318+ hasCheckA3 = true
319+ }
320+ }
321+ }
322+ assert .False (t , hasCheckA3 , "Expected check_a excluded for comp1 even with different image" )
323+
324+ target4 := EvaluationTarget {
325+ Inputs : []string {inputPath },
326+ Target : sameImage ,
327+ ComponentName : "comp2" ,
328+ }
329+
330+ result4 , err := evaluator .Evaluate (ctx , target4 )
331+ require .NoError (t , err )
332+
333+ hasCheckA4 := false
334+ for _ , outcome := range result4 {
335+ for _ , failure := range outcome .Failures {
336+ if codeStr , ok := failure .Metadata ["code" ].(string ); ok && codeStr == "test.check_a" {
337+ hasCheckA4 = true
338+ }
339+ }
340+ }
341+ assert .True (t , hasCheckA4 , "Expected check_a evaluated for comp2 with same image" )
342+ }
0 commit comments