Skip to content

Commit

Permalink
Allow usage of wildcards in talismarc file (#196)
Browse files Browse the repository at this point in the history
* Check scan required based on wildcard in talismanrc
* Introduce a interfaces for utility and checksumcalculator
* Inject checksumCalculator to the checksum comparator
* Inject ChecksumCompare to Detectors
  • Loading branch information
dineshba committed Jun 8, 2020
1 parent d1d9fd3 commit b3c1f06
Show file tree
Hide file tree
Showing 21 changed files with 291 additions and 108 deletions.
18 changes: 12 additions & 6 deletions checksumcalculator/checksumcalculator.go
Expand Up @@ -9,18 +9,24 @@ import (
yaml "gopkg.in/yaml.v2"
)

type ChecksumCalculator struct {
type ChecksumCalculator interface {
SuggestTalismanRC(fileNamePatterns []string) string
CalculateCollectiveChecksumForPattern(fileNamePattern string) string
}

type DefaultChecksumCalculator struct {
gitAdditions []gitrepo.Addition
hasher utility.SHA256Hasher
}

//NewChecksumCalculator returns new instance of the CheckSumDetector
func NewChecksumCalculator(gitAdditions []gitrepo.Addition) *ChecksumCalculator {
cc := ChecksumCalculator{gitAdditions: gitAdditions}
func NewChecksumCalculator(hasher utility.SHA256Hasher, gitAdditions []gitrepo.Addition) ChecksumCalculator {
cc := DefaultChecksumCalculator{hasher: hasher, gitAdditions: gitAdditions}
return &cc
}

//SuggestTalismanRC returns the suggestion for .talismanrc format
func (cc *ChecksumCalculator) SuggestTalismanRC(fileNamePatterns []string) string {
func (cc *DefaultChecksumCalculator) SuggestTalismanRC(fileNamePatterns []string) string {
var fileIgnoreConfigs []talismanrc.FileIgnoreConfig
result := ""
for _, pattern := range fileNamePatterns {
Expand All @@ -39,7 +45,7 @@ func (cc *ChecksumCalculator) SuggestTalismanRC(fileNamePatterns []string) strin
return result
}

func (cc *ChecksumCalculator) CalculateCollectiveChecksumForPattern(fileNamePattern string) string {
func (cc *DefaultChecksumCalculator) CalculateCollectiveChecksumForPattern(fileNamePattern string) string {
var patternPaths []string
currentCollectiveChecksum := ""
for _, addition := range cc.gitAdditions {
Expand All @@ -50,7 +56,7 @@ func (cc *ChecksumCalculator) CalculateCollectiveChecksumForPattern(fileNamePatt
// Calculate current collective checksum
patternPaths = utility.UniqueItems(patternPaths)
if len(patternPaths) != 0 {
currentCollectiveChecksum = utility.CollectiveSHA256Hash(patternPaths)
currentCollectiveChecksum = cc.hasher.CollectiveSHA256Hash(patternPaths)
}
return currentCollectiveChecksum
}
7 changes: 4 additions & 3 deletions detector/base64_aggressive_detector_test.go
@@ -1,6 +1,7 @@
package detector

import (
"talisman/utility"
"testing"

"talisman/gitrepo"
Expand All @@ -18,7 +19,7 @@ func TestShouldFlagPotentialAWSAccessKeysInAggressiveMode(t *testing.T) {
filename := "filename"
additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)}

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

Expand All @@ -29,7 +30,7 @@ func TestShouldFlagPotentialAWSAccessKeysAtPropertyDefinitionInAggressiveMode(t
filename := "filename"
additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)}

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

Expand All @@ -40,7 +41,7 @@ func TestShouldNotFlagPotentialSecretsWithinSafeJavaCodeEvenInAggressiveMode(t *
filename := "filename"
additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)}

NewFileContentDetector().AggressiveMode().Test(additions, talismanRC, results)
NewFileContentDetector().AggressiveMode().Test(NewChecksumCompare(nil, utility.DefaultSHA256Hasher{}, talismanrc.NewTalismanRC(nil)), additions, talismanRC, results)
if results == nil {
additions = nil
}
Expand Down
17 changes: 9 additions & 8 deletions detector/checksum_compare.go
@@ -1,28 +1,29 @@
package detector

import (
"talisman/checksumcalculator"
"talisman/gitrepo"
"talisman/talismanrc"
"talisman/utility"
)

type ChecksumCompare struct {
additions []gitrepo.Addition
ignoreConfig *talismanrc.TalismanRC
calculator checksumcalculator.ChecksumCalculator
hasher utility.SHA256Hasher
talismanRC *talismanrc.TalismanRC
}

//NewChecksumCompare returns new instance of the ChecksumCompare
func NewChecksumCompare(gitAdditions []gitrepo.Addition, talismanRCConfig *talismanrc.TalismanRC) *ChecksumCompare {
cc := ChecksumCompare{additions: gitAdditions, ignoreConfig: talismanRCConfig}
return &cc
func NewChecksumCompare(calculator checksumcalculator.ChecksumCalculator, hasher utility.SHA256Hasher, talismanRCConfig *talismanrc.TalismanRC) ChecksumCompare {
return ChecksumCompare{calculator: calculator, hasher: hasher, talismanRC: talismanRCConfig}
}

func (cc *ChecksumCompare) IsScanNotRequired(addition gitrepo.Addition) bool {
currentCollectiveChecksum := utility.CollectiveSHA256Hash([]string{string(addition.Path)})
currentCollectiveChecksum := cc.hasher.CollectiveSHA256Hash([]string{string(addition.Path)})
declaredCheckSum := ""
for _, ignore := range cc.ignoreConfig.FileIgnoreConfig {
for _, ignore := range cc.talismanRC.FileIgnoreConfig {
if addition.Matches(ignore.FileName) {
currentCollectiveChecksum = utility.CollectiveSHA256Hash([]string{ignore.FileName})
currentCollectiveChecksum = cc.calculator.CalculateCollectiveChecksumForPattern(ignore.FileName)
declaredCheckSum = ignore.Checksum
}
}
Expand Down
56 changes: 44 additions & 12 deletions detector/checksum_compare_test.go
@@ -1,20 +1,52 @@
package detector

import (
"talisman/utility"
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"talisman/gitrepo"
mockchecksumcalculator "talisman/internal/mock/checksumcalculator"
mockutility "talisman/internal/mock/utility"
"talisman/talismanrc"
"testing"
)

func TestShouldReturnCorrectFileHash(t *testing.T) {
checksumSomeFile := utility.CollectiveSHA256Hash([]string{"some_file.pem"})
checksumTestSomeFile := utility.CollectiveSHA256Hash([]string{"test/some_file.pem"})
assert.Equal(t, checksumSomeFile, "87139cc4d975333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac", "Should be equal to some_file.pem hash value")
assert.Equal(t, checksumTestSomeFile, "25bd31a28bf9d4e06327f1c4a5cab2260574ae508803f66adcc393350e994866", "Should be equal to test/some_file.pem hash value")
}
func TestChecksumCompare_IsScanNotRequired(t *testing.T) {

t.Run("should return false if talismanrc is empty", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSHA256Hasher := mockutility.NewMockSHA256Hasher(ctrl)
ignoreConfig := talismanrc.NewTalismanRC(nil)
cc := NewChecksumCompare(nil, mockSHA256Hasher, ignoreConfig)
addition := gitrepo.Addition{Path: "some.txt"}
mockSHA256Hasher.EXPECT().CollectiveSHA256Hash([]string{string(addition.Path)}).Return("somesha")

required := cc.IsScanNotRequired(addition)

assert.False(t, required)
})

t.Run("should loop through talismanrc configs", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockSHA256Hasher := mockutility.NewMockSHA256Hasher(ctrl)
checksumCalculator := mockchecksumcalculator.NewMockChecksumCalculator(ctrl)
ignoreConfig := talismanrc.TalismanRC{
FileIgnoreConfig: []talismanrc.FileIgnoreConfig{
{
FileName: "some.txt",
Checksum: "sha1",
},
},
}
cc := NewChecksumCompare(checksumCalculator, mockSHA256Hasher, &ignoreConfig)
addition := gitrepo.Addition{Name: "some.txt",}
mockSHA256Hasher.EXPECT().CollectiveSHA256Hash([]string{string(addition.Path)}).Return("somesha")
checksumCalculator.EXPECT().CalculateCollectiveChecksumForPattern("some.txt").Return("sha1")

required := cc.IsScanNotRequired(addition)

assert.True(t, required)
})

func TestShouldReturnEmptyFileHashWhenNoPathsPassed(t *testing.T) {
checksum := utility.CollectiveSHA256Hash([]string{})
assert.Equal(t, checksum, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "Should be equal to empty hash value when no paths passed")
}
2 changes: 1 addition & 1 deletion detector/detection_results.go
Expand Up @@ -307,7 +307,7 @@ func (r *DetectionResults) suggestTalismanRC(fs afero.Fs, ignoreFile string, fil
var entriesToAdd []talismanrc.FileIgnoreConfig

for _, filePath := range filePaths {
currentChecksum := utility.CollectiveSHA256Hash([]string{filePath})
currentChecksum := utility.DefaultSHA256Hasher{}.CollectiveSHA256Hash([]string{filePath})
fileIgnoreConfig := talismanrc.FileIgnoreConfig{filePath, currentChecksum, []string{}}
entriesToAdd = append(entriesToAdd, fileIgnoreConfig)
}
Expand Down
15 changes: 12 additions & 3 deletions detector/detector.go
@@ -1,15 +1,18 @@
package detector

import (
"os"
"talisman/checksumcalculator"
"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(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults)
Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults)
}

//Chain represents a chain of Detectors.
Expand Down Expand Up @@ -42,8 +45,14 @@ func (dc *Chain) AddDetector(d Detector) *Chain {

//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(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
func (dc *Chain) Test(currentAdditions []gitrepo.Addition, talismanRC *talismanrc.TalismanRC, result *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)
for _, v := range dc.detectors {
v.Test(additions, ignoreConfig, result)
v.Test(cc, currentAdditions, talismanRC, result)
}
}
4 changes: 2 additions & 2 deletions detector/detector_test.go
Expand Up @@ -28,11 +28,11 @@ func TestValidationChainWithFailingValidationAlwaysFails(t *testing.T) {

type FailingDetection struct{}

func (v FailingDetection) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
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(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
func (p PassingDetection) Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
}
11 changes: 5 additions & 6 deletions detector/filecontent_detector.go
Expand Up @@ -72,7 +72,7 @@ type content struct {
results []string
}

func (fc *FileContentDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
func (fc *FileContentDetector) Test(comparator ChecksumCompare, currentAdditions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) {
contentTypes := []struct {
contentType
fn
Expand All @@ -90,18 +90,17 @@ func (fc *FileContentDetector) Test(additions []gitrepo.Addition, ignoreConfig *
fn: checkCreditCardNumber,
},
}
cc := NewChecksumCompare(additions, ignoreConfig)
re := regexp.MustCompile(`(?i)checksum[ \t]*:[ \t]*[0-9a-fA-F]+`)

contents := make(chan content, 512)
ignoredFilePaths := make(chan gitrepo.FilePath, len(additions))
ignoredFilePaths := make(chan gitrepo.FilePath, len(currentAdditions))

waitGroup := &sync.WaitGroup{}
waitGroup.Add(len(additions))
for _, addition := range additions {
waitGroup.Add(len(currentAdditions))
for _, addition := range currentAdditions {
go func(addition gitrepo.Addition) {
defer waitGroup.Done()
if ignoreConfig.Deny(addition, "filecontent") || cc.IsScanNotRequired(addition) {
if ignoreConfig.Deny(addition, "filecontent") || comparator.IsScanNotRequired(addition) {
ignoredFilePaths <- addition.Path
return
}
Expand Down

0 comments on commit b3c1f06

Please sign in to comment.