@@ -2,6 +2,7 @@ package main
22
33import (
44 "context"
5+ "encoding/json"
56 "errors"
67 "flag"
78 "fmt"
@@ -13,8 +14,10 @@ import (
1314)
1415
1516const (
16- SlsaSourceLevel1 = "SLSA_SOURCE_LEVEL_1"
17- SlsaSourceLevel2 = "SLSA_SOURCE_LEVEL_2"
17+ SlsaSourceLevel1 = "SLSA_SOURCE_LEVEL_1"
18+ SlsaSourceLevel2 = "SLSA_SOURCE_LEVEL_2"
19+ SourcePolicyRepoOwner = "slsa-framework"
20+ SourcePolicyRepo = "slsa-source-poc"
1821)
1922
2023type activity struct {
@@ -26,6 +29,40 @@ type activity struct {
2629 ActivityType string `json:"activity_type"`
2730}
2831
32+ type protectedBranch struct {
33+ Name string
34+ Since time.Time
35+ TargetSlsaSourceLevel string `json:"target_slsa_source_level"`
36+ }
37+ type repoPolicy struct {
38+ // I'm actually not sure we need this. Consider removing?
39+ CanonicalRepo string `json:"canonical_repo"`
40+ ProtectedBranches []protectedBranch `json:"protected_branches"`
41+ }
42+
43+ func getBranchPolicy (ctx context.Context , gh_client * github.Client , owner string , repo string , branch string ) (* protectedBranch , error ) {
44+ path := fmt .Sprintf ("../policy/github.com/%s/%s/source-policy.json" , owner , repo )
45+
46+ policyContents , _ , _ , err := gh_client .Repositories .GetContents (ctx , SourcePolicyRepoOwner , SourcePolicyRepo , path , nil )
47+ if err != nil {
48+ return nil , err
49+ }
50+
51+ var p repoPolicy
52+ err = json .Unmarshal (policyContents .GetContents (), & p )
53+ if err != nil {
54+ return nil , err
55+ }
56+
57+ for _ , pb := range p .ProtectedBranches {
58+ if pb .Name == branch {
59+ return & pb , nil
60+ }
61+ }
62+
63+ return nil , errors .New (fmt .Sprintf ("Could not find rule for branch %s" , branch ))
64+ }
65+
2966// Checks to see if the rule meets our requirements.
3067func checkRule (ctx context.Context , gh_client * github.Client , owner string , repo string , rule * github.RepositoryRule , minTime time.Time ) (bool , error ) {
3168 ruleset , _ , err := gh_client .Repositories .GetRuleset (ctx , owner , repo , rule .RulesetID , false )
@@ -104,16 +141,23 @@ func determineSourceLevel(ctx context.Context, gh_client *github.Client, commit
104141 return "" , err
105142 }
106143
107- // We'd like to check that the rules have been enabled for the appropriate amount of time
108- // (to ensure they weren't disabled). For now we just require something that's not in
109- // the future.
110- minTime := pushTime .AddDate (0 , 0 , - 1 * minDays )
144+ // We want to check to ensure the repo hasn't enabled/disabled the rules since
145+ // setting the 'since' field in their policy.
146+ branchPolicy , err := getBranchPolicy (ctx , gh_client , owner , repo , branch )
147+ if err != nil {
148+ return "" , err
149+ }
150+
151+ if pushTime .Before (branchPolicy .Since ) {
152+ // This commit was pushed before they had an explicit policy.
153+ return SlsaSourceLevel1 , nil
154+ }
111155
112- deletionGood , err := checkRule (ctx , gh_client , owner , repo , deletionRule , minTime )
156+ deletionGood , err := checkRule (ctx , gh_client , owner , repo , deletionRule , branchPolicy . Since )
113157 if err != nil {
114158 return "" , err
115159 }
116- nonFFGood , err := checkRule (ctx , gh_client , owner , repo , nonFastFowardRule , minTime )
160+ nonFFGood , err := checkRule (ctx , gh_client , owner , repo , nonFastFowardRule , branchPolicy . Since )
117161 if err != nil {
118162 return "" , err
119163 }
0 commit comments