config.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package config
  2. import (
  3. "fmt"
  4. "github.com/BurntSushi/toml"
  5. "github.com/zricethezav/gitleaks/options"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. )
  10. // Whitelist is struct containing items that if encountered will whitelist
  11. // a commit/line of code that would be considered a leak.
  12. type Whitelist struct {
  13. Description string
  14. Regex *regexp.Regexp
  15. File *regexp.Regexp
  16. }
  17. // entropy represents an entropy range
  18. type entropy struct {
  19. P1, P2 float64
  20. }
  21. // Rule is a struct that contains information that is loaded from a gitleaks config.
  22. // This struct is used in the Config struct as an array of Rules and is iterated
  23. // over during an audit. Each rule will be checked. If a regex match is found AND
  24. // that match is not whitelisted (globally or locally), then a leak will be appended
  25. // to the final audit report.
  26. type Rule struct {
  27. Description string
  28. Regex *regexp.Regexp
  29. Tags []string
  30. Whitelist []Whitelist
  31. Entropy []entropy
  32. }
  33. // Config is a composite struct of Rules and Whitelists
  34. // Each Rule contains a description, regular expression, tags, and whitelists if available
  35. type Config struct {
  36. FileRegex *regexp.Regexp
  37. Message *regexp.Regexp
  38. Rules []Rule
  39. Whitelist struct {
  40. Description string
  41. Commits []string
  42. File *regexp.Regexp
  43. }
  44. }
  45. // TomlLoader gets loaded with the values from a gitleaks toml config
  46. // see the config in config/defaults.go for an example. TomlLoader is used
  47. // to generate Config values (compiling regexes, etc).
  48. type TomlLoader struct {
  49. Global struct {
  50. File string
  51. Message string
  52. }
  53. Whitelist struct {
  54. Description string
  55. Commits []string
  56. File string
  57. }
  58. Rules []struct {
  59. Description string
  60. Regex string
  61. Tags []string
  62. Entropies []string
  63. Whitelist []struct {
  64. Description string
  65. Regex string
  66. File string
  67. }
  68. }
  69. }
  70. // NewConfig will create a new config struct which contains
  71. // rules on how gitleaks will proceed with its audit.
  72. // If no options are passed via cli then NewConfig will return
  73. // a default config which can be seen in config.go
  74. func NewConfig(options options.Options) (Config, error) {
  75. var cfg Config
  76. tomlLoader := TomlLoader{}
  77. var err error
  78. if options.Config != "" {
  79. _, err = toml.DecodeFile(options.Config, &tomlLoader)
  80. } else {
  81. _, err = toml.Decode(DefaultConfig, &tomlLoader)
  82. }
  83. if err != nil {
  84. return cfg, err
  85. }
  86. cfg, err = tomlLoader.Parse()
  87. if err != nil {
  88. return cfg, err
  89. }
  90. return cfg, nil
  91. }
  92. // Parse will parse the values set in a TomlLoader and use those values
  93. // to create compiled regular expressions and rules used in audits
  94. func (tomlLoader TomlLoader) Parse() (Config, error) {
  95. var cfg Config
  96. for _, rule := range tomlLoader.Rules {
  97. re, err := regexp.Compile(rule.Regex)
  98. if err != nil {
  99. return cfg, fmt.Errorf("problem loading config: %v", err)
  100. }
  101. // rule specific whitelists
  102. var whitelists []Whitelist
  103. for _, wl := range rule.Whitelist {
  104. re, err := regexp.Compile(wl.Regex)
  105. if err != nil {
  106. return cfg, fmt.Errorf("problem loading config: %v", err)
  107. }
  108. fileRe, err := regexp.Compile(wl.File)
  109. if err != nil {
  110. return cfg, fmt.Errorf("problem loading config: %v", err)
  111. }
  112. whitelists = append(whitelists, Whitelist{
  113. Description: wl.Description,
  114. File: fileRe,
  115. Regex: re,
  116. })
  117. }
  118. entropies, err := getEntropy(rule.Entropies)
  119. if err != nil {
  120. return cfg, err
  121. }
  122. cfg.Rules = append(cfg.Rules, Rule{
  123. Description: rule.Description,
  124. Regex: re,
  125. Tags: rule.Tags,
  126. Whitelist: whitelists,
  127. Entropy: entropies,
  128. })
  129. }
  130. // global leaks
  131. if tomlLoader.Global.File != "" {
  132. re, err := regexp.Compile(tomlLoader.Global.File)
  133. if err != nil {
  134. return cfg, fmt.Errorf("problem loading config: %v", err)
  135. }
  136. cfg.FileRegex = re
  137. }
  138. if tomlLoader.Global.Message != "" {
  139. re, err := regexp.Compile(tomlLoader.Global.Message)
  140. if err != nil {
  141. return cfg, fmt.Errorf("problem loading config: %v", err)
  142. }
  143. cfg.Message = re
  144. }
  145. // global whitelists
  146. if tomlLoader.Whitelist.File != "" {
  147. re, err := regexp.Compile(tomlLoader.Whitelist.File)
  148. if err != nil {
  149. return cfg, fmt.Errorf("problem loading config: %v", err)
  150. }
  151. cfg.Whitelist.File = re
  152. }
  153. cfg.Whitelist.Commits = tomlLoader.Whitelist.Commits
  154. cfg.Whitelist.Description = tomlLoader.Whitelist.Description
  155. return cfg, nil
  156. }
  157. // getEntropy
  158. func getEntropy(entropyStr []string) ([]entropy, error) {
  159. var ranges []entropy
  160. for _, span := range entropyStr {
  161. split := strings.Split(span, "-")
  162. v1, err := strconv.ParseFloat(split[0], 64)
  163. if err != nil {
  164. return nil, err
  165. }
  166. v2, err := strconv.ParseFloat(split[1], 64)
  167. if err != nil {
  168. return nil, err
  169. }
  170. if v1 > v2 {
  171. return nil, fmt.Errorf("entropy range must be ascending")
  172. }
  173. r := entropy{P1: v1, P2: v2}
  174. if r.P1 > 8.0 || r.P1 < 0.0 || r.P2 > 8.0 || r.P2 < 0.0 {
  175. return nil, fmt.Errorf("invalid entropy ranges, must be within 0.0-8.0")
  176. }
  177. ranges = append(ranges, r)
  178. }
  179. return ranges, nil
  180. }