diff --git a/.talismanrc b/.talismanrc index e6dc75af..e08132c0 100644 --- a/.talismanrc +++ b/.talismanrc @@ -3,5 +3,8 @@ fileignoreconfig: checksum: 69fed055782cddfe0f0d23ea440cef9f9dd0b9e8a3c8a73856741bb26257b223 ignore_detectors: - filecontent +- filename: detector/match_pattern_test.go + checksum: d68aa0e06355e3b848941727d1fcb32cf47e3d615f9921f0db39855325010446 + ignore_detectors: [] scopeconfig: - scope: go diff --git a/README.md b/README.md index d3073947..7c4b8b01 100644 --- a/README.md +++ b/README.md @@ -263,7 +263,7 @@ For example, if your `init-env.sh` filename triggers a warning, you can only dis this warning while still being alerted if other things go wrong (e.g. file content): -```bash +```yaml fileignoreconfig: - filename: init-env.sh checksum: cf97abd34cebe895417eb4d97fbd7374aa138dcb65b1fe7f6b6cc1238aaf4d48 @@ -295,7 +295,7 @@ If any of the files are modified, talisman will scan the files again, unless you You can choose to ignore files by specifying the language scope for your project in your talismanrc. -``` +```yaml scopeconfig: - scope: go - scope: node @@ -307,6 +307,16 @@ You can specify multiple scopes. Currently .talismanrc only supports scopeconfig support for go and node. Other scopes will be added shortly. +### Custom search patterns + +You can specify custom regex patterns to look for in the current repository + +```yaml +custom_patterns: +- pattern1 +- pattern2 +``` +
**Note**: The use of .talismanignore has been deprecated. File .talismanrc replaces it because: @@ -319,9 +329,10 @@ Currently .talismanrc only supports scopeconfig support for go and node. Other s If you execute `talisman` on the command line, you will be able to view all the parameter options you can pass ``` - -c, --checksum string checksum calculator calculates checksum and suggests .talsimarc format + -c, --checksum string checksum calculator calculates checksum and suggests .talismanrc format -d, --debug enable debug mode (warning: very verbose) -g, --githook string either pre-push or pre-commit (default "pre-push") + -i, --interactive interactively update talismanrc (only makes sense with -g/--githook) -p, --pattern string pattern (glob-like) of files to scan (ignores githooks) -r, --reportdirectory string directory where the scan reports will be stored -s, --scan scanner scans the git commit history for potential secrets diff --git a/checksumcalculator/checksumcalculator.go b/checksumcalculator/checksumcalculator.go index 80b59606..7d0b1e6d 100644 --- a/checksumcalculator/checksumcalculator.go +++ b/checksumcalculator/checksumcalculator.go @@ -38,8 +38,8 @@ func (cc *ChecksumCalculator) SuggestTalismanRC() string { } if len(fileIgnoreConfigs) != 0 { result = result + fmt.Sprintf("\n\x1b[33m.talismanrc format for given file names / patterns\x1b[0m\n") - talismanRCIgnoreConfig := talismanrc.TalismanRCIgnore{FileIgnoreConfig: fileIgnoreConfigs} - m, _ := yaml.Marshal(&talismanRCIgnoreConfig) + talismanRCConfig := talismanrc.TalismanRC{FileIgnoreConfig: fileIgnoreConfigs} + m, _ := yaml.Marshal(&talismanRCConfig) result = result + string(m) } return result diff --git a/detector/base64_aggressive_detector_test.go b/detector/base64_aggressive_detector_test.go index 3b9c0a16..7326bb1e 100644 --- a/detector/base64_aggressive_detector_test.go +++ b/detector/base64_aggressive_detector_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" ) -var talismanRCIgnore = &talismanrc.TalismanRCIgnore{} +var talismanRC = &talismanrc.TalismanRC{} func TestShouldFlagPotentialAWSAccessKeysInAggressiveMode(t *testing.T) { const awsAccessKeyIDExample string = "AKIAIOSFODNN7EXAMPLE\n" @@ -18,7 +18,7 @@ func TestShouldFlagPotentialAWSAccessKeysInAggressiveMode(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().AggressiveMode().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().AggressiveMode().Test(additions, talismanRC, results) assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -29,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, talismanRC, results) assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -40,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, talismanRC, results) if results == nil { additions = nil } diff --git a/detector/checksum_compare.go b/detector/checksum_compare.go index 89ddae67..5ca763a7 100644 --- a/detector/checksum_compare.go +++ b/detector/checksum_compare.go @@ -8,12 +8,12 @@ import ( type ChecksumCompare struct { additions []gitrepo.Addition - ignoreConfig *talismanrc.TalismanRCIgnore + ignoreConfig *talismanrc.TalismanRC } //NewChecksumCompare returns new instance of the ChecksumCompare -func NewChecksumCompare(gitAdditions []gitrepo.Addition, talismanRCIgnoreConfig *talismanrc.TalismanRCIgnore) *ChecksumCompare { - cc := ChecksumCompare{additions: gitAdditions, ignoreConfig: talismanRCIgnoreConfig} +func NewChecksumCompare(gitAdditions []gitrepo.Addition, talismanRCConfig *talismanrc.TalismanRC) *ChecksumCompare { + cc := ChecksumCompare{additions: gitAdditions, ignoreConfig: talismanRCConfig} return &cc } @@ -31,8 +31,8 @@ func (cc *ChecksumCompare) IsScanNotRequired(addition gitrepo.Addition) bool { } -//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 { +//FilterIgnoresBasedOnChecksums filters the file ignores from the talismanrc.TalismanRC which doesn't have any checksum value or having mismatched checksum value from the .talsimanrc +func (cc *ChecksumCompare) FilterIgnoresBasedOnChecksums() talismanrc.TalismanRC { finalIgnores := []talismanrc.FileIgnoreConfig{} for _, ignore := range cc.ignoreConfig.FileIgnoreConfig { currentCollectiveChecksum := cc.calculateCollectiveChecksumForPattern(ignore.FileName, cc.additions) @@ -41,7 +41,7 @@ func (cc *ChecksumCompare) FilterIgnoresBasedOnChecksums() talismanrc.TalismanRC finalIgnores = append(finalIgnores, ignore) } } - rc := talismanrc.TalismanRCIgnore{} + rc := talismanrc.TalismanRC{} rc.FileIgnoreConfig = finalIgnores return rc } diff --git a/detector/checksum_compare_test.go b/detector/checksum_compare_test.go index 05614090..5cb39349 100644 --- a/detector/checksum_compare_test.go +++ b/detector/checksum_compare_test.go @@ -37,7 +37,7 @@ fileignoreconfig: ` func TestShouldConsiderBothFilesForDetection(t *testing.T) { - rc := talismanrc.NewTalismanRCIgnore([]byte(talismanRCWithInCorrectChecksum)) + rc := talismanrc.NewTalismanRC([]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) @@ -50,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 := talismanrc.NewTalismanRCIgnore([]byte(talismanRCWithCorrectChecksum)) + rc := talismanrc.NewTalismanRC([]byte(talismanRCWithCorrectChecksum)) cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc) filteredRC := cc.FilterIgnoresBasedOnChecksums() @@ -61,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 := talismanrc.NewTalismanRCIgnore([]byte(talismanRCWithOneCorrectChecksum)) + rc := talismanrc.NewTalismanRC([]byte(talismanRCWithOneCorrectChecksum)) cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc) filteredRC := cc.FilterIgnoresBasedOnChecksums() @@ -72,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 := talismanrc.NewTalismanRCIgnore([]byte{}) + rc := talismanrc.NewTalismanRC([]byte{}) cc := NewChecksumCompare([]gitrepo.Addition{addition1, addition2}, rc) filteredRC := cc.FilterIgnoresBasedOnChecksums() diff --git a/detector/detection_results.go b/detector/detection_results.go index 2a7ab0a0..59155e42 100644 --- a/detector/detection_results.go +++ b/detector/detection_results.go @@ -333,8 +333,8 @@ func getUserConfirmation(configs []talismanrc.FileIgnoreConfig, promptContext pr } func printTalismanIgnoreSuggestion(entriesToAdd []talismanrc.FileIgnoreConfig) { - talismanRcIgnoreConfig := talismanrc.TalismanRCIgnore{FileIgnoreConfig: entriesToAdd} - ignoreEntries, _ := yaml.Marshal(&talismanRcIgnoreConfig) + talismanRCConfig := talismanrc.TalismanRC{FileIgnoreConfig: entriesToAdd} + ignoreEntries, _ := yaml.Marshal(&talismanRCConfig) 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" + " in the project root\x1b[0m\n") diff --git a/detector/detection_results_test.go b/detector/detection_results_test.go index cee37c7e..c6e3f84d 100644 --- a/detector/detection_results_test.go +++ b/detector/detection_results_test.go @@ -86,8 +86,6 @@ func TestTalismanRCSuggestionWhenThereAreFailures(t *testing.T) { existingContent := `fileignoreconfig: - filename: existing.pem checksum: 123444ddssa75333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac - ignore_detectors: [] -scopeconfig: [] ` err = afero.WriteFile(fs, ignoreFile, []byte(existingContent), 0666) assert.NoError(t, err) @@ -141,8 +139,6 @@ scopeconfig: [] expectedFileContent := `fileignoreconfig: - filename: some_file.pem checksum: 87139cc4d975333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac - ignore_detectors: [] -scopeconfig: [] ` results.Report(fs, ignoreFile, promptContext) bytesFromFile, err := afero.ReadFile(fs, ignoreFile) @@ -161,8 +157,6 @@ scopeconfig: [] expectedFileContent := `fileignoreconfig: - filename: existing.pem checksum: 5bc0b0692a316bb2919263addaef0ffba3a21b9e1cca62a1028390e97e861e4e - ignore_detectors: [] -scopeconfig: [] ` results.Report(fs, ignoreFile, promptContext) @@ -183,11 +177,8 @@ scopeconfig: [] expectedFileContent := `fileignoreconfig: - filename: another.pem checksum: 117e23557c02cbd472854ebce4933d6daec1fd207971286f6ffc9f1774c1a83b - ignore_detectors: [] - filename: some_file.pem checksum: 87139cc4d975333b25b6275f97680604add51b84eb8f4a3b9dcbbc652e6f27ac - ignore_detectors: [] -scopeconfig: [] ` results.Report(fs, ignoreFile, promptContext) bytesFromFile, err := afero.ReadFile(fs, ignoreFile) diff --git a/detector/detector.go b/detector/detector.go index cd5ce618..adcba98a 100644 --- a/detector/detector.go +++ b/detector/detector.go @@ -10,7 +10,7 @@ import ( //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.TalismanRCIgnore, result *DetectionResults) + Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) } //Chain represents a chain of Detectors. @@ -27,11 +27,11 @@ func NewChain() *Chain { } //DefaultChain returns a DetectorChain with pre-configured detectors -func DefaultChain() *Chain { +func DefaultChain(tRC *talismanrc.TalismanRC) *Chain { result := NewChain() result.AddDetector(DefaultFileNameDetector()) result.AddDetector(NewFileContentDetector()) - result.AddDetector(NewPatternDetector()) + result.AddDetector(NewPatternDetector(tRC.CustomPatterns)) return result } @@ -43,7 +43,7 @@ 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.TalismanRCIgnore, result *DetectionResults) { +func (dc *Chain) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) { wd, _ := os.Getwd() repo := gitrepo.RepoLocatedAt(wd) gitTrackedFilesAsAdditions := repo.TrackedFilesAsAdditions() diff --git a/detector/detector_test.go b/detector/detector_test.go index 095a6ef0..b1f1ccc3 100644 --- a/detector/detector_test.go +++ b/detector/detector_test.go @@ -12,7 +12,7 @@ import ( func TestEmptyValidationChainPassesAllValidations(t *testing.T) { v := NewChain() results := NewDetectionResults() - v.Test(nil, &talismanrc.TalismanRCIgnore{}, results) + v.Test(nil, &talismanrc.TalismanRC{}, results) assert.False(t, results.HasFailures(), "Empty validation chain is expected to always pass") } @@ -21,18 +21,18 @@ func TestValidationChainWithFailingValidationAlwaysFails(t *testing.T) { v.AddDetector(PassingDetection{}) v.AddDetector(FailingDetection{}) results := NewDetectionResults() - v.Test(nil, &talismanrc.TalismanRCIgnore{}, results) + 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(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRCIgnore, result *DetectionResults) { +func (v FailingDetection) Test(additions []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.TalismanRCIgnore, result *DetectionResults) { +func (p PassingDetection) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) { } diff --git a/detector/filecontent_detector.go b/detector/filecontent_detector.go index de345fa1..b02df3c7 100644 --- a/detector/filecontent_detector.go +++ b/detector/filecontent_detector.go @@ -72,7 +72,7 @@ type content struct { results []string } -func (fc *FileContentDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRCIgnore, result *DetectionResults) { +func (fc *FileContentDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) { contentTypes := []struct { contentType fn diff --git a/detector/filecontent_detector_test.go b/detector/filecontent_detector_test.go index 3b3d9555..9ebfdb2f 100644 --- a/detector/filecontent_detector_test.go +++ b/detector/filecontent_detector_test.go @@ -21,7 +21,7 @@ func TestShouldNotFlagSafeText(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().Test(additions, &talismanrc.TalismanRCIgnore{}, results) + NewFileContentDetector().Test(additions, &talismanrc.TalismanRC{}, results) assert.False(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -31,7 +31,7 @@ func TestShouldIgnoreFileIfNeeded(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().Test(additions, talismanrc.NewTalismanRCIgnore([]byte(talismanRCContents)), results) + NewFileContentDetector().Test(additions, talismanrc.NewTalismanRC([]byte(talismanRCContents)), results) assert.True(t, results.Successful(), "Expected file %s to be ignored by pattern", filename) } @@ -45,7 +45,7 @@ func TestShouldNotFlag4CharSafeText(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) assert.False(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -56,7 +56,7 @@ func TestShouldNotFlagLowEntropyBase64Text(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) assert.False(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -68,7 +68,7 @@ func TestShouldFlagPotentialAWSSecretKeys(t *testing.T) { additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := fmt.Sprintf("Expected file to not to contain base64 encoded texts such as: %s", awsSecretAccessKey) assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") assert.Equal(t, expectedMessage, getFailureMessages(results, filePath)[0]) @@ -83,7 +83,7 @@ func TestShouldFlagPotentialSecretWithoutTrimmingWhenLengthLessThan50Characters( additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := fmt.Sprintf("Expected file to not to contain base64 encoded texts such as: %s", secret) assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") assert.Equal(t, expectedMessage, getFailureMessages(results, filePath)[0]) @@ -98,7 +98,7 @@ func TestShouldFlagPotentialJWT(t *testing.T) { additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := fmt.Sprintf("Expected file to not to contain base64 encoded texts such as: %s", jwt[:47]+"...") assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") assert.Equal(t, expectedMessage, getFailureMessages(results, filePath)[0]) @@ -113,7 +113,7 @@ func TestShouldFlagPotentialSecretsWithinJavaCode(t *testing.T) { additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := "Expected file to not to contain base64 encoded texts such as: accessKey=\"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPL..." assert.True(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") assert.Equal(t, expectedMessage, getFailureMessages(results, filePath)[0]) @@ -127,7 +127,7 @@ func TestShouldNotFlagPotentialSecretsWithinSafeJavaCode(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) assert.False(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -138,7 +138,7 @@ func TestShouldNotFlagPotentialSecretsWithinSafeLongMethodName(t *testing.T) { filename := "filename" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) assert.False(t, results.HasFailures(), "Expected file to not to contain base64 encoded texts") } @@ -150,7 +150,7 @@ func TestShouldFlagPotentialSecretsEncodedInHex(t *testing.T) { additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := "Expected file to not to contain hex encoded texts such as: " + hex assert.Equal(t, expectedMessage, getFailureMessages(results, filePath)[0]) assert.Len(t, results.Results, 1) @@ -166,7 +166,7 @@ func TestResultsShouldContainHexTextsIfHexAndBase64ExistInFile(t *testing.T) { additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := "Expected file to not to contain hex encoded texts such as: " + hex messageReceived := strings.Join(getFailureMessages(results, filePath), " ") assert.Regexp(t, expectedMessage, messageReceived, "Should contain hex detection message") @@ -183,7 +183,7 @@ func TestResultsShouldContainBase64TextsIfHexAndBase64ExistInFile(t *testing.T) additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := "Expected file to not to contain base64 encoded texts such as: " + base64 messageReceived := strings.Join(getFailureMessages(results, filePath), " ") assert.Regexp(t, expectedMessage, messageReceived, "Should contain base64 detection message") @@ -198,7 +198,7 @@ func TestResultsShouldContainCreditCardNumberIfCreditCardNumberExistInFile(t *te additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} filePath := additions[0].Path - NewFileContentDetector().Test(additions, talismanRCIgnore, results) + NewFileContentDetector().Test(additions, talismanRC, results) expectedMessage := "Expected file to not to contain credit card numbers such as: " + creditCardNumber assert.Equal(t, expectedMessage, getFailureMessages(results, filePath)[0]) assert.Len(t, results.Results, 1) diff --git a/detector/filename_detector.go b/detector/filename_detector.go index d51cd052..0831c30d 100644 --- a/detector/filename_detector.go +++ b/detector/filename_detector.go @@ -79,7 +79,7 @@ func NewFileNameDetector(patterns []*regexp.Regexp) Detector { } //Test tests the fileNames of the Additions to ensure that they don't look suspicious -func (fd FileNameDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRCIgnore, result *DetectionResults) { +func (fd FileNameDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) { cc := NewChecksumCompare(additions, ignoreConfig) for _, addition := range additions { if ignoreConfig.Deny(addition, "filename") || cc.IsScanNotRequired(addition) { diff --git a/detector/filename_detector_test.go b/detector/filename_detector_test.go index 2f8eb2ad..255766f3 100644 --- a/detector/filename_detector_test.go +++ b/detector/filename_detector_test.go @@ -148,24 +148,24 @@ func shouldNotFailWithDefaultDetectorAndIgnores(fileName, ignore string, t *test fileIgnoreConfig.FileName = ignore fileIgnoreConfig.IgnoreDetectors = make([]string, 1) fileIgnoreConfig.IgnoreDetectors[0] = "filename" - talismanRCIgnore := &talismanrc.TalismanRCIgnore{} - talismanRCIgnore.FileIgnoreConfig = make([]talismanrc.FileIgnoreConfig, 1) - talismanRCIgnore.FileIgnoreConfig[0] = fileIgnoreConfig + talismanRC := &talismanrc.TalismanRC{} + talismanRC.FileIgnoreConfig = make([]talismanrc.FileIgnoreConfig, 1) + talismanRC.FileIgnoreConfig[0] = fileIgnoreConfig - DefaultFileNameDetector().Test(additionsNamed(fileName), talismanRCIgnore, results) + DefaultFileNameDetector().Test(additionsNamed(fileName), talismanRC, results) assert.True(t, results.Successful(), "Expected file %s to be ignored by pattern", fileName, ignore) } func shouldFailWithSpecificPattern(fileName, pattern string, t *testing.T) { results := NewDetectionResults() pt := regexp.MustCompile(pattern) - NewFileNameDetector([]*regexp.Regexp{pt}).Test(additionsNamed(fileName), talismanRCIgnore, results) + NewFileNameDetector([]*regexp.Regexp{pt}).Test(additionsNamed(fileName), talismanRC, results) assert.True(t, results.HasFailures(), "Expected file %s to fail the check against the %s pattern", fileName, pattern) } func shouldFailWithDefaultDetector(fileName, pattern string, t *testing.T) { results := NewDetectionResults() - DefaultFileNameDetector().Test(additionsNamed(fileName), talismanRCIgnore, results) + DefaultFileNameDetector().Test(additionsNamed(fileName), talismanRC, results) assert.True(t, results.HasFailures(), "Expected file %s to fail the check against default detector. Missing pattern %s?", fileName, pattern) } diff --git a/detector/filesize_detector.go b/detector/filesize_detector.go index d73ff7e8..e697f8c0 100644 --- a/detector/filesize_detector.go +++ b/detector/filesize_detector.go @@ -21,7 +21,7 @@ func NewFileSizeDetector(size int) Detector { return FileSizeDetector{size} } -func (fd FileSizeDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRCIgnore, result *DetectionResults) { +func (fd FileSizeDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) { cc := NewChecksumCompare(additions, ignoreConfig) for _, addition := range additions { if ignoreConfig.Deny(addition, "filesize") || cc.IsScanNotRequired(addition) { diff --git a/detector/filesize_detector_test.go b/detector/filesize_detector_test.go index 5b5177dd..317735e1 100644 --- a/detector/filesize_detector_test.go +++ b/detector/filesize_detector_test.go @@ -13,7 +13,7 @@ func TestShouldFlagLargeFiles(t *testing.T) { results := NewDetectionResults() content := []byte("more than one byte") additions := []gitrepo.Addition{gitrepo.NewAddition("filename", content)} - NewFileSizeDetector(2).Test(additions, talismanRCIgnore, results) + NewFileSizeDetector(2).Test(additions, talismanRC, results) assert.True(t, results.HasFailures(), "Expected file to fail the check against file size detector.") } @@ -21,7 +21,7 @@ func TestShouldNotFlagSmallFiles(t *testing.T) { results := NewDetectionResults() content := []byte("m") additions := []gitrepo.Addition{gitrepo.NewAddition("filename", content)} - NewFileSizeDetector(2).Test(additions, talismanRCIgnore, results) + NewFileSizeDetector(2).Test(additions, talismanRC, results) assert.False(t, results.HasFailures(), "Expected file to not to fail the check against file size detector.") } @@ -34,11 +34,11 @@ func TestShouldNotFlagIgnoredLargeFiles(t *testing.T) { fileIgnoreConfig.FileName = filename fileIgnoreConfig.IgnoreDetectors = make([]string, 1) fileIgnoreConfig.IgnoreDetectors[0] = "filesize" - talismanRCIgnore := talismanRCIgnore - talismanRCIgnore.FileIgnoreConfig = make([]talismanrc.FileIgnoreConfig, 1) - talismanRCIgnore.FileIgnoreConfig[0] = fileIgnoreConfig + talismanRC := talismanRC + talismanRC.FileIgnoreConfig = make([]talismanrc.FileIgnoreConfig, 1) + talismanRC.FileIgnoreConfig[0] = fileIgnoreConfig additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewFileSizeDetector(2).Test(additions, talismanRCIgnore, results) + NewFileSizeDetector(2).Test(additions, talismanRC, results) assert.True(t, results.Successful(), "expected file %s to be ignored by file size detector", filename) } diff --git a/detector/match_pattern.go b/detector/match_pattern.go index ff4d9d34..f1912422 100644 --- a/detector/match_pattern.go +++ b/detector/match_pattern.go @@ -1,17 +1,23 @@ package detector -import "regexp" +import ( + "fmt" + "github.com/Sirupsen/logrus" + "regexp" + "talisman/talismanrc" +) type PatternMatcher struct { regexes []*regexp.Regexp } -func (detector PatternMatcher) check(content string) []string { +func (pm *PatternMatcher) check(content string) []string { var detected []string - for _, regex := range detector.regexes { - matches := regex.FindStringSubmatch(content) + for _, regex := range pm.regexes { + logrus.Debugf("checking for pattern %v", regex) + matches := regex.FindAllString(content, -1) if matches != nil { - detected = append(detected, matches[1:]...) + detected = append(detected, matches...) } } if detected != nil { @@ -20,6 +26,16 @@ func (detector PatternMatcher) check(content string) []string { return []string{""} } -func NewSecretsPatternDetector(patterns []*regexp.Regexp) *PatternMatcher { +func (pm *PatternMatcher) add(ps talismanrc.PatternString) { + re, err := regexp.Compile(fmt.Sprintf("(%s)", string(ps))) + if err != nil { + logrus.Warnf("ignoring invalid pattern '%s'", ps) + return + } + logrus.Infof("added custom pattern '%s'", ps) + pm.regexes = append(pm.regexes, re) +} + +func NewPatternMatcher(patterns []*regexp.Regexp) *PatternMatcher { return &PatternMatcher{patterns} } diff --git a/detector/match_pattern_test.go b/detector/match_pattern_test.go index fdf71caf..ab40cb8e 100644 --- a/detector/match_pattern_test.go +++ b/detector/match_pattern_test.go @@ -3,19 +3,35 @@ package detector import ( "github.com/stretchr/testify/assert" "regexp" + "talisman/talismanrc" "testing" ) var ( - testRegexpPassword = regexp.MustCompile(`(?i)(['"_]?password['"]? *[:=][^,;]{8,})`) - testRegexpPw = regexp.MustCompile(`(?i)(['"_]?pw['"]? *[:=][^,;]{8,})`) + testRegexpPasswordPattern = `(?i)(['"_]?password['"]? *[:=][^,;]{8,})` + testRegexpPassword = regexp.MustCompile(testRegexpPasswordPattern) + testRegexpPwPattern = `(?i)(['"_]?pw['"]? *[:=][^,;]{8,})` + testRegexpPw = regexp.MustCompile(testRegexpPwPattern) ) func TestShouldReturnEmptyStringWhenDoesNotMatchAnyRegex(t *testing.T) { - assert.Equal(t, "", NewSecretsPatternDetector([]*regexp.Regexp{testRegexpPassword}).check("safeString")[0]) + assert.Equal(t, "", NewPatternMatcher([]*regexp.Regexp{testRegexpPassword}).check("safeString")[0]) } func TestShouldReturnStringWhenMatchedPasswordPattern(t *testing.T) { - assert.Equal(t, []string{"password\" : 123456789"}, NewSecretsPatternDetector([]*regexp.Regexp{testRegexpPassword}).check("password\" : 123456789")) - assert.Equal(t, []string{"pw\" : 123456789"}, NewSecretsPatternDetector([]*regexp.Regexp{testRegexpPw}).check("pw\" : 123456789")) + assert.Equal(t, []string{"password\" : 123456789"}, NewPatternMatcher([]*regexp.Regexp{testRegexpPassword}).check("password\" : 123456789")) + assert.Equal(t, []string{"pw\" : 123456789"}, NewPatternMatcher([]*regexp.Regexp{testRegexpPw}).check("pw\" : 123456789")) } + +func TestShouldAddGoodPatternToMatcher(t *testing.T) { + pm := NewPatternMatcher([]*regexp.Regexp{}) + pm.add(talismanrc.PatternString(testRegexpPwPattern)) + assert.Equal(t, []string{"pw\" : 123456789"}, NewPatternMatcher([]*regexp.Regexp{testRegexpPw}).check("pw\" : 123456789")) +} + + +func TestShouldNotAddBadPatternToMatcher(t *testing.T) { + pm := NewPatternMatcher([]*regexp.Regexp{}) + pm.add(`*a(crappy|regex`) + assert.Equal(t, 0, len(pm.regexes)) +} \ No newline at end of file diff --git a/detector/pattern_detector.go b/detector/pattern_detector.go index abf61580..62752a9b 100644 --- a/detector/pattern_detector.go +++ b/detector/pattern_detector.go @@ -41,7 +41,7 @@ type match struct { } //Test tests the contents of the Additions to ensure that they don't look suspicious -func (detector PatternDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRCIgnore, result *DetectionResults) { +func (detector PatternDetector) Test(additions []gitrepo.Addition, ignoreConfig *talismanrc.TalismanRC, result *DetectionResults) { cc := NewChecksumCompare(additions, ignoreConfig) matches := make(chan match, 512) ignoredFilePaths := make(chan gitrepo.FilePath, 512) @@ -109,6 +109,10 @@ func (detector PatternDetector) processMatch(match match, result *DetectionResul } //NewPatternDetector returns a PatternDetector that tests Additions against the pre-configured patterns -func NewPatternDetector() *PatternDetector { - return &PatternDetector{NewSecretsPatternDetector(detectorPatterns)} +func NewPatternDetector(custom []talismanrc.PatternString) *PatternDetector { + matcher := NewPatternMatcher(detectorPatterns) + for _, pattern := range custom { + matcher.add(pattern) + } + return &PatternDetector{matcher} } diff --git a/detector/pattern_detector_test.go b/detector/pattern_detector_test.go index 631726b8..0e54cbf2 100644 --- a/detector/pattern_detector_test.go +++ b/detector/pattern_detector_test.go @@ -8,6 +8,10 @@ import ( "github.com/stretchr/testify/assert" ) +var ( + customPatterns []talismanrc.PatternString +) + func TestShouldDetectPasswordPatterns(t *testing.T) { filename := "secret.txt" @@ -28,16 +32,16 @@ func TestShouldIgnorePasswordPatterns(t *testing.T) { filename := "secret.txt" additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} fileIgnoreConfig := talismanrc.FileIgnoreConfig{filename, "833b6c24c8c2c5c7e1663226dc401b29c005492dc76a1150fc0e0f07f29d4cc3", []string{"filecontent"}} - ignores := &talismanrc.TalismanRCIgnore{FileIgnoreConfig: []talismanrc.FileIgnoreConfig{fileIgnoreConfig}} + ignores := &talismanrc.TalismanRC{FileIgnoreConfig: []talismanrc.FileIgnoreConfig{fileIgnoreConfig}} - NewPatternDetector().Test(additions, ignores, results) + NewPatternDetector(customPatterns).Test(additions, ignores, results) assert.True(t, results.Successful(), "Expected file %s to be ignored by pattern", filename) } func shouldPassDetectionOfSecretPattern(filename string, content []byte, t *testing.T) { results := NewDetectionResults() additions := []gitrepo.Addition{gitrepo.NewAddition(filename, content)} - NewPatternDetector().Test(additions, talismanRCIgnore, results) + NewPatternDetector(customPatterns).Test(additions, talismanRC, results) expected := "Potential secret pattern : " + string(content) assert.Equal(t, expected, getFailureMessage(results, additions)) assert.Len(t, results.Results, 1) diff --git a/runner.go b/runner.go index 48860936..fe7d80c2 100644 --- a/runner.go +++ b/runner.go @@ -50,8 +50,8 @@ func (r *Runner) Scan(reportDirectory string) int { fmt.Printf("\n\n") utility.CreateArt("Running Scan..") additions := scanner.GetAdditions() - ignores := &talismanrc.TalismanRCIgnore{} - detector.DefaultChain().Test(additions, ignores, r.results) + ignores := &talismanrc.TalismanRC{} + detector.DefaultChain(ignores).Test(additions, ignores, r.results) reportsPath, err := report.GenerateReport(r.results, reportDirectory) if err != nil { log.Printf("error while generating report: %v", err) @@ -78,7 +78,7 @@ func (r *Runner) doRun() { rcConfigIgnores := talismanrc.Get() scopeMap := getScopeConfig() additionsToScan := rcConfigIgnores.IgnoreAdditionsByScope(r.additions, scopeMap) - detector.DefaultChain().Test(additionsToScan, rcConfigIgnores, r.results) + detector.DefaultChain(rcConfigIgnores).Test(additionsToScan, rcConfigIgnores, r.results) } func getScopeConfig() map[string][]string { diff --git a/talisman.go b/talisman.go index dca79e84..076ba5c2 100644 --- a/talisman.go +++ b/talisman.go @@ -58,10 +58,10 @@ func main() { flag.StringVarP(&pattern, "pattern", "p", "", "pattern (glob-like) of files to scan (ignores githooks)") flag.StringVarP(&githook, "githook", "g", PrePush, "either pre-push or pre-commit") flag.BoolVarP(&scan, "scan", "s", false, "scanner scans the git commit history for potential secrets") - flag.StringVarP(&checksum, "checksum", "c", "", "checksum calculator calculates checksum and suggests .talsimarc format") + flag.StringVarP(&checksum, "checksum", "c", "", "checksum calculator calculates checksum and suggests .talismanrc format") flag.StringVarP(&reportdirectory, "reportdirectory", "r", "", "directory where the scan reports will be stored") flag.BoolVarP(&scanWithHtml, "scanWithHtml", "w", false, "generate html report (**Make sure you have installed talisman_html_report to use this, as mentioned in Readme**)") - flag.BoolVarP(&interactive, "interactive", "i", false, "to be interactive or not") + flag.BoolVarP(&interactive, "interactive", "i", false, "interactively update talismanrc (only makes sense with -g/--githook)") flag.Parse() diff --git a/talismanrc/talismanrc.go b/talismanrc/talismanrc.go index ebfea0f6..1b27c863 100644 --- a/talismanrc/talismanrc.go +++ b/talismanrc/talismanrc.go @@ -1,66 +1,46 @@ package talismanrc import ( + logr "github.com/Sirupsen/logrus" + "github.com/spf13/afero" + "gopkg.in/yaml.v2" "log" "os" "reflect" "regexp" "sort" - "strings" - - logr "github.com/Sirupsen/logrus" - "github.com/spf13/afero" - "gopkg.in/yaml.v2" "talisman/gitrepo" ) const ( - //LinePattern represents a line in the ignorefile with an optional comment - LinePattern string = `^([^#]+)?\s*(#(.*))?$` - - //IgnoreDetectorCommentPattern represents a special comment that ignores only certain detectors - IgnoreDetectorCommentPattern string = `^ignore:([^\s]+).*$` - //DefaultRCFileName represents the name of default file in which all the ignore patterns are configured in new version DefaultRCFileName string = ".talismanrc" ) var ( - commentPattern = regexp.MustCompile(LinePattern) - ignorePattern = regexp.MustCompile(IgnoreDetectorCommentPattern) emptyStringPattern = regexp.MustCompile(`^\s*$`) fs = afero.NewOsFs() currentRCFileName = DefaultRCFileName - cachedConfig TalismanRCIgnore ) -//Ignores represents a set of patterns that have been configured to be ignored by the Detectors. -//Detectors are expected to honor these ignores. -type Ignores struct { - patterns []Ignore -} - -//Ignore represents a single pattern and its comment -type Ignore struct { - pattern string - comment string - ignoredDetectors []string -} type FileIgnoreConfig struct { FileName string `yaml:"filename"` Checksum string `yaml:"checksum"` - IgnoreDetectors []string `yaml:"ignore_detectors"` + IgnoreDetectors []string `yaml:"ignore_detectors,omitempty"` } type ScopeConfig struct { ScopeName string `yaml:"scope"` } -type TalismanRCIgnore struct { - FileIgnoreConfig []FileIgnoreConfig `yaml:"fileignoreconfig"` - ScopeConfig []ScopeConfig `yaml:"scopeconfig"` +type PatternString string + +type TalismanRC struct { + FileIgnoreConfig []FileIgnoreConfig `yaml:"fileignoreconfig,omitempty"` + ScopeConfig []ScopeConfig `yaml:"scopeconfig,omitempty"` + CustomPatterns []PatternString `yaml:"custom_patterns,omitempty"` } func SetFs(_fs afero.Fs) { @@ -71,20 +51,20 @@ func SetRcFilename(rcFileName string) { currentRCFileName = rcFileName } -func Get() *TalismanRCIgnore { +func Get() *TalismanRC { return ReadConfigFromRCFile(readRepoFile()) } -func (ignore *TalismanRCIgnore) IsEmpty() bool { - return reflect.DeepEqual(TalismanRCIgnore{}, ignore) +func (tRC *TalismanRC) IsEmpty() bool { + return reflect.DeepEqual(TalismanRC{}, tRC) } -func ReadConfigFromRCFile(repoFileRead func(string) ([]byte, error)) *TalismanRCIgnore { +func ReadConfigFromRCFile(repoFileRead func(string) ([]byte, error)) *TalismanRC { fileContents, error := repoFileRead(currentRCFileName) if error != nil { panic(error) } - return NewTalismanRCIgnore(fileContents) + return NewTalismanRC(fileContents) } func readRepoFile() func(string) ([]byte, error) { @@ -93,29 +73,15 @@ func readRepoFile() func(string) ([]byte, error) { return repo.ReadRepoFileOrNothing } -func NewTalismanRCIgnore(fileContents []byte) *TalismanRCIgnore { - talismanRCIgnore := TalismanRCIgnore{} - err := yaml.Unmarshal([]byte(fileContents), &talismanRCIgnore) +func NewTalismanRC(fileContents []byte) *TalismanRC { + talismanRC := TalismanRC{} + err := yaml.Unmarshal(fileContents, &talismanRC) if err != nil { log.Println("Unable to parse .talismanrc") log.Printf("error: %v", err) - return &talismanRCIgnore - } - return &talismanRCIgnore -} - -func NewIgnore(pattern string, comment string) Ignore { - var ignoredDetectors []string - match := ignorePattern.FindStringSubmatch(comment) - if match != nil { - ignoredDetectors = strings.Split(match[1], ",") - } - - return Ignore{ - pattern: pattern, - comment: comment, - ignoredDetectors: ignoredDetectors, + return &talismanRC } + return &talismanRC } func (i FileIgnoreConfig) isEffective(detectorName string) bool { @@ -123,34 +89,20 @@ func (i FileIgnoreConfig) isEffective(detectorName string) bool { contains(i.IgnoreDetectors, detectorName) } -//NewIgnores builds a new Ignores with the patterns specified in the ignoreSpecs -//Empty lines and comments are ignored. -func NewIgnores(lines ...string) Ignores { - var groups []string - var ignores []Ignore - for _, line := range lines { - groups = commentPattern.FindStringSubmatch(line) - if len(groups) == 4 { - ignores = append(ignores, NewIgnore(strings.TrimSpace(groups[1]), strings.TrimSpace(groups[3]))) - } - } - return Ignores{ignores} -} - //AcceptsAll returns true if there are no rules specified -func (i *TalismanRCIgnore) AcceptsAll() bool { - return len(i.effectiveRules("any-detector")) == 0 +func (tRC *TalismanRC) AcceptsAll() bool { + return len(tRC.effectiveRules("any-detector")) == 0 } //Accept answers true if the Addition.Path is configured to be checked by the detectors -func (i *TalismanRCIgnore) Accept(addition gitrepo.Addition, detectorName string) bool { - return !i.Deny(addition, detectorName) +func (tRC *TalismanRC) Accept(addition gitrepo.Addition, detectorName string) bool { + return !tRC.Deny(addition, detectorName) } -func (rcConfigIgnores *TalismanRCIgnore) IgnoreAdditionsByScope(additions []gitrepo.Addition, scopeMap map[string][]string) []gitrepo.Addition { +func (tRC *TalismanRC) IgnoreAdditionsByScope(additions []gitrepo.Addition, scopeMap map[string][]string) []gitrepo.Addition { var applicableScopeFileNames []string - if rcConfigIgnores.ScopeConfig != nil { - for _, scope := range rcConfigIgnores.ScopeConfig { + if tRC.ScopeConfig != nil { + for _, scope := range tRC.ScopeConfig { if len(scopeMap[scope.ScopeName]) > 0 { applicableScopeFileNames = append(applicableScopeFileNames, scopeMap[scope.ScopeName]...) } @@ -171,12 +123,12 @@ func (rcConfigIgnores *TalismanRCIgnore) IgnoreAdditionsByScope(additions []gitr return result } -func (rcConfigIgnores *TalismanRCIgnore) AddFileIgnores(entriesToAdd []FileIgnoreConfig) { +func (tRC *TalismanRC) AddFileIgnores(entriesToAdd []FileIgnoreConfig) { if len(entriesToAdd) > 0 { logr.Debugf("Adding entries: %v", entriesToAdd) - talismanRcIgnoreConfig := Get() - talismanRcIgnoreConfig.FileIgnoreConfig = combineFileIgnores(talismanRcIgnoreConfig.FileIgnoreConfig, entriesToAdd) - ignoreEntries, _ := yaml.Marshal(&talismanRcIgnoreConfig) + talismanRCConfig := Get() + talismanRCConfig.FileIgnoreConfig = combineFileIgnores(talismanRCConfig.FileIgnoreConfig, entriesToAdd) + ignoreEntries, _ := yaml.Marshal(&talismanRCConfig) file, err := fs.OpenFile(currentRCFileName, os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Printf("error opening %s: %s", currentRCFileName, err) @@ -207,13 +159,13 @@ func combineFileIgnores(exsiting, incoming []FileIgnoreConfig) []FileIgnoreConfi result := make([]FileIgnoreConfig, len(existingMap)) resultKeys := make([]string, len(existingMap)) index := 0 - //sort keys in alpabetical order + //sort keys in alphabetical order for k, _ := range existingMap { resultKeys[index] = k index++ } sort.Strings(resultKeys) - //add result entries based on sortedkeys + //add result entries based on sorted keys index = 0 for _, k := range resultKeys { result[index] = existingMap[k] @@ -223,17 +175,17 @@ func combineFileIgnores(exsiting, incoming []FileIgnoreConfig) []FileIgnoreConfi } //Deny answers true if the Addition.Path is configured to be ignored and not checked by the detectors -func (i *TalismanRCIgnore) Deny(addition gitrepo.Addition, detectorName string) bool { +func (tRC *TalismanRC) Deny(addition gitrepo.Addition, detectorName string) bool { result := false - for _, pattern := range i.effectiveRules(detectorName) { + for _, pattern := range tRC.effectiveRules(detectorName) { result = result || addition.Matches(pattern) } return result } -func (i *TalismanRCIgnore) effectiveRules(detectorName string) []string { +func (tRC *TalismanRC) effectiveRules(detectorName string) []string { var result []string - for _, ignore := range i.FileIgnoreConfig { + for _, ignore := range tRC.FileIgnoreConfig { if ignore.isEffective(detectorName) { result = append(result, ignore.FileName) } diff --git a/talismanrc/talismanrc_test.go b/talismanrc/talismanrc_test.go index fa0ca712..14ca17c8 100644 --- a/talismanrc/talismanrc_test.go +++ b/talismanrc/talismanrc_test.go @@ -10,34 +10,16 @@ import ( func TestShouldIgnoreEmptyLinesInTheFile(t *testing.T) { for _, s := range []string{"", " ", " "} { - assert.True(t, NewTalismanRCIgnore([]byte(s)).AcceptsAll(), "Expected '%s' to result in no ignore patterns.", s) + assert.True(t, NewTalismanRC([]byte(s)).AcceptsAll(), "Expected '%s' to result in no ignore patterns.", s) } } func TestShouldIgnoreUnformattedFiles(t *testing.T) { for _, s := range []string{"#", "#monkey", "# this monkey likes bananas "} { - assert.True(t, NewTalismanRCIgnore([]byte(s)).AcceptsAll(), "Expected commented line '%s' to result in no ignore patterns", s) + assert.True(t, NewTalismanRC([]byte(s)).AcceptsAll(), "Expected commented line '%s' to result in no ignore patterns", s) } } -func TestShouldParseIgnoreLinesProperly(t *testing.T) { - assert.Equal(t, NewIgnores("foo* # comment"), SingleIgnore("foo*", "comment")) - assert.Equal(t, NewIgnores("foo* # comment with multiple words"), SingleIgnore("foo*", "comment with multiple words")) - assert.Equal(t, NewIgnores("foo* # comment with#multiple#words"), SingleIgnore("foo*", "comment with#multiple#words")) - assert.Equal(t, NewIgnores("foo*# comment"), SingleIgnore("foo*", "comment")) - - assert.Equal(t, NewIgnores("# comment"), SingleIgnore("", "comment")) - assert.Equal(t, NewIgnores("#comment"), SingleIgnore("", "comment")) - - assert.Equal(t, NewIgnores(""), SingleIgnore("", "")) - assert.Equal(t, NewIgnores(" "), SingleIgnore("", "")) - - assert.Equal(t, NewIgnores("foo # ignore:some-detector"), SingleIgnore("foo", "ignore:some-detector", "some-detector")) - assert.Equal(t, NewIgnores("foo # ignore:some-detector,some-other-detector"), SingleIgnore("foo", "ignore:some-detector,some-other-detector", "some-detector", "some-other-detector")) - assert.Equal(t, NewIgnores("foo # ignore:some-detector because of some reason"), SingleIgnore("foo", "ignore:some-detector because of some reason", "some-detector")) - -} - func TestDirectoryPatterns(t *testing.T) { assertAccepts("foo/", "", "bar", t) assertAccepts("foo/", "", "foo", t) @@ -55,14 +37,14 @@ func TestIgnoreAdditionsByScope(t *testing.T) { additions := []gitrepo.Addition{file1, file2, file3, file4, file5} scopesToIgnore := []string{"node", "go"} - talismanRCIgnoreConfig := CreateTalismanRCIgnoreWithScopeIgnore(scopesToIgnore) + talismanRCConfig := CreatetalismanRCWithScopeIgnore(scopesToIgnore) nodeIgnores := []string{"node.lock", "*yarn.lock"} javaIgnores := []string{"java.lock"} goIgnores := []string{"go.lock", "Gopkg.lock", "vendors/"} scopesMap := map[string][]string{"node": nodeIgnores, "java": javaIgnores, "go": goIgnores} - filteredAdditions := talismanRCIgnoreConfig.IgnoreAdditionsByScope(additions, scopesMap) + filteredAdditions := talismanRCConfig.IgnoreAdditionsByScope(additions, scopesMap) assert.NotContains(t, filteredAdditions, file1) assert.NotContains(t, filteredAdditions, file2) @@ -77,10 +59,10 @@ func TestIgnoringDetectors(t *testing.T) { } func TestAddIgnoreFiles(t *testing.T) { - talismanRCIgnoreConfig := CreateTalismanRCIgnoreWithScopeIgnore([]string{}) - talismanRCIgnoreConfig.AddFileIgnores([]FileIgnoreConfig{FileIgnoreConfig{"Foo", "SomeCheckSum", []string{}}}) - talismanRCIgnoreConfig = Get() - assert.Equal(t, 1, len(talismanRCIgnoreConfig.FileIgnoreConfig)) + talismanRCConfig := CreatetalismanRCWithScopeIgnore([]string{}) + talismanRCConfig.AddFileIgnores([]FileIgnoreConfig{FileIgnoreConfig{"Foo", "SomeCheckSum", []string{}}}) + talismanRCConfig = Get() + assert.Equal(t, 1, len(talismanRCConfig.FileIgnoreConfig)) } func assertDenies(line, ignoreDetector string, path string, t *testing.T) { @@ -88,7 +70,7 @@ func assertDenies(line, ignoreDetector string, path string, t *testing.T) { } func assertDeniesDetector(line, ignoreDetector string, path string, detectorName string, t *testing.T) { - assert.True(t, CreateTalismanRCIgnoreWithFileName(line, ignoreDetector).Deny(testAddition(path), detectorName), "%s is expected to deny a file named %s.", line, path) + assert.True(t, CreatetalismanRCWithFileName(line, ignoreDetector).Deny(testAddition(path), detectorName), "%s is expected to deny a file named %s.", line, path) } func assertAccepts(line, ignoreDetector string, path string, t *testing.T, detectorNames ...string) { @@ -96,27 +78,27 @@ func assertAccepts(line, ignoreDetector string, path string, t *testing.T, detec } func assertAcceptsDetector(line, ignoreDetector string, path string, detectorName string, t *testing.T) { - assert.True(t, CreateTalismanRCIgnoreWithFileName(line, ignoreDetector).Accept(testAddition(path), detectorName), "%s is expected to accept a file named %s.", line, path) + assert.True(t, CreatetalismanRCWithFileName(line, ignoreDetector).Accept(testAddition(path), detectorName), "%s is expected to accept a file named %s.", line, path) } func testAddition(path string) gitrepo.Addition { return gitrepo.NewAddition(path, make([]byte, 0)) } -func CreateTalismanRCIgnoreWithFileName(filename string, detector string) *TalismanRCIgnore { +func CreatetalismanRCWithFileName(filename string, detector string) *TalismanRC { fileIgnoreConfig := FileIgnoreConfig{} fileIgnoreConfig.FileName = filename if detector != "" { fileIgnoreConfig.IgnoreDetectors = make([]string, 1) fileIgnoreConfig.IgnoreDetectors[0] = detector } - talismanRCIgnore := TalismanRCIgnore{} - talismanRCIgnore.FileIgnoreConfig = make([]FileIgnoreConfig, 1) - talismanRCIgnore.FileIgnoreConfig[0] = fileIgnoreConfig - return &talismanRCIgnore + talismanRC := TalismanRC{} + talismanRC.FileIgnoreConfig = make([]FileIgnoreConfig, 1) + talismanRC.FileIgnoreConfig[0] = fileIgnoreConfig + return &talismanRC } -func CreateTalismanRCIgnoreWithScopeIgnore(scopesToIgnore []string) *TalismanRCIgnore { +func CreatetalismanRCWithScopeIgnore(scopesToIgnore []string) *TalismanRC { var scopeConfigs []ScopeConfig for _, scopeIgnore := range scopesToIgnore { scopeIgnoreConfig := ScopeConfig{} @@ -124,14 +106,6 @@ func CreateTalismanRCIgnoreWithScopeIgnore(scopesToIgnore []string) *TalismanRCI scopeConfigs = append(scopeConfigs, scopeIgnoreConfig) } - talismanRCIgnore := TalismanRCIgnore{ScopeConfig: scopeConfigs} - return &talismanRCIgnore -} - -func SingleIgnore(pattern string, comment string, ignoredDetectors ...string) Ignores { - return Ignores{patterns: []Ignore{{ - pattern: pattern, - comment: comment, - ignoredDetectors: ignoredDetectors, - }}} -} + talismanRC := TalismanRC{ScopeConfig: scopeConfigs} + return &talismanRC +} \ No newline at end of file