8
8
"encoding/json"
9
9
"fmt"
10
10
"strings"
11
+ "time"
11
12
12
13
"github.com/aws/aws-sdk-go/aws"
13
14
"github.com/aws/aws-sdk-go/aws/session"
@@ -19,17 +20,43 @@ import (
19
20
// SNSConfig holds the required SNS config information.
20
21
type SNSConfig struct {
21
22
TopicArn string `mapstructure:"topic_arn"`
22
- Enabled bool `mapstructure:"enabled"`
23
23
Endpoint string `mapstructure:"endpoint"`
24
24
}
25
25
26
- // SNSNotifier sends push events to an SNS topic.
26
+ // SNSNotifier sends notifications to an SNS topic.
27
27
type SNSNotifier struct {
28
28
conf SNSConfig
29
29
sns snsiface.SNSAPI
30
30
logger * log.Logger
31
31
}
32
32
33
+ // FindingNotification is the data that's notified when a new finding occurs.
34
+ // TODO: This struct has been moved from processor types so it's isolated in
35
+ // the SNS notifier implementation and it's easier to deprecate in the future
36
+ // in favor of Kafka implementation. This SNS implementation only exists in
37
+ // order to maintain compatibility with old integrations that expects this
38
+ // notification format.
39
+ type findingNotification struct {
40
+ TargetID string `json:"target_id"`
41
+ Target string `json:"target"`
42
+ IssueID string `json:"issue_id"`
43
+ FindingID string `json:"finding_id"`
44
+ CheckID string `json:"check_id"`
45
+ ChecktypeName string `json:"checktype_name"`
46
+ CheckTypeOptions string `json:"checktype_options"`
47
+ Tag string `json:"tag"`
48
+ Time time.Time `json:"time"`
49
+ Vulnerability vulnerability `json:"vulnerability"`
50
+ }
51
+
52
+ type vulnerability struct {
53
+ ID string `json:"id"`
54
+ Summary string `json:"summary"`
55
+ Score float64 `json:"score"`
56
+ CWEID uint32 `json:"cwe_id"`
57
+ Description string `json:"description"`
58
+ }
59
+
33
60
// NewSNSNotifier creates a new SNSNotifier with the given configuration.
34
61
func NewSNSNotifier (conf SNSConfig , logger * log.Logger ) (* SNSNotifier , error ) {
35
62
sess , err := session .NewSession ()
@@ -57,25 +84,23 @@ func NewSNSNotifier(conf SNSConfig, logger *log.Logger) (*SNSNotifier, error) {
57
84
58
85
// PushFinding pushes a finding notification to the configured sns topic.
59
86
func (n * SNSNotifier ) PushFinding (f FindingNotification ) error {
60
- if ! n .conf .Enabled {
61
- return nil
62
- }
63
-
64
- n .logger .Info ("Pushing notification to SNS" )
65
- content , err := json .Marshal (f )
87
+ n .logger .WithFields (log.Fields {
88
+ "notifier" : "sns" ,
89
+ "id" : f .ID ,
90
+ }).Info ("pushing finding notification" )
91
+ content , err := json .Marshal (toOldFmt (f ))
66
92
if err != nil {
67
93
return err
68
94
}
69
95
input := & sns.PublishInput {
70
96
Message : aws .String (string (content )),
71
97
TopicArn : aws .String (n .conf .TopicArn ),
72
98
}
99
+
73
100
_ , err = n .sns .Publish (input )
74
101
if err != nil {
75
102
return err
76
103
}
77
- n .logger .Info ("Notification pushed to SNS successfully" )
78
-
79
104
return nil
80
105
}
81
106
@@ -96,3 +121,26 @@ func parseSNSARN(snsARN string) snsData {
96
121
endpoint : fmt .Sprintf ("https://sns.%v.amazonaws.com/%v/%v" , region , accountID , name ),
97
122
}
98
123
}
124
+
125
+ // toOldFmt translates a FindingNotification into the old
126
+ // findingNotification format.
127
+ func toOldFmt (f FindingNotification ) findingNotification {
128
+ return findingNotification {
129
+ TargetID : f .Target .ID ,
130
+ Target : f .Target .Identifier ,
131
+ IssueID : f .Issue .ID ,
132
+ FindingID : f .ID ,
133
+ CheckID : f .Source .Instance ,
134
+ ChecktypeName : f .Source .Component ,
135
+ CheckTypeOptions : f .Source .Options ,
136
+ Tag : f .Tag ,
137
+ Time : f .Source .Time ,
138
+ Vulnerability : vulnerability {
139
+ ID : f .Issue .ID ,
140
+ Summary : f .Issue .Summary ,
141
+ Score : f .Finding .Score ,
142
+ CWEID : f .Issue .CWEID ,
143
+ Description : f .Issue .Description ,
144
+ },
145
+ }
146
+ }
0 commit comments