| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- package gitleaks
- import (
- "fmt"
- "os"
- "os/user"
- "regexp"
- "strconv"
- "strings"
- "github.com/BurntSushi/toml"
- "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
- )
- type entropyRange struct {
- v1 float64
- v2 float64
- }
- type Regex struct {
- description string
- regex *regexp.Regexp
- }
- // TomlConfig is used for loading gitleaks configs from a toml file
- type TomlConfig struct {
- Regexes []struct {
- Description string
- Regex string
- }
- Entropy struct {
- LineRegexes []string
- Ranges []string
- }
- Whitelist struct {
- Files []string
- Regexes []string
- Commits []string
- Repos []string
- }
- }
- // Config contains gitleaks config
- type Config struct {
- Regexes []Regex
- WhiteList struct {
- regexes []*regexp.Regexp
- files []*regexp.Regexp
- commits map[string]bool
- repos []*regexp.Regexp
- }
- Entropy struct {
- entropyRanges []*entropyRange
- regexes []*regexp.Regexp
- }
- sshAuth *ssh.PublicKeys
- }
- // loadToml loads of the toml config containing regexes and whitelists.
- // This function will first look if the configPath is set and load the config
- // from that file. Otherwise will then look for the path set by the GITHLEAKS_CONIFG
- // env var. If that is not set, then gitleaks will continue with the default configs
- // specified by the const var at the top `defaultConfig`
- func newConfig() (*Config, error) {
- var (
- tomlConfig TomlConfig
- configPath string
- config Config
- )
- if opts.ConfigPath != "" {
- configPath = opts.ConfigPath
- _, err := os.Stat(configPath)
- if err != nil {
- return nil, fmt.Errorf("no gitleaks config at %s", configPath)
- }
- } else {
- configPath = os.Getenv("GITLEAKS_CONFIG")
- }
- if configPath != "" {
- if _, err := toml.DecodeFile(configPath, &tomlConfig); err != nil {
- return nil, fmt.Errorf("problem loading config: %v", err)
- }
- } else {
- _, err := toml.Decode(defaultConfig, &tomlConfig)
- if err != nil {
- return nil, fmt.Errorf("problem loading default config: %v", err)
- }
- }
- sshAuth, err := getSSHAuth()
- if err != nil {
- return nil, err
- }
- config.sshAuth = sshAuth
- err = config.update(tomlConfig)
- if err != nil {
- return nil, err
- }
- return &config, err
- }
- // updateConfig will update a the global config values
- func (config *Config) update(tomlConfig TomlConfig) error {
- if len(tomlConfig.Entropy.Ranges) != 0 {
- err := config.updateEntropyRanges(tomlConfig.Entropy.Ranges)
- if err != nil {
- return err
- }
- }
- for _, regex := range tomlConfig.Entropy.LineRegexes {
- config.Entropy.regexes = append(config.Entropy.regexes, regexp.MustCompile(regex))
- }
- if singleSearchRegex != nil {
- config.Regexes = append(config.Regexes, Regex{
- description: "single search",
- regex: singleSearchRegex,
- })
- } else {
- for _, regex := range tomlConfig.Regexes {
- config.Regexes = append(config.Regexes, Regex{
- description: regex.Description,
- regex: regexp.MustCompile(regex.Regex),
- })
- }
- }
- config.WhiteList.commits = make(map[string]bool)
- for _, commit := range tomlConfig.Whitelist.Commits {
- config.WhiteList.commits[commit] = true
- }
- for _, regex := range tomlConfig.Whitelist.Files {
- config.WhiteList.files = append(config.WhiteList.files, regexp.MustCompile(regex))
- }
- for _, regex := range tomlConfig.Whitelist.Regexes {
- config.WhiteList.regexes = append(config.WhiteList.regexes, regexp.MustCompile(regex))
- }
- for _, regex := range tomlConfig.Whitelist.Repos {
- config.WhiteList.repos = append(config.WhiteList.repos, regexp.MustCompile(regex))
- }
- return nil
- }
- // entropyRanges hydrates entropyRanges which allows for fine tuning entropy checking
- func (config *Config) updateEntropyRanges(entropyLimitStr []string) error {
- for _, span := range entropyLimitStr {
- split := strings.Split(span, "-")
- v1, err := strconv.ParseFloat(split[0], 64)
- if err != nil {
- return err
- }
- v2, err := strconv.ParseFloat(split[1], 64)
- if err != nil {
- return err
- }
- if v1 > v2 {
- return fmt.Errorf("entropy range must be ascending")
- }
- r := &entropyRange{
- v1: v1,
- v2: v2,
- }
- if r.v1 > 8.0 || r.v1 < 0.0 || r.v2 > 8.0 || r.v2 < 0.0 {
- return fmt.Errorf("invalid entropy ranges, must be within 0.0-8.0")
- }
- config.Entropy.entropyRanges = append(config.Entropy.entropyRanges, r)
- }
- return nil
- }
- // externalConfig will attempt to load a pinned ".gitleaks.toml" configuration file
- // from a remote or local repo. Use the --repo-config option to trigger this.
- func (config *Config) updateFromRepo(repo *RepoInfo) error {
- var tomlConfig TomlConfig
- wt, err := repo.repository.Worktree()
- if err != nil {
- return err
- }
- f, err := wt.Filesystem.Open(".gitleaks.toml")
- if err != nil {
- return err
- }
- if _, err := toml.DecodeReader(f, &config); err != nil {
- return fmt.Errorf("problem loading config: %v", err)
- }
- f.Close()
- if err != nil {
- return err
- }
- return config.update(tomlConfig)
- }
- // getSSHAuth return an ssh auth use by go-git to clone repos behind authentication.
- // If --ssh-key is set then it will attempt to load the key from that path. If not,
- // gitleaks will use the default $HOME/.ssh/id_rsa key
- func getSSHAuth() (*ssh.PublicKeys, error) {
- var (
- sshKeyPath string
- )
- if opts.SSHKey != "" {
- sshKeyPath = opts.SSHKey
- } else {
- // try grabbing default
- c, err := user.Current()
- if err != nil {
- return nil, nil
- }
- sshKeyPath = fmt.Sprintf("%s/.ssh/id_rsa", c.HomeDir)
- }
- sshAuth, err := ssh.NewPublicKeysFromFile("git", sshKeyPath, "")
- if err != nil {
- if strings.HasPrefix(opts.Repo, "git") {
- // if you are attempting to clone a git repo via ssh and supply a bad ssh key,
- // the clone will fail.
- return nil, fmt.Errorf("unable to generate ssh key: %v", err)
- }
- }
- return sshAuth, nil
- }
|