config.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package config
  2. import (
  3. _ "embed"
  4. "fmt"
  5. "regexp"
  6. "strings"
  7. )
  8. //go:embed gitleaks.toml
  9. var DefaultConfig string
  10. // ViperConfig is the config struct used by the Viper config package
  11. // to parse the config file. This struct does not include regular expressions.
  12. // It is used as an intermediary to convert the Viper config to the Config struct.
  13. type ViperConfig struct {
  14. Description string
  15. Rules []struct {
  16. ID string
  17. Description string
  18. Entropy float64
  19. SecretGroup int
  20. Regex string
  21. Keywords []string
  22. Path string
  23. Tags []string
  24. Allowlist struct {
  25. Regexes []string
  26. Paths []string
  27. Commits []string
  28. StopWords []string
  29. }
  30. }
  31. Allowlist struct {
  32. Regexes []string
  33. Paths []string
  34. Commits []string
  35. StopWords []string
  36. }
  37. }
  38. // Config is a configuration struct that contains rules and an allowlist if present.
  39. type Config struct {
  40. Path string
  41. Description string
  42. Rules []*Rule
  43. Allowlist Allowlist
  44. Keywords []string
  45. }
  46. func (vc *ViperConfig) Translate() (Config, error) {
  47. var (
  48. rules []*Rule
  49. keywords []string
  50. )
  51. for _, r := range vc.Rules {
  52. var allowlistRegexes []*regexp.Regexp
  53. for _, a := range r.Allowlist.Regexes {
  54. allowlistRegexes = append(allowlistRegexes, regexp.MustCompile(a))
  55. }
  56. var allowlistPaths []*regexp.Regexp
  57. for _, a := range r.Allowlist.Paths {
  58. allowlistPaths = append(allowlistPaths, regexp.MustCompile(a))
  59. }
  60. if r.Keywords == nil {
  61. r.Keywords = []string{}
  62. } else {
  63. for _, k := range r.Keywords {
  64. keywords = append(keywords, strings.ToLower(k))
  65. }
  66. }
  67. if r.Tags == nil {
  68. r.Tags = []string{}
  69. }
  70. var configRegex *regexp.Regexp
  71. var configPathRegex *regexp.Regexp
  72. if r.Regex == "" {
  73. configRegex = nil
  74. } else {
  75. configRegex = regexp.MustCompile(r.Regex)
  76. }
  77. if r.Path == "" {
  78. configPathRegex = nil
  79. } else {
  80. configPathRegex = regexp.MustCompile(r.Path)
  81. }
  82. r := &Rule{
  83. Description: r.Description,
  84. RuleID: r.ID,
  85. Regex: configRegex,
  86. Path: configPathRegex,
  87. SecretGroup: r.SecretGroup,
  88. Entropy: r.Entropy,
  89. Tags: r.Tags,
  90. Keywords: r.Keywords,
  91. Allowlist: Allowlist{
  92. Regexes: allowlistRegexes,
  93. Paths: allowlistPaths,
  94. Commits: r.Allowlist.Commits,
  95. StopWords: r.Allowlist.StopWords,
  96. },
  97. }
  98. if r.Regex != nil && r.SecretGroup > r.Regex.NumSubexp() {
  99. return Config{}, fmt.Errorf("%s invalid regex secret group %d, max regex secret group %d", r.Description, r.SecretGroup, r.Regex.NumSubexp())
  100. }
  101. rules = append(rules, r)
  102. }
  103. var allowlistRegexes []*regexp.Regexp
  104. for _, a := range vc.Allowlist.Regexes {
  105. allowlistRegexes = append(allowlistRegexes, regexp.MustCompile(a))
  106. }
  107. var allowlistPaths []*regexp.Regexp
  108. for _, a := range vc.Allowlist.Paths {
  109. allowlistPaths = append(allowlistPaths, regexp.MustCompile(a))
  110. }
  111. return Config{
  112. Description: vc.Description,
  113. Rules: rules,
  114. Allowlist: Allowlist{
  115. Regexes: allowlistRegexes,
  116. Paths: allowlistPaths,
  117. Commits: vc.Allowlist.Commits,
  118. StopWords: vc.Allowlist.StopWords,
  119. },
  120. Keywords: keywords,
  121. }, nil
  122. }