Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix interactive file ignore addition #172

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ talisman_darwin_*
talisman_windows_*
vendor/
gitrepo/data/*
.talismanrc
detector/.talismanrc
.vscode/**
coverage.out
coverage.txt
7 changes: 7 additions & 0 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fileignoreconfig:
- filename: detector/detection_results_test.go
checksum: 69fed055782cddfe0f0d23ea440cef9f9dd0b9e8a3c8a73856741bb26257b223
ignore_detectors:
- filecontent
scopeconfig:
- scope: go
8 changes: 4 additions & 4 deletions checksumcalculator/checksumcalculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package checksumcalculator
import (
"fmt"
"os"
"talisman/detector"
"talisman/gitrepo"
"talisman/talismanrc"
"talisman/utility"

yaml "gopkg.in/yaml.v2"
Expand All @@ -27,18 +27,18 @@ func (cc *ChecksumCalculator) SuggestTalismanRC() string {
gitTrackedFilesAsAdditions := repo.TrackedFilesAsAdditions()
//Adding staged files for calculation
gitTrackedFilesAsAdditions = append(gitTrackedFilesAsAdditions, repo.StagedAdditions()...)
var fileIgnoreConfigs []detector.FileIgnoreConfig
var fileIgnoreConfigs []talismanrc.FileIgnoreConfig
result := ""
for _, pattern := range cc.fileNamePatterns {
collectiveChecksum := cc.calculateCollectiveChecksumForPattern(pattern, gitTrackedFilesAsAdditions)
if collectiveChecksum != "" {
fileIgnoreConfig := detector.FileIgnoreConfig{FileName: pattern, Checksum: collectiveChecksum, IgnoreDetectors: []string{}}
fileIgnoreConfig := talismanrc.FileIgnoreConfig{FileName: pattern, Checksum: collectiveChecksum, IgnoreDetectors: []string{}}
fileIgnoreConfigs = append(fileIgnoreConfigs, fileIgnoreConfig)
}
}
if len(fileIgnoreConfigs) != 0 {
result = result + fmt.Sprintf("\n\x1b[33m.talismanrc format for given file names / patterns\x1b[0m\n")
talismanRCIgnoreConfig := detector.TalismanRCIgnore{FileIgnoreConfig: fileIgnoreConfigs}
talismanRCIgnoreConfig := talismanrc.TalismanRCIgnore{FileIgnoreConfig: fileIgnoreConfigs}
m, _ := yaml.Marshal(&talismanRCIgnoreConfig)
result = result + string(m)
}
Expand Down
9 changes: 6 additions & 3 deletions detector/base64_aggressive_detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ import (
"testing"

"talisman/gitrepo"
"talisman/talismanrc"

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

var talismanRCIgnore = &talismanrc.TalismanRCIgnore{}

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

NewFileContentDetector().AggressiveMode().Test(additions, TalismanRCIgnore{}, results)
NewFileContentDetector().AggressiveMode().Test(additions, talismanRCIgnore, results)
assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts")
}

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

NewFileContentDetector().AggressiveMode().Test(additions, TalismanRCIgnore{}, results)
NewFileContentDetector().AggressiveMode().Test(additions, talismanRCIgnore, results)
assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts")
}

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

NewFileContentDetector().AggressiveMode().Test(additions, TalismanRCIgnore{}, results)
NewFileContentDetector().AggressiveMode().Test(additions, talismanRCIgnore, results)
if results == nil {
additions = nil
}
Expand Down
15 changes: 8 additions & 7 deletions detector/checksum_compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ package detector

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

type ChecksumCompare struct {
additions []gitrepo.Addition
ignoreConfig TalismanRCIgnore
ignoreConfig *talismanrc.TalismanRCIgnore
}

//NewChecksumCompare returns new instance of the ChecksumCompare
func NewChecksumCompare(gitAdditions []gitrepo.Addition, talismanRCIgnoreConfig TalismanRCIgnore) *ChecksumCompare {
func NewChecksumCompare(gitAdditions []gitrepo.Addition, talismanRCIgnoreConfig *talismanrc.TalismanRCIgnore) *ChecksumCompare {
cc := ChecksumCompare{additions: gitAdditions, ignoreConfig: talismanRCIgnoreConfig}
return &cc
}
Expand All @@ -30,17 +31,17 @@ func (cc *ChecksumCompare) IsScanNotRequired(addition gitrepo.Addition) bool {

}

//FilterIgnoresBasedOnChecksums filters the file ignores from the TalismanRCIgnore which doesn't have any checksum value or having mismatched checksum value from the .talsimanrc
func (cc *ChecksumCompare) FilterIgnoresBasedOnChecksums() TalismanRCIgnore {
finalIgnores := []FileIgnoreConfig{}
//FilterIgnoresBasedOnChecksums filters the file ignores from the talismanrc.TalismanRCIgnore which doesn't have any checksum value or having mismatched checksum value from the .talsimanrc
func (cc *ChecksumCompare) FilterIgnoresBasedOnChecksums() talismanrc.TalismanRCIgnore {
finalIgnores := []talismanrc.FileIgnoreConfig{}
for _, ignore := range cc.ignoreConfig.FileIgnoreConfig {
currentCollectiveChecksum := cc.calculateCollectiveChecksumForPattern(ignore.FileName, cc.additions)
// Compare with previous checksum from FileIgnoreConfig
// Compare with previous checksum from talismanrc.FileIgnoreConfig
if ignore.Checksum == currentCollectiveChecksum {
finalIgnores = append(finalIgnores, ignore)
}
}
rc := TalismanRCIgnore{}
rc := talismanrc.TalismanRCIgnore{}
rc.FileIgnoreConfig = finalIgnores
return rc
}
Expand Down
9 changes: 5 additions & 4 deletions detector/checksum_compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package detector

import (
"talisman/gitrepo"
"talisman/talismanrc"
"talisman/utility"
"testing"

Expand Down Expand Up @@ -36,7 +37,7 @@ fileignoreconfig:
`

func TestShouldConsiderBothFilesForDetection(t *testing.T) {
rc := NewTalismanRCIgnore([]byte(talismanRCWithInCorrectChecksum))
rc := talismanrc.NewTalismanRCIgnore([]byte(talismanRCWithInCorrectChecksum))
addition1 := gitrepo.NewAddition("some_file.pem", make([]byte, 0))
addition2 := gitrepo.NewAddition("test/some_file.pem", make([]byte, 0))
cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc)
Expand All @@ -49,7 +50,7 @@ func TestShouldConsiderBothFilesForDetection(t *testing.T) {
func TestShouldNotConsiderBothFilesForDetection(t *testing.T) {
addition1 := gitrepo.NewAddition("some_file.pem", make([]byte, 0))
addition2 := gitrepo.NewAddition("test/some_file.pem", make([]byte, 0))
rc := NewTalismanRCIgnore([]byte(talismanRCWithCorrectChecksum))
rc := talismanrc.NewTalismanRCIgnore([]byte(talismanRCWithCorrectChecksum))
cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc)

filteredRC := cc.FilterIgnoresBasedOnChecksums()
Expand All @@ -60,7 +61,7 @@ func TestShouldNotConsiderBothFilesForDetection(t *testing.T) {
func TestShouldConsiderOneFileForDetection(t *testing.T) {
addition1 := gitrepo.NewAddition("some_file.pem", make([]byte, 0))
addition2 := gitrepo.NewAddition("test/some1_file.pem", make([]byte, 0))
rc := NewTalismanRCIgnore([]byte(talismanRCWithOneCorrectChecksum))
rc := talismanrc.NewTalismanRCIgnore([]byte(talismanRCWithOneCorrectChecksum))
cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc)

filteredRC := cc.FilterIgnoresBasedOnChecksums()
Expand All @@ -71,7 +72,7 @@ func TestShouldConsiderOneFileForDetection(t *testing.T) {
func TestShouldConsiderBothFilesForDetectionIfTalismanRCIsEmpty(t *testing.T) {
addition1 := gitrepo.NewAddition("some_file.pem", make([]byte, 0))
addition2 := gitrepo.NewAddition("test/some_file.pem", make([]byte, 0))
rc := NewTalismanRCIgnore([]byte{})
rc := talismanrc.NewTalismanRCIgnore([]byte{})
cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc)

filteredRC := cc.FilterIgnoresBasedOnChecksums()
Expand Down
46 changes: 12 additions & 34 deletions detector/detection_results.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ package detector

import (
"fmt"
"github.com/spf13/afero"
"gopkg.in/yaml.v2"
"log"
"os"
"strings"
"talisman/gitrepo"
"talisman/prompt"
"talisman/talismanrc"
"talisman/utility"

"github.com/spf13/afero"
"gopkg.in/yaml.v2"

"github.com/olekukonko/tablewriter"
)

Expand Down Expand Up @@ -302,26 +304,26 @@ func (r *DetectionResults) Report(fs afero.Fs, ignoreFile string, promptContext
}

func (r *DetectionResults) suggestTalismanRC(fs afero.Fs, ignoreFile string, filePaths []string, promptContext prompt.PromptContext) {
var entriesToAdd []FileIgnoreConfig
var entriesToAdd []talismanrc.FileIgnoreConfig

for _, filePath := range filePaths {
currentChecksum := utility.CollectiveSHA256Hash([]string{filePath})
fileIgnoreConfig := FileIgnoreConfig{filePath, currentChecksum, []string{}}
fileIgnoreConfig := talismanrc.FileIgnoreConfig{filePath, currentChecksum, []string{}}
entriesToAdd = append(entriesToAdd, fileIgnoreConfig)
}

if promptContext.Interactive {
confirmedEntries := getUserConfirmation(entriesToAdd, promptContext)
addToTalismanIgnoreFile(confirmedEntries, fs, ignoreFile)
talismanrc.Get().AddFileIgnores(confirmedEntries)
} else {
printTalismanIgnoreSuggestion(entriesToAdd)
return
}

}

func getUserConfirmation(configs []FileIgnoreConfig, promptContext prompt.PromptContext) []FileIgnoreConfig {
confirmed := []FileIgnoreConfig{}
func getUserConfirmation(configs []talismanrc.FileIgnoreConfig, promptContext prompt.PromptContext) []talismanrc.FileIgnoreConfig {
confirmed := []talismanrc.FileIgnoreConfig{}
for _, config := range configs {
if confirm(config, promptContext) {
confirmed = append(confirmed, config)
Expand All @@ -330,8 +332,8 @@ func getUserConfirmation(configs []FileIgnoreConfig, promptContext prompt.Prompt
return confirmed
}

func printTalismanIgnoreSuggestion(entriesToAdd []FileIgnoreConfig) {
talismanRcIgnoreConfig := TalismanRCIgnore{FileIgnoreConfig: entriesToAdd}
func printTalismanIgnoreSuggestion(entriesToAdd []talismanrc.FileIgnoreConfig) {
talismanRcIgnoreConfig := talismanrc.TalismanRCIgnore{FileIgnoreConfig: entriesToAdd}
ignoreEntries, _ := yaml.Marshal(&talismanRcIgnoreConfig)
suggestString := fmt.Sprintf("\n\x1b[33mIf you are absolutely sure that you want to ignore the " +
"above files from talisman detectors, consider pasting the following format in .talismanrc file" +
Expand All @@ -340,31 +342,7 @@ func printTalismanIgnoreSuggestion(entriesToAdd []FileIgnoreConfig) {
fmt.Println(string(ignoreEntries))
}

func addToTalismanIgnoreFile(entriesToAdd []FileIgnoreConfig, fs afero.Fs, ignoreFile string) {

if len(entriesToAdd) > 0 {
talismanRcIgnoreConfig := TalismanRCIgnore{FileIgnoreConfig: entriesToAdd}
ignoreEntries, _ := yaml.Marshal(&talismanRcIgnoreConfig)
file, err := fs.OpenFile(ignoreFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Printf("error opening %s: %s", ignoreFile, err)
}
defer func() {
err := file.Close()
if err != nil {
log.Printf("error closing %s: %s", ignoreFile, err)
}

}()

_, err = file.WriteString(string(ignoreEntries))
if err != nil {
log.Printf("error writing to %s: %s", ignoreFile, err)
}
}
}

func confirm(config FileIgnoreConfig, promptContext prompt.PromptContext) bool {
func confirm(config talismanrc.FileIgnoreConfig, promptContext prompt.PromptContext) bool {
bytes, err := yaml.Marshal(&config)
if err != nil {
log.Printf("error marshalling file ignore config: %s", err)
Expand Down
48 changes: 34 additions & 14 deletions detector/detection_results_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package detector

import (
"github.com/golang/mock/gomock"
"github.com/spf13/afero"
"strings"
mock "talisman/internal/mock/prompt"
"talisman/prompt"
"talisman/talismanrc"
"testing"

"github.com/golang/mock/gomock"
"github.com/spf13/afero"

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

Expand Down Expand Up @@ -78,6 +80,9 @@ func TestTalismanRCSuggestionWhenThereAreFailures(t *testing.T) {
assert.NoError(t, err)
ignoreFile := file.Name()

talismanrc.SetFs(fs)
talismanrc.SetRcFilename(ignoreFile)

existingContent := `fileignoreconfig:
- filename: existing.pem
checksum: 123444ddssa75333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac
Expand All @@ -100,6 +105,7 @@ scopeconfig: []
assert.Equal(t, existingContent, string(bytesFromFile))
})

_ = afero.WriteFile(fs, ignoreFile, []byte(existingContent), 0666)
t.Run("when user declines, entry should not be added to talismanrc", func(t *testing.T) {
promptContext := prompt.NewPromptContext(true, prompter)
prompter.EXPECT().Confirm("Do you want to add this entry in talismanrc ?").Return(false)
Expand All @@ -112,6 +118,7 @@ scopeconfig: []
assert.Equal(t, existingContent, string(bytesFromFile))
})

_ = afero.WriteFile(fs, ignoreFile, []byte(existingContent), 0666)
t.Run("when interactive flag is set to false, it should not ask user", func(t *testing.T) {
promptContext := prompt.NewPromptContext(false, prompter)
prompter.EXPECT().Confirm(gomock.Any()).Return(false).Times(0)
Expand All @@ -124,18 +131,14 @@ scopeconfig: []
assert.Equal(t, existingContent, string(bytesFromFile))
})

_ = afero.WriteFile(fs, ignoreFile, []byte(existingContent), 0666)
t.Run("when user confirms, entry should be appended to given ignore file", func(t *testing.T) {
promptContext := prompt.NewPromptContext(true, prompter)
prompter.EXPECT().Confirm("Do you want to add this entry in talismanrc ?").Return(true)

results.Fail("some_file.pem", "filecontent", "Bomb", []string{})

expectedFileContent := `fileignoreconfig:
- filename: existing.pem
checksum: 123444ddssa75333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac
ignore_detectors: []
scopeconfig: []
fileignoreconfig:
- filename: some_file.pem
checksum: 87139cc4d975333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac
ignore_detectors: []
Expand All @@ -148,24 +151,42 @@ scopeconfig: []
assert.Equal(t, expectedFileContent, string(bytesFromFile))
})

t.Run("when user confirms for multiple entries, they should be appended to given ignore file", func(t *testing.T) {
// Clearing file contents from previous tests
err := afero.WriteFile(fs, ignoreFile, []byte{}, 0666)
_ = afero.WriteFile(fs, ignoreFile, []byte(existingContent), 0666)
t.Run("when user confirms, entry for existing file should updated", func(t *testing.T) {
promptContext := prompt.NewPromptContext(true, prompter)
prompter.EXPECT().Confirm("Do you want to add this entry in talismanrc ?").Return(true)
results := NewDetectionResults()
results.Fail("existing.pem", "filecontent", "This will bomb!", []string{})

expectedFileContent := `fileignoreconfig:
- filename: existing.pem
checksum: 5bc0b0692a316bb2919263addaef0ffba3a21b9e1cca62a1028390e97e861e4e
ignore_detectors: []
scopeconfig: []

`
results.Report(fs, ignoreFile, promptContext)
bytesFromFile, err := afero.ReadFile(fs, ignoreFile)

assert.NoError(t, err)
assert.Equal(t, expectedFileContent, string(bytesFromFile))
})

_ = afero.WriteFile(fs, ignoreFile, []byte(existingContent), 0666)
t.Run("when user confirms for multiple entries, they should be appended to given ignore file", func(t *testing.T) {
promptContext := prompt.NewPromptContext(true, prompter)
prompter.EXPECT().Confirm("Do you want to add this entry in talismanrc ?").Return(true).Times(2)

results.Fail("some_file.pem", "filecontent", "Bomb", []string{})
results.Fail("another.pem", "filecontent", "password", []string{})

expectedFileContent := `fileignoreconfig:
- filename: some_file.pem
checksum: 87139cc4d975333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac
ignore_detectors: []
- filename: another.pem
checksum: 117e23557c02cbd472854ebce4933d6daec1fd207971286f6ffc9f1774c1a83b
ignore_detectors: []
- filename: some_file.pem
checksum: 87139cc4d975333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac
ignore_detectors: []
scopeconfig: []
`
results.Report(fs, ignoreFile, promptContext)
Expand All @@ -175,7 +196,6 @@ scopeconfig: []
assert.Equal(t, expectedFileContent, string(bytesFromFile))
})


err = fs.Remove(ignoreFile)
assert.NoError(t, err)
}
Loading