Skip to content

Commit aa26664

Browse files
authored
Update Nightfall Config detectors to be array (#23)
* Clean up tests
1 parent 2191e0f commit aa26664

File tree

12 files changed

+71
-185
lines changed

12 files changed

+71
-185
lines changed

.github/workflows/nightfalldlp.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
name: nightfalldlp
32
on:
43
push:
@@ -14,7 +13,7 @@ jobs:
1413
run: |
1514
echo ::add-path::$(go env GOPATH)/bin
1615
17-
- name: Download repo (and action since it's currently in a private repo)
16+
- name: Download repo
1817
uses: actions/checkout@v2
1918

2019
# https://github.com/actions/cache/blob/master/examples.md#go---modules

.nightfalldlp/config.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
{
2-
"detectors": {
3-
"CREDIT_CARD_NUMBER": "POSSIBLE",
4-
"PHONE_NUMBER": "LIKELY"
5-
},
2+
"detectors": [
3+
"CREDIT_CARD_NUMBER",
4+
"PHONE_NUMBER",
5+
"API_KEY",
6+
"CRYPTOGRAPHIC_KEY"
7+
],
68
"maxNumberConcurrentRoutines": 5,
79
"tokenExclusionList": [
8-
"4242-4242-4242-4242",
910
"4916-6734-7572-5015",
1011
"301-123-4567",
1112
"1-240-925-5721"

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ security, and ensure you never accidentally leak secrets or other sensitive info
99
### GithubActions
1010
[NightfallDLP](https://github.com/nightfallai/nightfall_dlp_action)
1111

12+
## Detectors
13+
Each detector represents a type of information you want to search for in your code scans (e.g. CRYPTOGRAPHIC_KEY). The
14+
configuration is an array of canonical detector names.
15+
1216
## Additional Configuration
1317
Aside from which detectors to scan on, you can add additional fields to your config, `./nightfall/config.json`, to ignore tokens and files as well as specify which files to exclusively scan on.
1418
### Token Exclusion

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
77
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
88
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
99
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
10+
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
1011
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
1112
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
1213
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -42,9 +43,12 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq
4243
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
4344
golang.org/x/tools v0.0.0-20190425150028-36563e24a262 h1:qsl9y/CJx34tuA7QCPNp86JNJe4spst6Ff8MjvPUdPg=
4445
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
46+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
4547
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
4648
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
49+
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
4750
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
51+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
4852
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4953
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
5054
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/clients/diffreviewer/github/github_service.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (s *Service) LoadConfig(nightfallConfigFileName string) (*nightfallconfig.C
178178
if s.CheckRequest.SHA == "" {
179179
s.CheckRequest.SHA = event.HeadCommit.ID
180180
}
181-
nightfallConfig, err := nightfallconfig.GetConfigFile(workspacePath, nightfallConfigFileName)
181+
nightfallConfig, err := nightfallconfig.GetNightfallConfigFile(workspacePath, nightfallConfigFileName)
182182
if err != nil {
183183
s.Logger.Error("Error getting Nightfall config file. Ensure you have a Nightfall config file located in the root of your repository at .nightfalldlp/config.json with at least one Detector enabled")
184184
return nil, err
@@ -261,9 +261,7 @@ func whitespaceOnlyLine(line *diffreviewer.Line) bool {
261261
}
262262

263263
// WriteComments posts the findings as annotations to the github check
264-
func (s *Service) WriteComments(
265-
comments []*diffreviewer.Comment,
266-
) error {
264+
func (s *Service) WriteComments(comments []*diffreviewer.Comment) error {
267265
s.Logger.Debug(fmt.Sprintf("Writting %d annotations to Github", len(comments)))
268266
checkRun, err := s.createCheckRun()
269267
if err != nil {

internal/clients/diffreviewer/github/github_service_test.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ func (g *githubTestSuite) TestLoadConfig() {
160160
sha := "1234"
161161
owner := "nightfallai"
162162
repo := "testRepo"
163+
cc := nightfallAPI.CREDIT_CARD_NUMBER
164+
phone := nightfallAPI.PHONE_NUMBER
165+
ip := nightfallAPI.IP_ADDRESS
163166
pullRequest := 1
164167
workspace, err := os.Getwd()
165168
g.NoError(err, "Error getting workspace")
@@ -170,12 +173,8 @@ func (g *githubTestSuite) TestLoadConfig() {
170173
os.Setenv(githubservice.NightfallAPIKeyEnvVar, apiKey)
171174

172175
expectedNightfallConfig := &nightfallconfig.Config{
173-
NightfallAPIKey: apiKey,
174-
NightfallDetectors: nightfallconfig.DetectorConfig{
175-
nightfallAPI.CREDIT_CARD_NUMBER: nightfallAPI.POSSIBLE,
176-
nightfallAPI.PHONE_NUMBER: nightfallAPI.LIKELY,
177-
nightfallAPI.IP_ADDRESS: nightfallAPI.POSSIBLE,
178-
},
176+
NightfallAPIKey: apiKey,
177+
NightfallDetectors: []*nightfallAPI.Detector{&cc, &phone, &ip},
179178
NightfallMaxNumberRoutines: 20,
180179
TokenExclusionList: []string{excludedCreditCardRegex, excludedApiToken, excludedIPRegex},
181180
FileInclusionList: []string{"*"},

internal/clients/nightfall/nightfall.go

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,12 @@ const (
3232
MaxConcurrentRoutinesCap = 50
3333
)
3434

35-
// likelihoodThresholdMap gives each likelihood an integer value representation
36-
// the integer value can be used to determine relative importance and can
37-
// allow for likelihoods to be compared directly
38-
// eg. VERY_LIKELY > LIKELY since likelihoodThresholdMap[VERY_LIKELY] > likelihoodThresholdMap[LIKELY]
39-
var likelihoodThresholdMap = map[nightfallAPI.Likelihood]int{
40-
nightfallAPI.VERY_UNLIKELY: 1,
41-
nightfallAPI.UNLIKELY: 2,
42-
nightfallAPI.POSSIBLE: 3,
43-
nightfallAPI.LIKELY: 4,
44-
nightfallAPI.VERY_LIKELY: 5,
45-
}
46-
4735
// Client client which uses Nightfall API
4836
// to determine findings from input strings
4937
type Client struct {
5038
APIClient nightfallintf.NightfallAPI
5139
APIKey string
52-
DetectorConfigs nightfallconfig.DetectorConfig
40+
Detectors []*nightfallAPI.Detector
5341
MaxNumberRoutines int
5442
TokenExclusionList []string
5543
FileInclusionList []string
@@ -61,7 +49,7 @@ func NewClient(config nightfallconfig.Config) *Client {
6149
n := Client{
6250
APIClient: NewAPIClient(),
6351
APIKey: config.NightfallAPIKey,
64-
DetectorConfigs: config.NightfallDetectors,
52+
Detectors: config.NightfallDetectors,
6553
MaxNumberRoutines: config.NightfallMaxNumberRoutines,
6654
TokenExclusionList: config.TokenExclusionList,
6755
FileInclusionList: config.FileInclusionList,
@@ -76,15 +64,6 @@ type contentToScan struct {
7664
LineNumber int
7765
}
7866

79-
func foundSensitiveData(finding nightfallAPI.ScanResponse, detectorConfigs nightfallconfig.DetectorConfig) bool {
80-
minimumLikelihoodForDetector, ok := detectorConfigs[nightfallAPI.Detector(finding.Detector)]
81-
if !ok {
82-
return false
83-
}
84-
findingLikelihood := nightfallAPI.Likelihood(finding.Confidence.Bucket)
85-
return likelihoodThresholdMap[findingLikelihood] >= likelihoodThresholdMap[minimumLikelihoodForDetector]
86-
}
87-
8867
func blurContent(content string) string {
8968
contentRune := []rune(content)
9069
blurredContent := string(contentRune[:2])
@@ -174,14 +153,12 @@ func sliceListBySize(index, numItemsForMaxSize int, contentToScanList []*content
174153
func createCommentsFromScanResp(
175154
inputContent []*contentToScan,
176155
resp [][]nightfallAPI.ScanResponse,
177-
detectorConfigs nightfallconfig.DetectorConfig,
178156
tokenExclusionList []string,
179157
) []*diffreviewer.Comment {
180158
comments := []*diffreviewer.Comment{}
181159
for j, findingList := range resp {
182160
for _, finding := range findingList {
183-
if foundSensitiveData(finding, detectorConfigs) &&
184-
!isFindingInTokenExclusionList(finding.Fragment, tokenExclusionList) {
161+
if !isFindingInTokenExclusionList(finding.Fragment, tokenExclusionList) {
185162
// Found sensitive info
186163
// Create comment if fragment is not in exclusion set
187164
correspondingContent := inputContent[j]
@@ -217,10 +194,10 @@ func matchRegex(finding string, regexPatterns []string) bool {
217194
}
218195

219196
func (n *Client) createScanRequest(items []string) nightfallAPI.ScanRequest {
220-
detectors := make([]nightfallAPI.ScanRequestDetectors, 0, len(n.DetectorConfigs))
221-
for d := range n.DetectorConfigs {
197+
detectors := make([]nightfallAPI.ScanRequestDetectors, 0, len(n.Detectors))
198+
for _, d := range n.Detectors {
222199
detectors = append(detectors, nightfallAPI.ScanRequestDetectors{
223-
Name: string(d),
200+
Name: string(*d),
224201
})
225202
}
226203
return nightfallAPI.ScanRequest{
@@ -241,12 +218,12 @@ func (n *Client) scanContent(ctx context.Context, cts []*contentToScan, requestN
241218
// send API request
242219
resp, err := n.Scan(ctx, logger, items)
243220
if err != nil {
244-
logger.Debug(fmt.Sprintf("Error sending request number %d with %d items", requestNum, len(items)))
221+
logger.Debug(fmt.Sprintf("Error sending request number %d with %d items: %v", requestNum, len(items), err))
245222
return nil, err
246223
}
247224

248225
// Determine findings from response and create comments
249-
createdComments := createCommentsFromScanResp(cts, resp, n.DetectorConfigs, n.TokenExclusionList)
226+
createdComments := createCommentsFromScanResp(cts, resp, n.TokenExclusionList)
250227
logger.Debug(fmt.Sprintf("Got %d annotations for request #%d", len(createdComments), requestNum))
251228
return createdComments, nil
252229
}

internal/clients/nightfall/nightfall_internal_test.go

Lines changed: 10 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66

77
"github.com/nightfallai/nightfall_cli/internal/clients/diffreviewer"
88
githublogger "github.com/nightfallai/nightfall_cli/internal/clients/logger/github_logger"
9-
"github.com/nightfallai/nightfall_cli/internal/nightfallconfig"
109
nightfallAPI "github.com/nightfallai/nightfall_go_client/generated"
10+
1111
"github.com/stretchr/testify/assert"
1212
)
1313

@@ -127,18 +127,14 @@ func TestSliceListBySize(t *testing.T) {
127127
}
128128

129129
func TestCreateCommentsFromScanResp(t *testing.T) {
130-
detectorConfigs := nightfallconfig.DetectorConfig{
131-
nightfallAPI.CREDIT_CARD_NUMBER: nightfallAPI.LIKELY,
132-
nightfallAPI.IP_ADDRESS: nightfallAPI.LIKELY,
133-
}
134130
emptyTokenExclusionList := []string{}
135131
creditCard2Regex := "4242-4242-4242-[0-9]{4}"
136132
localIpRegex := "^127\\."
137133
tokenExclusionList := []string{creditCard2Regex, localIpRegex}
138-
creditCardResponse := createScanResponse(exampleCreditCardNumber, nightfallAPI.CREDIT_CARD_NUMBER, nightfallAPI.VERY_LIKELY)
139-
creditCard2Response := createScanResponse(exampleCreditCardNumber2, nightfallAPI.CREDIT_CARD_NUMBER, nightfallAPI.VERY_LIKELY)
140-
apiKeyResponse := createScanResponse(exampleAPIKey, nightfallAPI.API_KEY, nightfallAPI.VERY_LIKELY)
141-
ipAddressResponse := createScanResponse(exampleIP, nightfallAPI.IP_ADDRESS, nightfallAPI.VERY_LIKELY)
134+
creditCardResponse := createScanResponse(exampleCreditCardNumber, nightfallAPI.CREDIT_CARD_NUMBER)
135+
creditCard2Response := createScanResponse(exampleCreditCardNumber2, nightfallAPI.CREDIT_CARD_NUMBER)
136+
apiKeyResponse := createScanResponse(exampleAPIKey, nightfallAPI.API_KEY)
137+
ipAddressResponse := createScanResponse(exampleIP, nightfallAPI.IP_ADDRESS)
142138
tests := []struct {
143139
haveContentToScanList []*contentToScan
144140
haveScanResponseList [][]nightfallAPI.ScanResponse
@@ -168,76 +164,28 @@ func TestCreateCommentsFromScanResp(t *testing.T) {
168164
haveTokenExclusionList: emptyTokenExclusionList,
169165
want: []*diffreviewer.Comment{
170166
createComment(creditCardResponse),
167+
createComment(apiKeyResponse),
171168
createComment(creditCard2Response),
172169
},
173-
desc: "credit cards omit api finding",
174-
},
175-
{
176-
haveContentToScanList: []*contentToScan{
177-
createContentToScan(creditCardNumberContent),
178-
createContentToScan("nothing in here"),
179-
createContentToScan(apiKeyContent),
180-
},
181-
haveScanResponseList: [][]nightfallAPI.ScanResponse{
182-
{
183-
creditCardResponse,
184-
},
185-
{
186-
createScanResponse("low likelihood on 4534343", nightfallAPI.CREDIT_CARD_NUMBER, nightfallAPI.UNLIKELY),
187-
},
188-
},
189-
haveTokenExclusionList: emptyTokenExclusionList,
190-
want: []*diffreviewer.Comment{
191-
createComment(creditCardResponse),
192-
},
193-
desc: "single credit card passing likelihood threshold",
170+
desc: "credit cards and an api key",
194171
},
195172
{
196173
haveContentToScanList: []*contentToScan{
197174
createContentToScan("nothing in here"),
198175
createContentToScan("nothing in here"),
199176
createContentToScan("nothing in here"),
200177
createContentToScan("nothing in here"),
201-
createContentToScan(apiKeyContent),
202178
},
203179
haveScanResponseList: [][]nightfallAPI.ScanResponse{
204180
{},
205181
{},
206182
{},
207183
{},
208-
{
209-
apiKeyResponse,
210-
},
211184
},
212185
haveTokenExclusionList: emptyTokenExclusionList,
213186
want: []*diffreviewer.Comment{},
214187
desc: "no comments",
215188
},
216-
{
217-
haveContentToScanList: []*contentToScan{
218-
createContentToScan(creditCardNumberContent),
219-
createContentToScan("nothing in here"),
220-
createContentToScan(apiKeyContent),
221-
createContentToScan(creditCardNumber2Content),
222-
},
223-
haveScanResponseList: [][]nightfallAPI.ScanResponse{
224-
{
225-
creditCardResponse,
226-
},
227-
{},
228-
{
229-
apiKeyResponse,
230-
},
231-
{
232-
creditCard2Response,
233-
},
234-
},
235-
haveTokenExclusionList: tokenExclusionList,
236-
want: []*diffreviewer.Comment{
237-
createComment(creditCardResponse),
238-
},
239-
desc: "single credit card excluded",
240-
},
241189
{
242190
haveContentToScanList: []*contentToScan{
243191
createContentToScan("4242-4242-4242-abcd"),
@@ -266,40 +214,8 @@ func TestCreateCommentsFromScanResp(t *testing.T) {
266214
},
267215
}
268216
for _, tt := range tests {
269-
actual := createCommentsFromScanResp(tt.haveContentToScanList, tt.haveScanResponseList, detectorConfigs, tt.haveTokenExclusionList)
270-
assert.Equal(t, tt.want, actual, fmt.Sprintf("Incorrect response from createCommentsFromScanResp: %s test", tt.desc))
271-
}
272-
}
273-
274-
func TestFoundSensitiveData(t *testing.T) {
275-
detectorConfigs := nightfallconfig.DetectorConfig{
276-
nightfallAPI.CREDIT_CARD_NUMBER: nightfallAPI.POSSIBLE,
277-
}
278-
tests := []struct {
279-
have nightfallAPI.Likelihood
280-
want bool
281-
}{}
282-
for _, l := range allLikelihoods {
283-
var want bool
284-
switch l {
285-
case nightfallAPI.VERY_UNLIKELY, nightfallAPI.UNLIKELY:
286-
want = false
287-
default:
288-
want = true
289-
}
290-
tests = append(tests, struct {
291-
have nightfallAPI.Likelihood
292-
want bool
293-
}{
294-
have: l,
295-
want: want,
296-
})
297-
}
298-
299-
for _, tt := range tests {
300-
finding := createScanResponse("", nightfallAPI.CREDIT_CARD_NUMBER, tt.have)
301-
actual := foundSensitiveData(finding, detectorConfigs)
302-
assert.Equal(t, tt.want, actual, "Incorrect response from foundSensitiveData")
217+
actual := createCommentsFromScanResp(tt.haveContentToScanList, tt.haveScanResponseList, tt.haveTokenExclusionList)
218+
assert.Equal(t, tt.want, actual, fmt.Sprintf("Incorrect response from createCommentsFromScanResp: test '%s'", tt.desc))
303219
}
304220
}
305221

@@ -465,14 +381,10 @@ func TestMatchGlob(t *testing.T) {
465381
assert.Equal(t, tt.wantMatchedPaths, matchedPaths, fmt.Sprintf("Incorrect response from match glob %s test", tt.desc))
466382
}
467383
}
468-
469-
func createScanResponse(fragment string, detector nightfallAPI.Detector, likelihood nightfallAPI.Likelihood) nightfallAPI.ScanResponse {
384+
func createScanResponse(fragment string, detector nightfallAPI.Detector) nightfallAPI.ScanResponse {
470385
return nightfallAPI.ScanResponse{
471386
Fragment: fragment,
472387
Detector: string(detector),
473-
Confidence: nightfallAPI.ScanResponseConfidence{
474-
Bucket: string(likelihood),
475-
},
476388
Location: nightfallAPI.ScanResponseLocation{
477389
ByteRange: nightfallAPI.ScanResponseLocationByteRange{
478390
Start: 0,

0 commit comments

Comments
 (0)