Skip to content

Commit 38c63fb

Browse files
author
Dan Hertz
authored
add ability to change annotation level (#72)
* add ability to change annotation level * fix readme json * test violation * When warn annotation is set, do not fail check * Add log warning to unknown annotation level * re-order log to make sure to capture a useful message * Correct log levels in circle ci logging * add test to run binary * pass through new config in circleci * Revert "test violation" This reverts commit 395d23d.
1 parent 07bdb81 commit 38c63fb

File tree

15 files changed

+259
-64
lines changed

15 files changed

+259
-64
lines changed

.circleci/config.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ jobs:
2121
name: Clean up reusable Docker
2222
command: clean_up_reusable_docker
2323

24+
run-local:
25+
docker:
26+
- image: cimg/go:1.18.4
27+
steps:
28+
- checkout
29+
- run:
30+
name: run binary locally
31+
command: make
32+
environment:
33+
GITHUB_WORKSPACE: "."
34+
2435
lint:
2536
docker:
2637
- image: deliveroo/circleci:0.2.8
@@ -83,6 +94,11 @@ workflows:
8394
tags:
8495
only: /.*/
8596
context: build
97+
- run-local:
98+
filters:
99+
tags:
100+
only: /.*/
101+
context: build
86102
- lint:
87103
filters:
88104
tags:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ clean:
2525
$(GOCLEAN)
2626
rm -f $(BINARY_NAME)
2727
start:
28-
./$(BINARY_NAME)
28+
$(BINARY_NAME)
2929
dockertag:
3030
docker tag $(NAME):latest $(VERSION)
3131
docker tag $(NAME):latest $(LATEST)

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ config will be equivalent to the snippet below:
4545
}
4646
]
4747
}
48-
]
48+
],
49+
"annotationLevel": "failure"
4950
}
5051
```
5152

@@ -152,7 +153,12 @@ object:
152153
If your config file specifies a non-null value for `defaultRedactionConfig`, then exactly one of the above keys must be
153154
filled out; if more than one is filled out, the Nightfall API will return a 400 error code.
154155

155-
For more information on how to configure redaction-related fields, refer to the [Nightfall docs](https://docs.nightfall.ai/reference/scanpayloadv3).
156+
For more information on how to configure redaction-related fields, refer to the [Nightfall docs](https://docs.nightfall.ai/reference/scanpayloadv3).
157+
158+
### Annotation Level customization
159+
160+
Annotations can be configured to be `notice`, `warning`, or `failure`, by setting the `annotationLevel` key in the
161+
configuration object. The check will only fail if `failure` annotations are written.
156162

157163
## Configuration Examples
158164

@@ -332,3 +338,9 @@ Encryption:
332338
}
333339
}
334340
```
341+
342+
Annotate as Warnings:
343+
```json
344+
{
345+
"annotationLevel": "warning"
346+
}

cmd/nightfalldlp/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func run() error {
6060
return err
6161
}
6262

63-
return diffReviewClient.WriteComments(comments)
63+
return diffReviewClient.WriteComments(comments, nightfallConfig.AnnotationLevel)
6464
}
6565

6666
// usingGithubAction determine if nightfalldlp is being run by

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
172172
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
173173
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
174174
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
175+
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
175176
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
176177
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
177178
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -287,6 +288,7 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY
287288
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
288289
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
289290
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
291+
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k=
290292
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
291293
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
292294
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/clients/diffreviewer/circleci/circleci_service.go

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func (s *Service) LoadConfig(nightfallConfigFileName string) (*nightfallconfig.C
120120
FileInclusionList: nightfallConfig.FileInclusionList,
121121
FileExclusionList: nightfallConfig.FileExclusionList,
122122
DefaultRedactionConfig: nightfallConfig.DefaultRedactionConfig,
123+
AnnotationLevel: nightfallConfig.AnnotationLevel,
123124
}, nil
124125
}
125126

@@ -198,14 +199,18 @@ func (s *Service) GetDiff() ([]*diffreviewer.FileDiff, error) {
198199
}
199200

200201
// WriteComments posts the findings as annotations to the github check
201-
func (s *Service) WriteComments(comments []*diffreviewer.Comment) error {
202+
func (s *Service) WriteComments(comments []*diffreviewer.Comment, level string) error {
202203
if len(comments) == 0 {
203204
s.Logger.Info("no sensitive items found")
204205
return nil
205206
}
206-
s.logCommentsToCircle(comments)
207+
s.logCommentsToCircle(comments, level)
208+
var returnErr error
209+
if level == nightfallconfig.AnnotationLevelFailure {
210+
returnErr = errSensitiveItemsFound
211+
}
207212
if s.GithubClient == nil {
208-
return errSensitiveItemsFound
213+
return returnErr
209214
}
210215
if s.PrDetails.PrNumber != nil {
211216
existingComments, _, err := s.GithubClient.PullRequestsService().ListComments(
@@ -218,7 +223,7 @@ func (s *Service) WriteComments(comments []*diffreviewer.Comment) error {
218223
if err != nil {
219224
s.Logger.Error(fmt.Sprintf("Error listing existing pull request comments: %s", err.Error()))
220225
}
221-
githubComments := s.createGithubPullRequestComments(comments)
226+
githubComments := s.createGithubPullRequestComments(comments, level)
222227
filteredGithubComments := filterExistingComments(githubComments, existingComments)
223228
for _, c := range filteredGithubComments {
224229
_, _, err := s.GithubClient.PullRequestsService().CreateComment(
@@ -233,7 +238,7 @@ func (s *Service) WriteComments(comments []*diffreviewer.Comment) error {
233238
}
234239
}
235240
} else {
236-
githubComments := s.createGithubRepositoryComments(comments)
241+
githubComments := s.createGithubRepositoryComments(comments, level)
237242
for _, c := range githubComments {
238243
_, _, err := s.GithubClient.RepositoriesService().CreateComment(
239244
context.Background(),
@@ -248,26 +253,37 @@ func (s *Service) WriteComments(comments []*diffreviewer.Comment) error {
248253
}
249254
}
250255
// returning error to fail circleCI step
251-
return errSensitiveItemsFound
256+
return returnErr
252257
}
253258

254-
func (s *Service) logCommentsToCircle(comments []*diffreviewer.Comment) {
259+
func (s *Service) logCommentsToCircle(comments []*diffreviewer.Comment, level string) {
255260
for _, comment := range comments {
256-
s.Logger.Error(fmt.Sprintf(
261+
logString := fmt.Sprintf(
257262
"%s at %s on line %d",
258263
comment.Body,
259264
comment.FilePath,
260265
comment.LineNumber,
261-
))
266+
)
267+
switch level {
268+
case nightfallconfig.AnnotationLevelFailure:
269+
s.Logger.Error(logString)
270+
case nightfallconfig.AnnotationLevelWarning:
271+
s.Logger.Warning(logString)
272+
case nightfallconfig.AnnotationLevelNotice:
273+
s.Logger.Info(logString)
274+
default:
275+
s.Logger.Error(logString)
276+
}
262277
}
263278
}
264279

265-
func (s *Service) createGithubPullRequestComments(comments []*diffreviewer.Comment) []*github.PullRequestComment {
280+
func (s *Service) createGithubPullRequestComments(comments []*diffreviewer.Comment, level string) []*github.PullRequestComment {
266281
githubComments := make([]*github.PullRequestComment, len(comments))
267282
for i, comment := range comments {
283+
body := fmt.Sprintf("%s: %s", level, comment.Body)
268284
githubComments[i] = &github.PullRequestComment{
269285
CommitID: &s.PrDetails.CommitSha,
270-
Body: &comment.Body,
286+
Body: &body,
271287
Path: &comment.FilePath,
272288
Line: &comment.LineNumber,
273289
Side: github.String(GithubCommentRightSide),
@@ -276,12 +292,13 @@ func (s *Service) createGithubPullRequestComments(comments []*diffreviewer.Comme
276292
return githubComments
277293
}
278294

279-
func (s *Service) createGithubRepositoryComments(comments []*diffreviewer.Comment) []*github.RepositoryComment {
295+
func (s *Service) createGithubRepositoryComments(comments []*diffreviewer.Comment, level string) []*github.RepositoryComment {
280296
githubComments := make([]*github.RepositoryComment, len(comments))
281297
for i, comment := range comments {
298+
body := fmt.Sprintf("%s: %s", level, comment.Body)
282299
githubComments[i] = &github.RepositoryComment{
283300
CommitID: &s.PrDetails.CommitSha,
284-
Body: &comment.Body,
301+
Body: &body,
285302
Path: &comment.FilePath,
286303
Position: &comment.LineNumber,
287304
}

internal/clients/diffreviewer/circleci/circleci_service_test.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ func (c *circleCiTestSuite) TestLoadConfig() {
216216
DefaultRedactionConfig: &nf.RedactionConfig{
217217
SubstitutionConfig: &nf.SubstitutionConfig{SubstitutionPhrase: "REDACTED"},
218218
},
219+
AnnotationLevel: "warning",
219220
}
220221

221222
nightfallConfig, err := tp.cs.LoadConfig(testConfigFileName)
@@ -246,6 +247,7 @@ func (c *circleCiTestSuite) TestLoadConfigDetectionRuleUUID() {
246247
TokenExclusionList: []string{excludedCreditCardRegex, excludedApiToken, excludedIPRegex},
247248
FileInclusionList: []string{"*"},
248249
FileExclusionList: []string{".nightfalldlp/config.json"},
250+
AnnotationLevel: "failure",
249251
}
250252

251253
nightfallConfig, err := tp.cs.LoadConfig(testConfigDetectionRuleUUIDFileName)
@@ -326,6 +328,7 @@ func (c *circleCiTestSuite) TestLoadEmptyConfig() {
326328
NumCharsToLeaveUnmasked: 2,
327329
},
328330
},
331+
AnnotationLevel: "failure",
329332
}
330333

331334
nightfallConfig, err := tp.cs.LoadConfig(testEmptyConfigFileName)
@@ -367,6 +370,7 @@ func (c *circleCiTestSuite) TestWriteCircleComments() {
367370
"/comments.txt",
368371
tp.cs.PrDetails.CommitSha,
369372
60,
373+
"notice",
370374
)
371375
emptyComments := make([]*diffreviewer.Comment, 0)
372376

@@ -377,8 +381,8 @@ func (c *circleCiTestSuite) TestWriteCircleComments() {
377381
}{
378382
{
379383
giveComments: testComments,
380-
wantErr: errSensitiveItemsFound,
381-
desc: "single batch comments test",
384+
wantErr: nil,
385+
desc: "notice: single batch comments test",
382386
},
383387
{
384388
giveComments: emptyComments,
@@ -392,15 +396,15 @@ func (c *circleCiTestSuite) TestWriteCircleComments() {
392396
mockLogger.EXPECT().Info("no sensitive items found")
393397
}
394398
for _, comment := range tt.giveComments {
395-
mockLogger.EXPECT().Error(fmt.Sprintf(
399+
mockLogger.EXPECT().Info(fmt.Sprintf(
396400
"%s at %s on line %d",
397401
comment.Body,
398402
comment.FilePath,
399403
comment.LineNumber,
400404
))
401405
}
402-
err := tp.cs.WriteComments(tt.giveComments)
403-
if len(tt.giveComments) == 0 {
406+
err := tp.cs.WriteComments(tt.giveComments, "notice")
407+
if tt.wantErr == nil {
404408
c.NoError(err, fmt.Sprintf("unexpected error writing comments for %s test", tt.desc))
405409
} else {
406410
c.EqualError(err, tt.wantErr.Error(), fmt.Sprintf("invalid error writing comments for %s test", tt.desc))
@@ -432,6 +436,7 @@ func (c *circleCiTestSuite) TestWritePullRequestComments() {
432436
"/comments.txt",
433437
tp.cs.PrDetails.CommitSha,
434438
60,
439+
"failure",
435440
)
436441
emptyComments, emptyGithubComments := make([]*diffreviewer.Comment, 0), make([]*github.PullRequestComment, 0)
437442

@@ -478,12 +483,12 @@ func (c *circleCiTestSuite) TestWritePullRequestComments() {
478483
)
479484
mockLogger.EXPECT().Error(fmt.Sprintf(
480485
"%s at %s on line %d",
481-
gc.GetBody(),
486+
"testComment",
482487
gc.GetPath(),
483488
gc.GetLine(),
484489
))
485490
}
486-
err := tp.cs.WriteComments(tt.giveComments)
491+
err := tp.cs.WriteComments(tt.giveComments, "failure")
487492
if len(tt.giveComments) > 0 {
488493
c.EqualError(
489494
err,
@@ -501,6 +506,7 @@ func makeTestGithubPullRequestComments(
501506
filePath,
502507
commitSha string,
503508
size int,
509+
level string,
504510
) ([]*diffreviewer.Comment, []*github.PullRequestComment) {
505511
comments := make([]*diffreviewer.Comment, size)
506512
githubComments := make([]*github.PullRequestComment, size)
@@ -511,9 +517,10 @@ func makeTestGithubPullRequestComments(
511517
FilePath: filePath,
512518
LineNumber: i + 1,
513519
}
520+
githubBody := fmt.Sprintf("%s: %s", level, body)
514521
githubComments[i] = &github.PullRequestComment{
515522
CommitID: &commitSha,
516-
Body: &body,
523+
Body: &githubBody,
517524
Path: &filePath,
518525
Line: &comments[i].LineNumber,
519526
Side: github.String(GithubCommentRightSide),
@@ -545,25 +552,23 @@ func (c *circleCiTestSuite) TestWriteRepositoryComments() {
545552
"/comments.txt",
546553
tp.cs.PrDetails.CommitSha,
547554
60,
555+
"warning",
548556
)
549557
emptyComments, emptyGithubComments := make([]*diffreviewer.Comment, 0), make([]*github.RepositoryComment, 0)
550558

551559
tests := []struct {
552560
giveComments []*diffreviewer.Comment
553561
giveGithubComments []*github.RepositoryComment
554-
wantError error
555562
desc string
556563
}{
557564
{
558565
giveComments: testComments,
559566
giveGithubComments: testGithubComments,
560-
wantError: errSensitiveItemsFound,
561567
desc: "single batch comments test",
562568
},
563569
{
564570
giveComments: emptyComments,
565571
giveGithubComments: emptyGithubComments,
566-
wantError: nil,
567572
desc: "no comments test",
568573
},
569574
}
@@ -581,19 +586,18 @@ func (c *circleCiTestSuite) TestWriteRepositoryComments() {
581586
testCircleService.PrDetails.CommitSha,
582587
gc,
583588
)
584-
mockLogger.EXPECT().Error(fmt.Sprintf(
589+
mockLogger.EXPECT().Warning(fmt.Sprintf(
585590
"%s at %s on line %d",
586-
gc.GetBody(),
591+
"testComment",
587592
gc.GetPath(),
588593
tt.giveComments[index].LineNumber,
589594
))
590595
}
591-
err := tp.cs.WriteComments(tt.giveComments)
596+
err := tp.cs.WriteComments(tt.giveComments, "warning")
592597
if len(tt.giveComments) > 0 {
593-
c.EqualError(
598+
c.NoError(
594599
err,
595-
tt.wantError.Error(),
596-
fmt.Sprintf("invalid error writing comments for %s test", tt.desc),
600+
fmt.Sprintf("should be no error writing comments for %s test", tt.desc),
597601
)
598602
} else {
599603
c.NoError(err, fmt.Sprintf("Error writing comments for %s test", tt.desc))
@@ -606,6 +610,7 @@ func makeTestGithubRepositoryComments(
606610
filePath,
607611
commitSha string,
608612
size int,
613+
level string,
609614
) ([]*diffreviewer.Comment, []*github.RepositoryComment) {
610615
comments := make([]*diffreviewer.Comment, size)
611616
githubComments := make([]*github.RepositoryComment, size)
@@ -616,9 +621,10 @@ func makeTestGithubRepositoryComments(
616621
FilePath: filePath,
617622
LineNumber: i + 1,
618623
}
624+
githubBody := fmt.Sprintf("%s: %s", level, body)
619625
githubComments[i] = &github.RepositoryComment{
620626
CommitID: &commitSha,
621-
Body: &body,
627+
Body: &githubBody,
622628
Path: &filePath,
623629
Position: github.Int(i + 1),
624630
}

internal/clients/diffreviewer/diff_reviewer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ type DiffReviewer interface {
1313
LoadConfig(nightfallConfigFileName string) (*nightfallconfig.Config, error)
1414
// GetDiff fetches the diff from the code repository and return a parsed array of FileDiffs
1515
GetDiff() ([]*FileDiff, error)
16-
// WriteComments posts the Nightfall DLP findings as comments/a review to the diff
17-
WriteComments(comments []*Comment) error
16+
// WriteComments posts the Nightfall DLP findings as comments/a review to the diff at a given alert level
17+
WriteComments(comments []*Comment, level string) error
1818
// GetLogger gets the logger for the diff reviewer
1919
GetLogger() logger.Logger
2020
}

0 commit comments

Comments
 (0)