Skip to content

Commit

Permalink
Grouped detectors using package (#197)
Browse files Browse the repository at this point in the history
Signed-off-by: Dinesh <[email protected]>
  • Loading branch information
dineshba authored Jun 12, 2020
1 parent 83c2c93 commit 01d957c
Show file tree
Hide file tree
Showing 32 changed files with 181 additions and 152 deletions.
29 changes: 14 additions & 15 deletions detector/detector.go → detector/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,55 @@ package detector
import (
"os"
"talisman/checksumcalculator"
"talisman/detector/detector"
"talisman/detector/filecontent"
"talisman/detector/filename"
"talisman/detector/helpers"
"talisman/detector/pattern"
"talisman/gitrepo"
"talisman/talismanrc"
"talisman/utility"
)

//Detector represents a single kind of test to be performed against a set of Additions
//Detectors are expected to honor the ignores that are passed in and log them in the results
//Detectors are expected to signal any errors to the results
type Detector interface {
Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults)
}

//Chain represents a chain of Detectors.
//It is itself a detector.
type Chain struct {
detectors []Detector
detectors []detector.Detector
}

//NewChain returns an empty DetectorChain
//It is itself a detector, but it tests nothing.
func NewChain() *Chain {
result := Chain{make([]Detector, 0)}
result := Chain{make([]detector.Detector, 0)}
return &result
}

//DefaultChain returns a DetectorChain with pre-configured detectors
func DefaultChain(tRC *talismanrc.TalismanRC) *Chain {
result := NewChain()
result.AddDetector(DefaultFileNameDetector())
result.AddDetector(NewFileContentDetector())
result.AddDetector(NewPatternDetector(tRC.CustomPatterns))
result.AddDetector(filename.DefaultFileNameDetector())
result.AddDetector(filecontent.NewFileContentDetector())
result.AddDetector(pattern.NewPatternDetector(tRC.CustomPatterns))
return result
}

//AddDetector adds the detector that is passed in to the chain
func (dc *Chain) AddDetector(d Detector) *Chain {
func (dc *Chain) AddDetector(d detector.Detector) *Chain {
dc.detectors = append(dc.detectors, d)
return dc
}

//Test validates the additions against each detector in the chain.
//The results are passed in from detector to detector and thus collect all errors from all detectors
func (dc *Chain) Test(currentAdditions []gitrepo.Addition, talismanRC *talismanrc.TalismanRC, result *DetectionResults) {
func (dc *Chain) Test(currentAdditions []gitrepo.Addition, talismanRC *talismanrc.TalismanRC, result *helpers.DetectionResults) {
wd, _ := os.Getwd()
repo := gitrepo.RepoLocatedAt(wd)
allAdditions := repo.TrackedFilesAsAdditions()
hasher := utility.DefaultSHA256Hasher{}
calculator := checksumcalculator.NewChecksumCalculator(hasher, append(allAdditions, currentAdditions...))
cc := NewChecksumCompare(calculator, hasher, talismanRC)
cc := helpers.NewChecksumCompare(calculator, hasher, talismanRC)
for _, v := range dc.detectors {
v.Test(cc, currentAdditions, talismanRC, result)
}
}

33 changes: 16 additions & 17 deletions detector/detector_test.go → detector/chain_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
package detector

import (
"testing"

"github.com/stretchr/testify/assert"
"talisman/detector/helpers"
"talisman/gitrepo"
"talisman/talismanrc"

"github.com/stretchr/testify/assert"
"testing"
)

type FailingDetection struct{}

func (v FailingDetection) Test(comparator helpers.ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *helpers.DetectionResults) {
result.Fail("some_file", "filecontent", "FAILED BY DESIGN", []string{})
}

type PassingDetection struct{}

func (p PassingDetection) Test(comparator helpers.ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *helpers.DetectionResults) {
}

func TestEmptyValidationChainPassesAllValidations(t *testing.T) {
v := NewChain()
results := NewDetectionResults()
results := helpers.NewDetectionResults()
v.Test(nil, &talismanrc.TalismanRC{}, results)
assert.False(t, results.HasFailures(), "Empty validation chain is expected to always pass")
}
Expand All @@ -20,19 +30,8 @@ func TestValidationChainWithFailingValidationAlwaysFails(t *testing.T) {
v := NewChain()
v.AddDetector(PassingDetection{})
v.AddDetector(FailingDetection{})
results := NewDetectionResults()
results := helpers.NewDetectionResults()
v.Test(nil, &talismanrc.TalismanRC{}, results)

assert.False(t, results.Successful(), "Expected validation chain with a failure to fail.")
}

type FailingDetection struct{}

func (v FailingDetection) Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
result.Fail("some_file", "filecontent", "FAILED BY DESIGN", []string{})
}

type PassingDetection struct{}

func (p PassingDetection) Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
}
14 changes: 14 additions & 0 deletions detector/detector/detector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package detector

