@@ -210,7 +210,7 @@ func CreateLocalPolicy(ctx context.Context, gh_connection *gh_control.GitHubConn
210210 // Unless there is previous provenance metadata, then we can compute
211211 // a higher level
212212 if provPred != nil {
213- eligibleLevel , _ = computeEligibleSlsaLevel (provPred .Controls )
213+ eligibleLevel = computeEligibleSlsaLevel (provPred .Controls )
214214 eligibleSince , err = computeEligibleSince (provPred .Controls , eligibleLevel )
215215 if err != nil {
216216 return "" , fmt .Errorf ("could not compute eligible since: %w" , err )
@@ -245,81 +245,64 @@ func CreateLocalPolicy(ctx context.Context, gh_connection *gh_control.GitHubConn
245245 return path , nil
246246}
247247
248- // Computes the eligible SLSA level, and when they started being eligible for it,
249- // if only they had a policy. Also returns a rationale for why it's eligible for this level.
250- func computeEligibleSlsaLevel (controls slsa_types.Controls ) (slsa_types.SlsaSourceLevel , string ) {
251- continuityControl := controls .GetControl (slsa_types .ContinuityEnforced )
252- provControl := controls .GetControl (slsa_types .ProvenanceAvailable )
253- reviewControl := controls .GetControl (slsa_types .ReviewEnforced )
254-
255- if continuityControl != nil && provControl != nil && reviewControl != nil {
256- return slsa_types .SlsaSourceLevel4 , "continuity and review are enabled and provenance is available"
257- }
258-
259- if continuityControl != nil && provControl != nil {
260- // Both continuity and prov means it can get level 3
261- return slsa_types .SlsaSourceLevel3 , "continuity is enabled and provenance is available"
248+ func computeEligibleForLevel (controls slsa_types.Controls , level slsa_types.SlsaSourceLevel ) bool {
249+ requiredControls := slsa_types .GetRequiredControlsForLevel (level )
250+ if controls .AreControlsAvailable (requiredControls ) {
251+ return true
262252 }
253+ return false
254+ }
263255
264- if continuityControl != nil {
265- // Just continuity control means it can get level 2
266- return slsa_types .SlsaSourceLevel2 , "continuity is enabled but provenance is not available"
256+ // Computes the eligible SLSA level, and when they started being eligible for it,
257+ // if only they had a policy. Also returns a rationale for why it's eligible for this level.
258+ func computeEligibleSlsaLevel (controls slsa_types.Controls ) slsa_types.SlsaSourceLevel {
259+ // Go from highest to lowest.
260+ for _ , level := range []slsa_types.SlsaSourceLevel {
261+ slsa_types .SlsaSourceLevel4 , slsa_types .SlsaSourceLevel3 , slsa_types .SlsaSourceLevel2 } {
262+ eligible := computeEligibleForLevel (controls , level )
263+ if eligible {
264+ return level
265+ }
267266 }
268267
269268 // If nothing else, level 1.
270269 // The time here is tricky, it's really probably since whenever they created the repo
271270 // But also, they don't qualify for much so maybe it doesn't matter.
272271 // Just return now for now.
273- return slsa_types .SlsaSourceLevel1 , "continuity is not enabled"
272+ return slsa_types .SlsaSourceLevel1
274273}
275274
276275// Computes the time since these controls have been eligible for the level, nil if not eligible.
277276func computeEligibleSince (controls slsa_types.Controls , level slsa_types.SlsaSourceLevel ) (* time.Time , error ) {
278- continuityControl := controls .GetControl (slsa_types .ContinuityEnforced )
279- provControl := controls .GetControl (slsa_types .ProvenanceAvailable )
280- reviewControl := controls .GetControl (slsa_types .ReviewEnforced )
281277
282- if level == slsa_types .SlsaSourceLevel4 {
283- if continuityControl != nil && provControl != nil && reviewControl != nil {
284- t := slsa_types .LaterTime (continuityControl .Since , provControl .Since )
285- t = slsa_types .LaterTime (t , reviewControl .Since )
286- return & t , nil
278+ requiredControls := slsa_types .GetRequiredControlsForLevel (level )
279+ var newestTime time.Time
280+ for _ , rc := range requiredControls {
281+ ac := controls .GetControl (rc )
282+ if ac == nil {
283+ return nil , nil
287284 }
288- return nil , nil
289- }
290-
291- if level == slsa_types .SlsaSourceLevel3 {
292- if continuityControl != nil && provControl != nil {
293- t := slsa_types .LaterTime (continuityControl .Since , provControl .Since )
294- return & t , nil
295- }
296- return nil , nil
297- }
298-
299- if level == slsa_types .SlsaSourceLevel2 {
300- if continuityControl != nil {
301- return & continuityControl .Since , nil
285+ if newestTime .Equal (time.Time {}) {
286+ newestTime = ac .Since
287+ } else {
288+ newestTime = slsa_types .LaterTime (newestTime , ac .Since )
302289 }
303- return nil , nil
304290 }
305-
306- if level == slsa_types .SlsaSourceLevel1 {
307- // Use an uninitialized time to indicate it's always been eligible.
308- return & time.Time {}, nil
309- }
310-
311- // Unknown level
312- return nil , fmt .Errorf ("unknown level %s" , level )
291+ return & newestTime , nil
313292}
314293
315294// Every function that determines properties to include in the result & VSA implements this interface.
316295type computePolicyResult func (* ProtectedBranch , * ProtectedTag , slsa_types.Controls ) ([]slsa_types.ControlName , error )
317296
318297func computeSlsaLevel (branchPolicy * ProtectedBranch , _ * ProtectedTag , controls slsa_types.Controls ) ([]slsa_types.ControlName , error ) {
319- eligibleLevel , eligibleWhy := computeEligibleSlsaLevel (controls )
298+ eligibleLevel := computeEligibleSlsaLevel (controls )
320299
321300 if ! slsa_types .IsLevelHigherOrEqualTo (eligibleLevel , branchPolicy .TargetSlsaSourceLevel ) {
322- return []slsa_types.ControlName {}, fmt .Errorf ("policy sets target level %s, but branch is only eligible for %s because %s" , branchPolicy .TargetSlsaSourceLevel , eligibleLevel , eligibleWhy )
301+ return []slsa_types.ControlName {}, fmt .Errorf (
302+ "policy sets target level %s which requires %v, but branch is only eligible for %s because it only has %v" ,
303+ branchPolicy .TargetSlsaSourceLevel ,
304+ slsa_types .GetRequiredControlsForLevel (branchPolicy .TargetSlsaSourceLevel ),
305+ eligibleLevel , controls .Names ())
323306 }
324307
325308 // Check to see when this branch became eligible for the current target level.
0 commit comments