gitleaks_test.go 22 KB

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