Projects STRLCPY bearer Commits ffb360b0
🤬
  • feat: load rule definitions from GitHub release

  • Loading...
  • elsapet committed 1 year ago
    ffb360b0
    1 parent 5cbaf628
  • ■ ■ ■ ■ ■ ■
    pkg/commands/process/settings/ruleLoader.go
     1 +package settings
     2 + 
     3 +import (
     4 + "archive/tar"
     5 + "compress/gzip"
     6 + "encoding/json"
     7 + "fmt"
     8 + "io"
     9 + "net/http"
     10 + "os"
     11 + "path/filepath"
     12 + "strings"
     13 + 
     14 + "gopkg.in/yaml.v3"
     15 +)
     16 + 
     17 +const LATEST_RELEASE_URL = "https://api.github.com/repos/bearer/bearer/releases/latest"
     18 + 
     19 +// TODO: update this for bearer-rule structure
     20 +const BASE_RULE_FOLDER = "pkg/commands/process/settings/rules/"
     21 + 
     22 +func LoadRuleDefinitionsFromGitHub(ruleDefinitions map[string]RuleDefinition, builtInRuleDefinitions map[string]RuleDefinition) error {
     23 + resp, err := http.Get(LATEST_RELEASE_URL)
     24 + if err != nil {
     25 + return err
     26 + }
     27 + defer resp.Body.Close()
     28 + 
     29 + // Decode the response JSON to get the URL of the asset we want to download
     30 + var release struct {
     31 + TarballUrl string `json:"tarball_url"`
     32 + }
     33 + if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
     34 + return err
     35 + }
     36 + 
     37 + if release.TarballUrl == "" {
     38 + return fmt.Errorf("could not find source.tar.gz asset in latest release")
     39 + }
     40 + 
     41 + resp, err = http.Get(release.TarballUrl)
     42 + if err != nil {
     43 + return err
     44 + }
     45 + defer resp.Body.Close()
     46 + 
     47 + // Create a temporary file
     48 + tmpfile, err := os.CreateTemp("", "source-*.tar.gz")
     49 + if err != nil {
     50 + return err
     51 + }
     52 + defer os.Remove(tmpfile.Name())
     53 + defer tmpfile.Close()
     54 + 
     55 + // Copy the contents of the downloaded archive to the temporary file
     56 + if _, err := io.Copy(tmpfile, resp.Body); err != nil {
     57 + return err
     58 + }
     59 + 
     60 + tmpfile.Seek(0, 0) // reset file pointer to start of file
     61 + gzr, err := gzip.NewReader(tmpfile)
     62 + if err != nil {
     63 + return err
     64 + }
     65 + defer gzr.Close()
     66 + 
     67 + tr := tar.NewReader(gzr)
     68 + for {
     69 + header, err := tr.Next()
     70 + if err == io.EOF {
     71 + break
     72 + } else if err != nil {
     73 + return err
     74 + }
     75 + 
     76 + // TODO: only load rules for detected language(s)
     77 + if !isRuleFile(header.Name) {
     78 + continue
     79 + }
     80 + 
     81 + data := make([]byte, header.Size)
     82 + _, err = io.ReadFull(tr, data)
     83 + if err != nil {
     84 + return fmt.Errorf("failed to read file %s: %w", header.Name, err)
     85 + }
     86 + 
     87 + var ruleDefinition RuleDefinition
     88 + err = yaml.Unmarshal(data, &ruleDefinition)
     89 + if err != nil {
     90 + return fmt.Errorf("failed to unmarshal rule %s: %w", header.Name, err)
     91 + }
     92 + 
     93 + id := ruleDefinition.Metadata.ID
     94 + _, builtInRuleExists := builtInRuleDefinitions[id]
     95 + _, ruleExists := ruleDefinitions[id]
     96 + if builtInRuleExists || ruleExists {
     97 + return fmt.Errorf("duplicate built-in rule ID %s", id)
     98 + }
     99 + 
     100 + if strings.Contains(header.Name, "built_in_rules") {
     101 + builtInRuleDefinitions[id] = ruleDefinition
     102 + continue
     103 + }
     104 + 
     105 + ruleDefinitions[id] = ruleDefinition
     106 + }
     107 + 
     108 + return nil
     109 +}
     110 + 
     111 +func isRuleFile(headerName string) bool {
     112 + if strings.Contains(headerName, ".snapshots") {
     113 + return false
     114 + }
     115 + 
     116 + ext := filepath.Ext(headerName)
     117 + if ext != ".yaml" && ext != ".yml" {
     118 + return false
     119 + }
     120 + 
     121 + return strings.Contains(headerName, BASE_RULE_FOLDER)
     122 +}
     123 + 
  • ■ ■ ■ ■ ■ ■
    pkg/commands/process/settings/rules.go
    skipped 20 lines
    21 21   definitions := make(map[string]RuleDefinition)
    22 22   builtInDefinitions := make(map[string]RuleDefinition)
    23 23   
    24  - if err := loadRuleDefinitions(definitions, rulesFs); err != nil {
    25  - return nil, nil, fmt.Errorf("error loading default rules: %s", err)
     24 + if err := LoadRuleDefinitionsFromGitHub(definitions, builtInDefinitions); err != nil {
     25 + return nil, nil, fmt.Errorf("error loading rules: %s", err)
    26 26   }
     27 + 
    27 28   // add default documentation urls for default rules
    28 29   for id, definition := range definitions {
    29 30   if definition.Metadata.DocumentationUrl == "" {
    skipped 1 lines
    31 32   }
    32 33   }
    33 34   
    34  - if err := loadRuleDefinitions(builtInDefinitions, builtInRulesFs); err != nil {
    35  - return nil, nil, fmt.Errorf("error loading default built-in rules: %s", err)
    36  - }
    37  - 
    38 35   for _, dir := range externalRuleDirs {
    39 36   if strings.HasPrefix(dir, "~/") {
    40 37   dirname, _ := os.UserHomeDir()
    41 38   dir = filepath.Join(dirname, dir[2:])
    42 39   }
    43 40   log.Debug().Msgf("loading external rules from: %s", dir)
    44  - if err := loadRuleDefinitions(definitions, os.DirFS(dir)); err != nil {
     41 + if err := loadExternalRuleDefinitions(definitions, os.DirFS(dir)); err != nil {
    45 42   return nil, nil, fmt.Errorf("error loading external rules from %s: %w", dir, err)
    46 43   }
    47 44   }
    skipped 8 lines
    56 53   return buildRules(builtInDefinitions, builtInRules), buildRules(definitions, enabledRules), nil
    57 54  }
    58 55   
    59  -func loadRuleDefinitions(definitions map[string]RuleDefinition, dir fs.FS) error {
     56 +func loadExternalRuleDefinitions(definitions map[string]RuleDefinition, dir fs.FS) error {
    60 57   return fs.WalkDir(dir, ".", func(path string, dirEntry fs.DirEntry, err error) error {
    61 58   if err != nil {
    62 59   return err
    skipped 179 lines
  • ■ ■ ■ ■ ■ ■
    pkg/commands/process/settings/settings.go
    skipped 194 lines
    195 195  //go:embed policies.yml
    196 196  var defaultPolicies []byte
    197 197   
    198  -//go:embed rules/*
    199  -var rulesFs embed.FS
    200  - 
    201  -//go:embed built_in_rules/*
    202  -var builtInRulesFs embed.FS
    203  - 
    204 198  //go:embed policies/*
    205 199  var policiesFs embed.FS
    206 200   
    skipped 124 lines
Please wait...
Page is in error, reload to recover