Skip to content

Commit 9392d4b

Browse files
authored
Require Tag Hygiene at L2+ (#169)
* add missing tests for l4 Signed-off-by: Tom Hennen <[email protected]> * make it easier to add new control requirements for levels Signed-off-by: Tom Hennen <[email protected]> * Require Tag Hygiene for L2+ Refactored computeEligibleSince to use slsa_types.GetRequiredControlsForLevel Signed-off-by: Tom Hennen <[email protected]> --------- Signed-off-by: Tom Hennen <[email protected]>
1 parent 0471efc commit 9392d4b

File tree

3 files changed

+190
-151
lines changed

3 files changed

+190
-151
lines changed

sourcetool/pkg/policy/policy.go

Lines changed: 35 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
277276
func 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.
316295
type computePolicyResult func(*ProtectedBranch, *ProtectedTag, slsa_types.Controls) ([]slsa_types.ControlName, error)
317296

318297
func 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

Comments
 (0)