/config/config.go

https://github.com/zricethezav/gitleaks · Go · 249 lines · 190 code · 28 blank · 31 comment · 63 complexity · 00ea62f460a1cb99875d1b1999d3b7ce MD5 · raw file

  1. package config
  2. import (
  3. "fmt"
  4. "path"
  5. "regexp"
  6. "strconv"
  7. "github.com/zricethezav/gitleaks/v6/options"
  8. "github.com/BurntSushi/toml"
  9. log "github.com/sirupsen/logrus"
  10. )
  11. // AllowList is struct containing items that if encountered will allowlist
  12. // a commit/line of code that would be considered a leak.
  13. type AllowList struct {
  14. Description string
  15. Regexes []*regexp.Regexp
  16. Commits []string
  17. Files []*regexp.Regexp
  18. Paths []*regexp.Regexp
  19. Repos []*regexp.Regexp
  20. }
  21. // Entropy represents an entropy range
  22. type Entropy struct {
  23. Min float64
  24. Max float64
  25. Group int
  26. }
  27. // Rule is a struct that contains information that is loaded from a gitleaks config.
  28. // This struct is used in the Config struct as an array of Rules and is iterated
  29. // over during an scan. Each rule will be checked. If a regex match is found AND
  30. // that match is not allowlisted (globally or locally), then a leak will be appended
  31. // to the final scan report.
  32. type Rule struct {
  33. Description string
  34. Regex *regexp.Regexp
  35. File *regexp.Regexp
  36. Path *regexp.Regexp
  37. Tags []string
  38. AllowList AllowList
  39. Entropies []Entropy
  40. }
  41. // Config is a composite struct of Rules and Allowlists
  42. // Each Rule contains a description, regular expression, tags, and allowlists if available
  43. type Config struct {
  44. Rules []Rule
  45. Allowlist AllowList
  46. }
  47. // TomlAllowList is a struct used in the TomlLoader that loads in allowlists from
  48. // specific rules or globally at the top level config
  49. type TomlAllowList struct {
  50. Description string
  51. Regexes []string
  52. Commits []string
  53. Files []string
  54. Paths []string
  55. Repos []string
  56. }
  57. // TomlLoader gets loaded with the values from a gitleaks toml config
  58. // see the config in config/defaults.go for an example. TomlLoader is used
  59. // to generate Config values (compiling regexes, etc).
  60. type TomlLoader struct {
  61. AllowList TomlAllowList
  62. Rules []struct {
  63. Description string
  64. Regex string
  65. File string
  66. Path string
  67. Tags []string
  68. Entropies []struct {
  69. Min string
  70. Max string
  71. Group string
  72. }
  73. AllowList TomlAllowList
  74. }
  75. }
  76. // NewConfig will create a new config struct which contains
  77. // rules on how gitleaks will proceed with its scan.
  78. // If no options are passed via cli then NewConfig will return
  79. // a default config which can be seen in config.go
  80. func NewConfig(options options.Options) (Config, error) {
  81. var cfg Config
  82. tomlLoader := TomlLoader{}
  83. var err error
  84. if options.Config != "" {
  85. _, err = toml.DecodeFile(options.Config, &tomlLoader)
  86. // append a allowlist rule for allowlisting the config
  87. tomlLoader.AllowList.Files = append(tomlLoader.AllowList.Files, path.Base(options.Config))
  88. } else {
  89. _, err = toml.Decode(DefaultConfig, &tomlLoader)
  90. }
  91. if err != nil {
  92. return cfg, err
  93. }
  94. cfg, err = tomlLoader.Parse()
  95. if err != nil {
  96. return cfg, err
  97. }
  98. return cfg, nil
  99. }
  100. // Parse will parse the values set in a TomlLoader and use those values
  101. // to create compiled regular expressions and rules used in scans
  102. func (tomlLoader TomlLoader) Parse() (Config, error) {
  103. var cfg Config
  104. for _, rule := range tomlLoader.Rules {
  105. // check and make sure the rule is valid
  106. if rule.Regex == "" && rule.Path == "" && rule.File == "" && len(rule.Entropies) == 0 {
  107. log.Warnf("Rule %s does not define any actionable data", rule.Description)
  108. continue
  109. }
  110. re, err := regexp.Compile(rule.Regex)
  111. if err != nil {
  112. return cfg, fmt.Errorf("problem loading config: %v", err)
  113. }
  114. fileNameRe, err := regexp.Compile(rule.File)
  115. if err != nil {
  116. return cfg, fmt.Errorf("problem loading config: %v", err)
  117. }
  118. filePathRe, err := regexp.Compile(rule.Path)
  119. if err != nil {
  120. return cfg, fmt.Errorf("problem loading config: %v", err)
  121. }
  122. // rule specific allowlists
  123. var allowList AllowList
  124. // rule specific regexes
  125. for _, re := range rule.AllowList.Regexes {
  126. allowListedRegex, err := regexp.Compile(re)
  127. if err != nil {
  128. return cfg, fmt.Errorf("problem loading config: %v", err)
  129. }
  130. allowList.Regexes = append(allowList.Regexes, allowListedRegex)
  131. }
  132. // rule specific filenames
  133. for _, re := range rule.AllowList.Files {
  134. allowListedRegex, err := regexp.Compile(re)
  135. if err != nil {
  136. return cfg, fmt.Errorf("problem loading config: %v", err)
  137. }
  138. allowList.Files = append(allowList.Files, allowListedRegex)
  139. }
  140. // rule specific paths
  141. for _, re := range rule.AllowList.Paths {
  142. allowListedRegex, err := regexp.Compile(re)
  143. if err != nil {
  144. return cfg, fmt.Errorf("problem loading config: %v", err)
  145. }
  146. allowList.Paths = append(allowList.Paths, allowListedRegex)
  147. }
  148. var entropies []Entropy
  149. for _, e := range rule.Entropies {
  150. min, err := strconv.ParseFloat(e.Min, 64)
  151. if err != nil {
  152. return cfg, err
  153. }
  154. max, err := strconv.ParseFloat(e.Max, 64)
  155. if err != nil {
  156. return cfg, err
  157. }
  158. if e.Group == "" {
  159. e.Group = "0"
  160. }
  161. group, err := strconv.ParseInt(e.Group, 10, 64)
  162. if err != nil {
  163. return cfg, err
  164. } else if int(group) >= len(re.SubexpNames()) {
  165. return cfg, fmt.Errorf("problem loading config: group cannot be higher than number of groups in regexp")
  166. } else if group < 0 {
  167. return cfg, fmt.Errorf("problem loading config: group cannot be lower than 0")
  168. } else if min > 8.0 || min < 0.0 || max > 8.0 || max < 0.0 {
  169. return cfg, fmt.Errorf("problem loading config: invalid entropy ranges, must be within 0.0-8.0")
  170. } else if min > max {
  171. return cfg, fmt.Errorf("problem loading config: entropy Min value cannot be higher than Max value")
  172. }
  173. entropies = append(entropies, Entropy{Min: min, Max: max, Group: int(group)})
  174. }
  175. r := Rule{
  176. Description: rule.Description,
  177. Regex: re,
  178. File: fileNameRe,
  179. Path: filePathRe,
  180. Tags: rule.Tags,
  181. AllowList: allowList,
  182. Entropies: entropies,
  183. }
  184. cfg.Rules = append(cfg.Rules, r)
  185. }
  186. // global regex allowLists
  187. for _, allowListRegex := range tomlLoader.AllowList.Regexes {
  188. re, err := regexp.Compile(allowListRegex)
  189. if err != nil {
  190. return cfg, fmt.Errorf("problem loading config: %v", err)
  191. }
  192. cfg.Allowlist.Regexes = append(cfg.Allowlist.Regexes, re)
  193. }
  194. // global file name allowLists
  195. for _, allowListFileName := range tomlLoader.AllowList.Files {
  196. re, err := regexp.Compile(allowListFileName)
  197. if err != nil {
  198. return cfg, fmt.Errorf("problem loading config: %v", err)
  199. }
  200. cfg.Allowlist.Files = append(cfg.Allowlist.Files, re)
  201. }
  202. // global file path allowLists
  203. for _, allowListFilePath := range tomlLoader.AllowList.Paths {
  204. re, err := regexp.Compile(allowListFilePath)
  205. if err != nil {
  206. return cfg, fmt.Errorf("problem loading config: %v", err)
  207. }
  208. cfg.Allowlist.Paths = append(cfg.Allowlist.Paths, re)
  209. }
  210. // global repo allowLists
  211. for _, allowListRepo := range tomlLoader.AllowList.Repos {
  212. re, err := regexp.Compile(allowListRepo)
  213. if err != nil {
  214. return cfg, fmt.Errorf("problem loading config: %v", err)
  215. }
  216. cfg.Allowlist.Repos = append(cfg.Allowlist.Repos, re)
  217. }
  218. cfg.Allowlist.Commits = tomlLoader.AllowList.Commits
  219. cfg.Allowlist.Description = tomlLoader.AllowList.Description
  220. return cfg, nil
  221. }