@@ -9,10 +9,12 @@ import (
99 "github.com/open-policy-agent/opa/rego"
1010 "github.com/open-policy-agent/opa/types"
1111 "github.com/rs/zerolog/log"
12- cobra "github.com/spf13/cobra"
12+ "github.com/spf13/cobra"
13+ "github.com/spf13/viper"
1314 "io/ioutil"
1415 "os"
1516 "path/filepath"
17+ "strings"
1618)
1719
1820type regoInput struct {
@@ -53,6 +55,13 @@ opslevel run policy -f policy.rego | jq
5355 Decl : types .NewFunction (types .Args (types .S ), types .S ),
5456 },
5557 RegoFuncReadFile ),
58+ rego .Function2 (
59+ & rego.Function {
60+ Name : "opslevel.repo.github" ,
61+ Decl : types .NewFunction (types .Args (types .S , types .S ), types .A ),
62+ Memoize : true ,
63+ },
64+ RegoFuncGetGithubRepo ),
5665 rego .Input (input ),
5766 )
5867 rs , err := rego .Eval (context .Background ())
@@ -84,8 +93,52 @@ func RegoFuncReadFile(ctx rego.BuiltinContext, a *ast.Term) (*ast.Term, error) {
8493 return nil , nil
8594}
8695
96+ func RegoFuncGetGithubRepo (ctx rego.BuiltinContext , a , b * ast.Term ) (* ast.Term , error ) {
97+
98+ var org , repo string
99+ if err := ast .As (a .Value , & org ); err != nil {
100+ return nil , err
101+ }
102+ if err := ast .As (b .Value , & repo ); err != nil {
103+ return nil , err
104+ }
105+
106+ if org == "" {
107+ log .Error ().Msgf ("opslevel.repo.github(\" %s\" , \" %s\" ) failed: Please provide a valid org" , org , repo )
108+ return nil , nil
109+ }
110+
111+ if repo == "" {
112+ log .Error ().Msgf ("opslevel.repo.github(\" %s\" , \" %s\" ) failed: Please provide a valid repo" , org , repo )
113+ return nil , nil
114+ }
115+
116+ githubToken := viper .GetString ("github-token" )
117+ authorizationHeader := fmt .Sprintf ("token %s" , githubToken )
118+ githubAPIUrl := fmt .Sprintf ("https://api.github.com/repos/%v/%v" , org , repo )
119+
120+ response , err := getClientRest ().R ().
121+ SetHeader ("Accept" , "application/vnd.github+json" ).
122+ SetHeader ("Authorization" , authorizationHeader ).
123+ Get (githubAPIUrl )
124+ cobra .CheckErr (err )
125+
126+ if response .IsError () == true {
127+ log .Error ().Msgf ("error requesting Github repo metadata. CODE: %d: REASON: %s" , response .StatusCode (), response )
128+ return nil , nil
129+ }
130+
131+ reader := strings .NewReader (response .String ())
132+ v , err := ast .ValueFromReader (reader )
133+ return ast .NewTerm (v ), nil
134+ }
135+
87136func init () {
88137 runCmd .AddCommand (policyCmd )
89138
90139 policyCmd .Flags ().StringP ("file" , "f" , "-" , "File to read Rego policy from. Defaults to reading from stdin." )
140+ policyCmd .PersistentFlags ().String ("github-token" , "" , "The Github API token to use when calling opslevel.repo.github function within a Rego policy. Overrides environment variable 'GITHUB_API_TOKEN'" )
141+
142+ viper .BindPFlags (policyCmd .PersistentFlags ())
143+ viper .BindEnv ("github-token" , "GITHUB_API_TOKEN" )
91144}
0 commit comments