gitleaks_test.go 22 KB

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