import (
"talisman/detector/helpers"
"talisman/gitrepo"
"talisman/talismanrc"
)

//Detector represents a single kind of test to be performed against a set of Additions
//Detectors are expected to honor the ignores that are passed in and log them in the results
//Detectors are expected to signal any errors to the results
type Detector interface {
Test(comparator helpers.ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *helpers.DetectionResults)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package detector
package filecontent

import (
"encoding/base64"
Expand Down Expand Up @@ -41,4 +41,4 @@ func checkEachSubString(subStrings []string) string {
}
}
return ""
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package detector
package filecontent

import (
"talisman/detector/helpers"
"talisman/utility"
"testing"

Expand All @@ -10,38 +11,36 @@ import (
"github.com/stretchr/testify/assert"
)

var talismanRC = &talismanrc.TalismanRC{}

func TestShouldFlagPotentialAWSAccessKeysInAggressiveMode(t *testing.T) {
const awsAccessKeyIDExample string = "AKIAIOSFODNN7EXAMPLE\n"
results := NewDetectionResults()
results := helpers.NewDetectionResults()
content := []byte(awsAccessKeyIDExample)
filename := "filename"
additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)}

NewFileContentDetector().AggressiveMode().Test(NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
NewFileContentDetector().AggressiveMode().Test(helpers.NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts")
}

func TestShouldFlagPotentialAWSAccessKeysAtPropertyDefinitionInAggressiveMode(t *testing.T) {
const awsAccessKeyIDExample string = "accessKey=AKIAIOSFODNN7EXAMPLE"
results := NewDetectionResults()
results := helpers.NewDetectionResults()
content := []byte(awsAccessKeyIDExample)
filename := "filename"
additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)}

NewFileContentDetector().AggressiveMode().Test(NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
NewFileContentDetector().AggressiveMode().Test(helpers.NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts")
}

func TestShouldNotFlagPotentialSecretsWithinSafeJavaCodeEvenInAggressiveMode(t *testing.T) {
const awsAccessKeyIDExample string = "public class HelloWorld {\r\n\r\n public static void main(String[] args) {\r\n // Prints \"Hello, World\" to the terminal window.\r\n System.out.println(\"Hello, World\");\r\n }\r\n\r\n}"
results := NewDetectionResults()
results := helpers.NewDetectionResults()
content := []byte(awsAccessKeyIDExample)
filename := "filename"
additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)}

NewFileContentDetector().AggressiveMode().Test(NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
NewFileContentDetector().AggressiveMode().Test(helpers.NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
if results == nil {
additions = nil
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package detector
package filecontent

const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
const BASE64_ENTROPY_THRESHOLD = 4.5
const MIN_BASE64_SECRET_LENGTH = 20

type Base64Detector struct {
base64Map map[string]bool
aggressiveDetector *Base64AggressiveDetector
entropy *Entropy
wordCheck *WordCheck
base64Map map[string]bool
AggressiveDetector *Base64AggressiveDetector
entropy *Entropy
wordCheck *WordCheck
}

func NewBase64Detector() *Base64Detector {
bd := Base64Detector{}
bd.initBase64Map()
bd.aggressiveDetector = nil
bd.AggressiveDetector = nil
bd.entropy = &Entropy{}
return &bd
}
Expand All @@ -26,16 +26,16 @@ func (bd *Base64Detector) initBase64Map() {
}
}

func (bd *Base64Detector) checkBase64Encoding(word string) string {
func (bd *Base64Detector) CheckBase64Encoding(word string) string {
entropyCandidates := bd.entropy.GetEntropyCandidatesWithinWord(word, MIN_BASE64_SECRET_LENGTH, bd.base64Map)
for _, candidate := range entropyCandidates {
entropy := bd.entropy.GetShannonEntropy(candidate, BASE64_CHARS)
if entropy > BASE64_ENTROPY_THRESHOLD && !bd.wordCheck.containsWordsOnly(candidate) {
return word
}
}
if bd.aggressiveDetector != nil {
return bd.aggressiveDetector.Test(word)
if bd.AggressiveDetector != nil {
return bd.AggressiveDetector.Test(word)
}
return ""
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package detector
package filecontent

import (
"testing"
Expand All @@ -11,7 +11,7 @@ func TestBase64DetectorShouldNotDetectSafeText(t *testing.T) {
bd := Base64Detector{}
bd.initBase64Map()

res := bd.checkBase64Encoding(s)
res := bd.CheckBase64Encoding(s)
assert.Equal(t, "", res)
}

Expand All @@ -20,7 +20,7 @@ func TestBase64DetectorShouldDetectBase64Text(t *testing.T) {
bd := Base64Detector{}
bd.initBase64Map()

res := bd.checkBase64Encoding(s)
res := bd.CheckBase64Encoding(s)
assert.Equal(t, s, res)
}

Expand All @@ -29,6 +29,6 @@ func TestBase64DetectorShouldNotDetectLongMethodNamesEvenWithHighEntropy(t *test
bd := Base64Detector{}
bd.initBase64Map()

res := bd.checkBase64Encoding(s)
res := bd.CheckBase64Encoding(s)
assert.Equal(t, "", res)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package detector
package filecontent

import "regexp"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package detector
package filecontent

import (
"testing"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package detector
package filecontent

import (
"fmt"
"regexp"
"strings"
"sync"
"talisman/detector/helpers"
"talisman/gitrepo"
"talisman/talismanrc"

Expand All @@ -28,7 +29,7 @@ func NewFileContentDetector() *FileContentDetector {
}

func (fc *FileContentDetector) AggressiveMode() *FileContentDetector {
fc.base64Detector.aggressiveDetector = &Base64AggressiveDetector{}
fc.base64Detector.AggressiveDetector = &Base64AggressiveDetector{}
return fc
}

Expand Down Expand Up @@ -72,7 +73,7 @@ type content struct {
results []string
}

func (fc *FileContentDetector) Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
func (fc *FileContentDetector) Test(comparator helpers.ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *helpers.DetectionResults) {
contentTypes := []struct {
contentType
fn
Expand Down Expand Up @@ -144,14 +145,14 @@ func (fc *FileContentDetector) Test(comparator ChecksumCompare, currentAdditions
}
}

func processIgnoredFilepath(path gitrepo.FilePath, result *DetectionResults) {
func processIgnoredFilepath(path gitrepo.FilePath, result *helpers.DetectionResults) {
log.WithFields(log.Fields{
"filePath": path,
}).Info("Ignoring addition as it was specified to be ignored.")
result.Ignore(path, "filecontent")
}

func processContent(c content, result *DetectionResults) {
func processContent(c content, result *helpers.DetectionResults) {
for _, res := range c.results {
if res != "" {
log.WithFields(log.Fields{
Expand Down Expand Up @@ -203,13 +204,13 @@ func (fc *FileContentDetector) checkEachWord(line string, getResult fn) []string
}

func checkBase64(fc *FileContentDetector, word string) string {
return fc.base64Detector.checkBase64Encoding(word)
return fc.base64Detector.CheckBase64Encoding(word)
}

func checkCreditCardNumber(fc *FileContentDetector, word string) string {
return fc.creditCardDetector.checkCreditCardNumber(word)
}

func checkHex(fc *FileContentDetector, word string) string {
return fc.hexDetector.checkHexEncoding(word)
return fc.hexDetector.CheckHexEncoding(word)
}
Loading

0 comments on commit 01d957c

Please sign in to comment.