gitleaks_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "path"
  7. "regexp"
  8. "strings"
  9. "testing"
  10. "github.com/franela/goblin"
  11. git "gopkg.in/src-d/go-git.v4"
  12. "gopkg.in/src-d/go-git.v4/storage/memory"
  13. )
  14. const testWhitelistCommit = `
  15. [[regexes]]
  16. description = "AWS"
  17. regex = '''AKIA[0-9A-Z]{16}'''
  18. [whitelist]
  19. commits = [
  20. "eaeffdc65b4c73ccb67e75d96bd8743be2c85973",
  21. ]
  22. `
  23. const testWhitelistFile = `
  24. [[regexes]]
  25. description = "AWS"
  26. regex = '''AKIA[0-9A-Z]{16}'''
  27. [whitelist]
  28. files = [
  29. ".go",
  30. ]
  31. `
  32. const testWhitelistBranch = `
  33. [[regexes]]
  34. description = "AWS"
  35. regex = '''AKIA[0-9A-Z]{16}'''
  36. [whitelist]
  37. branches = [
  38. "origin/master",
  39. ]
  40. `
  41. const testWhitelistRegex = `
  42. [[regexes]]
  43. description = "AWS"
  44. regex = '''AKIA[0-9A-Z]{16}'''
  45. [whitelist]
  46. regexes= [
  47. "AKIA",
  48. ]
  49. `
  50. const testWhitelistRepo = `
  51. [[regexes]]
  52. description = "AWS"
  53. regex = '''AKIA[0-9A-Z]{16}'''
  54. [whitelist]
  55. repos = [
  56. "gronit",
  57. ]
  58. `
  59. var benchmarkRepo *RepoDescriptor
  60. var benchmarkLeaksRepo *RepoDescriptor
  61. func getBenchmarkLeaksRepo() *RepoDescriptor {
  62. if benchmarkLeaksRepo != nil {
  63. return benchmarkLeaksRepo
  64. }
  65. leaksR, _ := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
  66. URL: "https://github.com/gitleakstest/gronit.git",
  67. })
  68. benchmarkLeaksRepo = &RepoDescriptor{
  69. repository: leaksR,
  70. }
  71. return benchmarkLeaksRepo
  72. }
  73. func getBenchmarkRepo() *RepoDescriptor {
  74. if benchmarkRepo != nil {
  75. return benchmarkRepo
  76. }
  77. bmRepo, _ := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
  78. URL: "https://github.com/apple/swift-package-manager.git",
  79. })
  80. benchmarkRepo = &RepoDescriptor{
  81. repository: bmRepo,
  82. }
  83. return benchmarkRepo
  84. }
  85. func TestGetRepo(t *testing.T) {
  86. var err error
  87. dir, err = ioutil.TempDir("", "gitleaksTestRepo")
  88. defer os.RemoveAll(dir)
  89. if err != nil {
  90. panic(err)
  91. }
  92. _, err = git.PlainClone(dir, false, &git.CloneOptions{
  93. URL: "https://github.com/gitleakstest/gronit",
  94. })
  95. if err != nil {
  96. panic(err)
  97. }
  98. var tests = []struct {
  99. testOpts Options
  100. description string
  101. expectedErrMsg string
  102. }{
  103. {
  104. testOpts: Options{
  105. Repo: "https://github.com/gitleakstest/gronit",
  106. },
  107. description: "test plain clone remote repo",
  108. expectedErrMsg: "",
  109. },
  110. {
  111. testOpts: Options{
  112. Repo: "https://github.com/gitleakstest/gronit",
  113. Disk: true,
  114. },
  115. description: "test on disk clone remote repo",
  116. expectedErrMsg: "",
  117. },
  118. {
  119. testOpts: Options{
  120. RepoPath: dir,
  121. },
  122. description: "test local clone repo",
  123. expectedErrMsg: "",
  124. },
  125. {
  126. testOpts: Options{
  127. Repo: "https://github.com/gitleakstest/nope",
  128. },
  129. description: "test no repo",
  130. expectedErrMsg: "authentication required",
  131. },
  132. {
  133. testOpts: Options{
  134. Repo: "https://github.com/gitleakstest/private",
  135. IncludePrivate: true,
  136. },
  137. description: "test private repo",
  138. expectedErrMsg: "invalid auth method",
  139. },
  140. {
  141. testOpts: Options{
  142. Repo: "https://github.com/gitleakstest/private",
  143. IncludePrivate: true,
  144. Disk: true,
  145. },
  146. description: "test private repo",
  147. expectedErrMsg: "invalid auth method",
  148. },
  149. }
  150. g := goblin.Goblin(t)
  151. for _, test := range tests {
  152. g.Describe("TestGetRepo", func() {
  153. g.It(test.description, func() {
  154. opts = test.testOpts
  155. _, err := cloneRepo()
  156. if err != nil {
  157. g.Assert(err.Error()).Equal(test.expectedErrMsg)
  158. }
  159. })
  160. })
  161. }
  162. }
  163. func TestRun(t *testing.T) {
  164. var err error
  165. configsDir := testTomlLoader()
  166. dir, err = ioutil.TempDir("", "gitleaksTestOwner")
  167. defer os.RemoveAll(dir)
  168. if err != nil {
  169. panic(err)
  170. }
  171. git.PlainClone(dir+"/gronit", false, &git.CloneOptions{
  172. URL: "https://github.com/gitleakstest/gronit",
  173. })
  174. git.PlainClone(dir+"/h1domains", false, &git.CloneOptions{
  175. URL: "https://github.com/gitleakstest/h1domains",
  176. })
  177. var tests = []struct {
  178. testOpts Options
  179. description string
  180. expectedErrMsg string
  181. whiteListRepos []string
  182. numLeaks int
  183. configPath string
  184. commitPerPage int
  185. }{
  186. {
  187. testOpts: Options{
  188. GithubUser: "gitleakstest",
  189. },
  190. description: "test github user",
  191. numLeaks: 2,
  192. expectedErrMsg: "",
  193. },
  194. {
  195. testOpts: Options{
  196. GithubUser: "gitleakstest",
  197. Disk: true,
  198. },
  199. description: "test github user on disk ",
  200. numLeaks: 2,
  201. expectedErrMsg: "",
  202. },
  203. {
  204. testOpts: Options{
  205. GithubOrg: "gitleakstestorg",
  206. },
  207. description: "test github org",
  208. numLeaks: 2,
  209. expectedErrMsg: "",
  210. },
  211. {
  212. testOpts: Options{
  213. GithubOrg: "gitleakstestorg",
  214. Disk: true,
  215. },
  216. description: "test org on disk",
  217. numLeaks: 2,
  218. expectedErrMsg: "",
  219. },
  220. {
  221. testOpts: Options{
  222. OwnerPath: dir,
  223. },
  224. description: "test owner path",
  225. numLeaks: 2,
  226. expectedErrMsg: "",
  227. },
  228. {
  229. testOpts: Options{
  230. GithubOrg: "gitleakstestorg",
  231. IncludePrivate: true,
  232. SSHKey: "reallyreallyreallyreallywrongpath",
  233. },
  234. description: "test private org no ssh",
  235. numLeaks: 0,
  236. expectedErrMsg: "unable to generate ssh key: open reallyreallyreallyreallywrongpath: no such file or directory",
  237. },
  238. {
  239. testOpts: Options{
  240. Repo: "https://github.com/gitleakstest/gronit.git",
  241. },
  242. description: "test leak",
  243. numLeaks: 2,
  244. expectedErrMsg: "",
  245. },
  246. {
  247. testOpts: Options{
  248. Repo: "https://github.com/gitleakstest/h1domains.git",
  249. },
  250. description: "test clean",
  251. numLeaks: 0,
  252. expectedErrMsg: "",
  253. },
  254. {
  255. testOpts: Options{
  256. Repo: "https://github.com/gitleakstest/empty.git",
  257. },
  258. description: "test empty",
  259. numLeaks: 0,
  260. expectedErrMsg: "reference not found",
  261. },
  262. {
  263. testOpts: Options{
  264. GithubOrg: "gitleakstestorg",
  265. },
  266. description: "test github org, whitelist repo",
  267. numLeaks: 0,
  268. expectedErrMsg: "",
  269. configPath: path.Join(configsDir, "repo"),
  270. },
  271. {
  272. testOpts: Options{
  273. GithubOrg: "gitleakstestorg",
  274. ExcludeForks: true,
  275. },
  276. description: "test github org, exclude forks",
  277. numLeaks: 0,
  278. expectedErrMsg: "",
  279. },
  280. {
  281. testOpts: Options{
  282. GithubPR: "https://github.com/gitleakstest/gronit/pull/1",
  283. },
  284. description: "test github pr",
  285. numLeaks: 4,
  286. expectedErrMsg: "",
  287. },
  288. {
  289. testOpts: Options{
  290. GithubPR: "https://github.com/gitleakstest/gronit/pull/1",
  291. },
  292. description: "test github pr",
  293. numLeaks: 4,
  294. expectedErrMsg: "",
  295. commitPerPage: 1,
  296. },
  297. }
  298. g := goblin.Goblin(t)
  299. for _, test := range tests {
  300. g.Describe("TestRun", func() {
  301. g.It(test.description, func() {
  302. if test.configPath != "" {
  303. os.Setenv("GITLEAKS_CONFIG", test.configPath)
  304. }
  305. if test.commitPerPage != 0 {
  306. githubPages = test.commitPerPage
  307. }
  308. opts = test.testOpts
  309. leaks, err := run()
  310. if err != nil {
  311. g.Assert(err.Error()).Equal(test.expectedErrMsg)
  312. }
  313. g.Assert(len(leaks)).Equal(test.numLeaks)
  314. githubPages = 100
  315. })
  316. })
  317. }
  318. }
  319. func TestWriteReport(t *testing.T) {
  320. tmpDir, _ := ioutil.TempDir("", "reportDir")
  321. reportJSON := path.Join(tmpDir, "report.json")
  322. reportJASON := path.Join(tmpDir, "report.jason")
  323. reportVOID := path.Join("thereIsNoWay", "thisReportWillGetWritten.json")
  324. reportCSV := path.Join(tmpDir, "report.csv")
  325. defer os.RemoveAll(tmpDir)
  326. leaks := []Leak{
  327. {
  328. Line: "eat",
  329. Commit: "your",
  330. Offender: "veggies",
  331. Type: "and",
  332. Message: "get",
  333. Author: "some",
  334. File: "sleep",
  335. Branch: "thxu",
  336. },
  337. }
  338. var tests = []struct {
  339. leaks []Leak
  340. reportFile string
  341. fileName string
  342. description string
  343. testOpts Options
  344. expectedErrMsg string
  345. }{
  346. {
  347. leaks: leaks,
  348. reportFile: reportJSON,
  349. fileName: "report.json",
  350. description: "can we write a json file",
  351. testOpts: Options{
  352. Report: reportJSON,
  353. },
  354. },
  355. {
  356. leaks: leaks,
  357. reportFile: reportCSV,
  358. fileName: "report.csv",
  359. description: "can we write a csv file",
  360. testOpts: Options{
  361. Report: reportCSV,
  362. },
  363. },
  364. {
  365. leaks: leaks,
  366. reportFile: reportJASON,
  367. fileName: "report.jason",
  368. description: "bad file",
  369. expectedErrMsg: "Report should be a .json or .csv file",
  370. testOpts: Options{
  371. Report: reportJASON,
  372. },
  373. },
  374. {
  375. leaks: leaks,
  376. reportFile: reportVOID,
  377. fileName: "report.jason",
  378. description: "bad dir",
  379. expectedErrMsg: "thereIsNoWay does not exist",
  380. testOpts: Options{
  381. Report: reportVOID,
  382. },
  383. },
  384. }
  385. g := goblin.Goblin(t)
  386. for _, test := range tests {
  387. g.Describe("TestWriteReport", func() {
  388. g.It(test.description, func() {
  389. opts = test.testOpts
  390. err := optsGuard()
  391. if err != nil {
  392. g.Assert(err.Error()).Equal(test.expectedErrMsg)
  393. } else {
  394. writeReport(test.leaks)
  395. f, _ := os.Stat(test.reportFile)
  396. g.Assert(f.Name()).Equal(test.fileName)
  397. }
  398. })
  399. })
  400. }
  401. }
  402. func testTomlLoader() string {
  403. tmpDir, _ := ioutil.TempDir("", "whiteListConfigs")
  404. ioutil.WriteFile(path.Join(tmpDir, "regex"), []byte(testWhitelistRegex), 0644)
  405. ioutil.WriteFile(path.Join(tmpDir, "branch"), []byte(testWhitelistBranch), 0644)
  406. ioutil.WriteFile(path.Join(tmpDir, "commit"), []byte(testWhitelistCommit), 0644)
  407. ioutil.WriteFile(path.Join(tmpDir, "file"), []byte(testWhitelistFile), 0644)
  408. ioutil.WriteFile(path.Join(tmpDir, "repo"), []byte(testWhitelistRepo), 0644)
  409. return tmpDir
  410. }
  411. func TestAuditRepo(t *testing.T) {
  412. var leaks []Leak
  413. err := loadToml()
  414. configsDir := testTomlLoader()
  415. defer os.RemoveAll(configsDir)
  416. if err != nil {
  417. panic(err)
  418. }
  419. leaksR, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
  420. URL: "https://github.com/gitleakstest/gronit.git",
  421. })
  422. if err != nil {
  423. panic(err)
  424. }
  425. leaksRepo := &RepoDescriptor{
  426. repository: leaksR,
  427. name: "gronit",
  428. }
  429. cleanR, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
  430. URL: "https://github.com/gitleakstest/h1domains.git",
  431. })
  432. if err != nil {
  433. panic(err)
  434. }
  435. cleanRepo := &RepoDescriptor{
  436. repository: cleanR,
  437. name: "h1domains",
  438. }
  439. var tests = []struct {
  440. testOpts Options
  441. description string
  442. expectedErrMsg string
  443. numLeaks int
  444. repo *RepoDescriptor
  445. whiteListFiles []*regexp.Regexp
  446. whiteListCommits map[string]bool
  447. whiteListBranches []string
  448. whiteListRepos []string
  449. whiteListRegexes []*regexp.Regexp
  450. configPath string
  451. }{
  452. {
  453. repo: leaksRepo,
  454. description: "two leaks present",
  455. numLeaks: 2,
  456. },
  457. {
  458. repo: leaksRepo,
  459. description: "two leaks present limit goroutines",
  460. numLeaks: 2,
  461. testOpts: Options{
  462. MaxGoRoutines: 4,
  463. },
  464. },
  465. {
  466. repo: leaksRepo,
  467. description: "audit specific bad branch",
  468. numLeaks: 2,
  469. testOpts: Options{
  470. Branch: "master",
  471. },
  472. },
  473. {
  474. repo: leaksRepo,
  475. description: "audit specific good branch",
  476. numLeaks: 0,
  477. testOpts: Options{
  478. Branch: "dev",
  479. },
  480. },
  481. {
  482. repo: leaksRepo,
  483. description: "audit all branch",
  484. numLeaks: 6,
  485. testOpts: Options{
  486. AuditAllRefs: true,
  487. },
  488. },
  489. {
  490. repo: leaksRepo,
  491. description: "audit all branch whitelist 1",
  492. numLeaks: 4,
  493. testOpts: Options{
  494. AuditAllRefs: true,
  495. },
  496. whiteListBranches: []string{
  497. "origin/master",
  498. },
  499. },
  500. {
  501. repo: leaksRepo,
  502. description: "two leaks present whitelist AWS.. no leaks",
  503. whiteListRegexes: []*regexp.Regexp{
  504. regexp.MustCompile("AKIA"),
  505. },
  506. numLeaks: 0,
  507. },
  508. {
  509. repo: leaksRepo,
  510. description: "two leaks present limit goroutines",
  511. numLeaks: 2,
  512. },
  513. {
  514. repo: cleanRepo,
  515. description: "no leaks present",
  516. numLeaks: 0,
  517. },
  518. {
  519. repo: leaksRepo,
  520. description: "two leaks present whitelist go files",
  521. whiteListFiles: []*regexp.Regexp{
  522. regexp.MustCompile(".go"),
  523. },
  524. numLeaks: 0,
  525. },
  526. {
  527. repo: leaksRepo,
  528. description: "two leaks present whitelist bad commit",
  529. whiteListCommits: map[string]bool{
  530. "eaeffdc65b4c73ccb67e75d96bd8743be2c85973": true,
  531. },
  532. numLeaks: 1,
  533. },
  534. {
  535. repo: leaksRepo,
  536. description: "redact",
  537. testOpts: Options{
  538. Redact: true,
  539. },
  540. numLeaks: 2,
  541. },
  542. {
  543. repo: leaksRepo,
  544. description: "toml whitelist regex",
  545. configPath: path.Join(configsDir, "regex"),
  546. numLeaks: 0,
  547. },
  548. {
  549. repo: leaksRepo,
  550. description: "toml whitelist branch",
  551. configPath: path.Join(configsDir, "branch"),
  552. testOpts: Options{
  553. AuditAllRefs: true,
  554. },
  555. numLeaks: 4,
  556. },
  557. {
  558. repo: leaksRepo,
  559. description: "toml whitelist file",
  560. configPath: path.Join(configsDir, "file"),
  561. numLeaks: 0,
  562. },
  563. {
  564. repo: leaksRepo,
  565. description: "toml whitelist commit",
  566. configPath: path.Join(configsDir, "commit"),
  567. numLeaks: 1,
  568. },
  569. {
  570. repo: leaksRepo,
  571. description: "audit whitelist repo",
  572. numLeaks: 0,
  573. whiteListRepos: []string{
  574. "gronit",
  575. },
  576. },
  577. {
  578. repo: leaksRepo,
  579. description: "toml whitelist repo",
  580. numLeaks: 0,
  581. configPath: path.Join(configsDir, "repo"),
  582. },
  583. {
  584. repo: leaksRepo,
  585. description: "leaks present with entropy",
  586. testOpts: Options{
  587. Entropy: 4.7,
  588. },
  589. numLeaks: 7,
  590. },
  591. {
  592. repo: leaksRepo,
  593. description: "Audit until specific commit",
  594. numLeaks: 1,
  595. testOpts: Options{
  596. Commit: "f6839959b7bbdcd23008f1fb16f797f35bcd3a0c",
  597. },
  598. },
  599. {
  600. repo: leaksRepo,
  601. description: "commit depth = 1, no leaks",
  602. numLeaks: 0,
  603. testOpts: Options{
  604. Depth: 1,
  605. },
  606. },
  607. {
  608. repo: leaksRepo,
  609. description: "commit depth = 2, one leak",
  610. numLeaks: 1,
  611. testOpts: Options{
  612. Depth: 2,
  613. },
  614. },
  615. }
  616. whiteListCommits = make(map[string]bool)
  617. g := goblin.Goblin(t)
  618. for _, test := range tests {
  619. g.Describe("TestAuditRepo", func() {
  620. g.It(test.description, func() {
  621. opts = test.testOpts
  622. // settin da globs
  623. if test.whiteListFiles != nil {
  624. whiteListFiles = test.whiteListFiles
  625. } else {
  626. whiteListFiles = nil
  627. }
  628. if test.whiteListCommits != nil {
  629. whiteListCommits = test.whiteListCommits
  630. } else {
  631. whiteListCommits = nil
  632. }
  633. if test.whiteListBranches != nil {
  634. whiteListBranches = test.whiteListBranches
  635. } else {
  636. whiteListBranches = nil
  637. }
  638. if test.whiteListRegexes != nil {
  639. whiteListRegexes = test.whiteListRegexes
  640. } else {
  641. whiteListRegexes = nil
  642. }
  643. if test.whiteListRepos != nil {
  644. whiteListRepos = test.whiteListRepos
  645. } else {
  646. whiteListRepos = nil
  647. }
  648. // config paths
  649. if test.configPath != "" {
  650. os.Setenv("GITLEAKS_CONFIG", test.configPath)
  651. loadToml()
  652. }
  653. leaks, err = auditGitRepo(test.repo)
  654. if opts.Redact {
  655. g.Assert(leaks[0].Offender).Equal("REDACTED")
  656. }
  657. g.Assert(len(leaks)).Equal(test.numLeaks)
  658. })
  659. })
  660. }
  661. }
  662. func TestOptionGuard(t *testing.T) {
  663. var tests = []struct {
  664. testOpts Options
  665. githubToken bool
  666. description string
  667. expectedErrMsg string
  668. expectedErrMsgFuzzy string
  669. }{
  670. {
  671. testOpts: Options{},
  672. description: "default no opts",
  673. expectedErrMsg: "",
  674. },
  675. {
  676. testOpts: Options{
  677. IncludePrivate: true,
  678. GithubOrg: "fakeOrg",
  679. },
  680. description: "private org no githubtoken",
  681. expectedErrMsg: "user/organization private repos require env var GITHUB_TOKEN to be set",
  682. githubToken: false,
  683. },
  684. {
  685. testOpts: Options{
  686. IncludePrivate: true,
  687. GithubUser: "fakeUser",
  688. },
  689. description: "private user no githubtoken",
  690. expectedErrMsg: "user/organization private repos require env var GITHUB_TOKEN to be set",
  691. githubToken: false,
  692. },
  693. {
  694. testOpts: Options{
  695. IncludePrivate: true,
  696. GithubUser: "fakeUser",
  697. GithubOrg: "fakeOrg",
  698. },
  699. description: "double owner",
  700. expectedErrMsg: "github user and organization set",
  701. },
  702. {
  703. testOpts: Options{
  704. IncludePrivate: true,
  705. GithubOrg: "fakeOrg",
  706. OwnerPath: "/dev/null",
  707. },
  708. description: "local and remote target",
  709. expectedErrMsg: "github organization set and local owner path",
  710. },
  711. {
  712. testOpts: Options{
  713. IncludePrivate: true,
  714. GithubUser: "fakeUser",
  715. OwnerPath: "/dev/null",
  716. },
  717. description: "local and remote target",
  718. expectedErrMsg: "github user set and local owner path",
  719. },
  720. {
  721. testOpts: Options{
  722. GithubUser: "fakeUser",
  723. SingleSearch: "*/./....",
  724. },
  725. description: "single search invalid regex gaurd",
  726. expectedErrMsgFuzzy: "unable to compile regex: */./...., ",
  727. },
  728. {
  729. testOpts: Options{
  730. GithubUser: "fakeUser",
  731. SingleSearch: "mystring",
  732. },
  733. description: "single search regex gaurd",
  734. expectedErrMsg: "",
  735. },
  736. {
  737. testOpts: Options{
  738. GithubOrg: "fakeOrg",
  739. Entropy: 9,
  740. },
  741. description: "Invalid entropy level guard",
  742. expectedErrMsg: "The maximum level of entropy is 8",
  743. },
  744. }
  745. g := goblin.Goblin(t)
  746. for _, test := range tests {
  747. g.Describe("Test Option Gaurd", func() {
  748. g.It(test.description, func() {
  749. os.Clearenv()
  750. opts = test.testOpts
  751. if test.githubToken {
  752. os.Setenv("GITHUB_TOKEN", "fakeToken")
  753. }
  754. err := optsGuard()
  755. if err != nil {
  756. if test.expectedErrMsgFuzzy != "" {
  757. g.Assert(strings.Contains(err.Error(), test.expectedErrMsgFuzzy)).Equal(true)
  758. } else {
  759. g.Assert(err.Error()).Equal(test.expectedErrMsg)
  760. }
  761. } else {
  762. g.Assert("").Equal(test.expectedErrMsg)
  763. }
  764. })
  765. })
  766. }
  767. }
  768. func TestLoadToml(t *testing.T) {
  769. tmpDir, _ := ioutil.TempDir("", "gitleaksTestConfigDir")
  770. defer os.RemoveAll(tmpDir)
  771. err := ioutil.WriteFile(path.Join(tmpDir, "gitleaksConfig"), []byte(defaultConfig), 0644)
  772. if err != nil {
  773. panic(err)
  774. }
  775. configPath := path.Join(tmpDir, "gitleaksConfig")
  776. noConfigPath := path.Join(tmpDir, "gitleaksConfigNope")
  777. var tests = []struct {
  778. testOpts Options
  779. description string
  780. configPath string
  781. expectedErrMsg string
  782. singleSearch bool
  783. }{
  784. {
  785. testOpts: Options{
  786. ConfigPath: configPath,
  787. },
  788. description: "path to config",
  789. },
  790. {
  791. testOpts: Options{},
  792. description: "env var path to no config",
  793. singleSearch: true,
  794. },
  795. {
  796. testOpts: Options{
  797. ConfigPath: noConfigPath,
  798. },
  799. description: "no path to config",
  800. expectedErrMsg: fmt.Sprintf("no gitleaks config at %s", noConfigPath),
  801. },
  802. {
  803. testOpts: Options{},
  804. description: "env var path to config",
  805. configPath: configPath,
  806. expectedErrMsg: "",
  807. },
  808. {
  809. testOpts: Options{},
  810. description: "env var path to no config",
  811. configPath: noConfigPath,
  812. expectedErrMsg: fmt.Sprintf("problem loading config: open %s: no such file or directory", noConfigPath),
  813. },
  814. }
  815. g := goblin.Goblin(t)
  816. for _, test := range tests {
  817. g.Describe("TestLoadToml", func() {
  818. g.It(test.description, func() {
  819. opts = test.testOpts
  820. if test.singleSearch {
  821. singleSearchRegex = regexp.MustCompile("test")
  822. } else {
  823. singleSearchRegex = nil
  824. }
  825. if test.configPath != "" {
  826. os.Setenv("GITLEAKS_CONFIG", test.configPath)
  827. } else {
  828. os.Clearenv()
  829. }
  830. err := loadToml()
  831. if err != nil {
  832. g.Assert(err.Error()).Equal(test.expectedErrMsg)
  833. } else {
  834. g.Assert("").Equal(test.expectedErrMsg)
  835. }
  836. })
  837. })
  838. }
  839. }
  840. func BenchmarkAuditRepo1Proc(b *testing.B) {
  841. loadToml()
  842. opts.MaxGoRoutines = 1
  843. benchmarkRepo = getBenchmarkRepo()
  844. for n := 0; n < b.N; n++ {
  845. auditGitRepo(benchmarkRepo)
  846. }
  847. }
  848. func BenchmarkAuditRepo2Proc(b *testing.B) {
  849. loadToml()
  850. opts.MaxGoRoutines = 2
  851. benchmarkRepo = getBenchmarkRepo()
  852. for n := 0; n < b.N; n++ {
  853. auditGitRepo(benchmarkRepo)
  854. }
  855. }
  856. func BenchmarkAuditRepo4Proc(b *testing.B) {
  857. loadToml()
  858. opts.MaxGoRoutines = 4
  859. benchmarkRepo = getBenchmarkRepo()
  860. for n := 0; n < b.N; n++ {
  861. auditGitRepo(benchmarkRepo)
  862. }
  863. }
  864. func BenchmarkAuditRepo8Proc(b *testing.B) {
  865. loadToml()
  866. opts.MaxGoRoutines = 8
  867. benchmarkRepo = getBenchmarkRepo()
  868. for n := 0; n < b.N; n++ {
  869. auditGitRepo(benchmarkRepo)
  870. }
  871. }
  872. func BenchmarkAuditRepo10Proc(b *testing.B) {
  873. loadToml()
  874. opts.MaxGoRoutines = 10
  875. benchmarkRepo = getBenchmarkRepo()
  876. for n := 0; n < b.N; n++ {
  877. auditGitRepo(benchmarkRepo)
  878. }
  879. }
  880. func BenchmarkAuditRepo100Proc(b *testing.B) {
  881. loadToml()
  882. opts.MaxGoRoutines = 100
  883. benchmarkRepo = getBenchmarkRepo()
  884. for n := 0; n < b.N; n++ {
  885. auditGitRepo(benchmarkRepo)
  886. }
  887. }
  888. func BenchmarkAuditRepo1000Proc(b *testing.B) {
  889. loadToml()
  890. opts.MaxGoRoutines = 1000
  891. benchmarkRepo = getBenchmarkRepo()
  892. for n := 0; n < b.N; n++ {
  893. auditGitRepo(benchmarkRepo)
  894. }
  895. }
  896. func BenchmarkAuditLeakRepo1Proc(b *testing.B) {
  897. loadToml()
  898. opts.MaxGoRoutines = 1
  899. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  900. for n := 0; n < b.N; n++ {
  901. auditGitRepo(benchmarkRepo)
  902. }
  903. }
  904. func BenchmarkAuditLeakRepo2Proc(b *testing.B) {
  905. loadToml()
  906. opts.MaxGoRoutines = 2
  907. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  908. for n := 0; n < b.N; n++ {
  909. auditGitRepo(benchmarkRepo)
  910. }
  911. }
  912. func BenchmarkAuditLeakRepo4Proc(b *testing.B) {
  913. loadToml()
  914. opts.MaxGoRoutines = 4
  915. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  916. for n := 0; n < b.N; n++ {
  917. auditGitRepo(benchmarkRepo)
  918. }
  919. }
  920. func BenchmarkAuditLeakRepo8Proc(b *testing.B) {
  921. loadToml()
  922. opts.MaxGoRoutines = 8
  923. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  924. for n := 0; n < b.N; n++ {
  925. auditGitRepo(benchmarkRepo)
  926. }
  927. }
  928. func BenchmarkAuditLeakRepo10Proc(b *testing.B) {
  929. loadToml()
  930. opts.MaxGoRoutines = 10
  931. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  932. for n := 0; n < b.N; n++ {
  933. auditGitRepo(benchmarkRepo)
  934. }
  935. }
  936. func BenchmarkAuditLeakRepo100Proc(b *testing.B) {
  937. loadToml()
  938. opts.MaxGoRoutines = 100
  939. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  940. for n := 0; n < b.N; n++ {
  941. auditGitRepo(benchmarkRepo)
  942. }
  943. }
  944. func BenchmarkAuditLeakRepo1000Proc(b *testing.B) {
  945. loadToml()
  946. opts.MaxGoRoutines = 1000
  947. benchmarkLeaksRepo = getBenchmarkLeaksRepo()
  948. for n := 0; n < b.N; n++ {
  949. auditGitRepo(benchmarkRepo)
  950. }
  951. }