88 "encoding/json"
99 "fmt"
1010 "strings"
11+ "time"
1112
1213 "github.com/aws/aws-sdk-go/aws"
1314 "github.com/aws/aws-sdk-go/aws/session"
@@ -19,17 +20,43 @@ import (
1920// SNSConfig holds the required SNS config information.
2021type SNSConfig struct {
2122 TopicArn string `mapstructure:"topic_arn"`
22- Enabled bool `mapstructure:"enabled"`
2323 Endpoint string `mapstructure:"endpoint"`
2424}
2525
26- // SNSNotifier sends push events to an SNS topic.
26+ // SNSNotifier sends notifications to an SNS topic.
2727type SNSNotifier struct {
2828 conf SNSConfig
2929 sns snsiface.SNSAPI
3030 logger * log.Logger
3131}
3232
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+
3360// NewSNSNotifier creates a new SNSNotifier with the given configuration.
3461func NewSNSNotifier (conf SNSConfig , logger * log.Logger ) (* SNSNotifier , error ) {
3562 sess , err := session .NewSession ()
@@ -57,25 +84,23 @@ func NewSNSNotifier(conf SNSConfig, logger *log.Logger) (*SNSNotifier, error) {
5784
5885// PushFinding pushes a finding notification to the configured sns topic.
5986func (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 ))
6692 if err != nil {
6793 return err
6894 }
6995 input := & sns.PublishInput {
7096 Message : aws .String (string (content )),
7197 TopicArn : aws .String (n .conf .TopicArn ),
7298 }
99+
73100 _ , err = n .sns .Publish (input )
74101 if err != nil {
75102 return err
76103 }
77- n .logger .Info ("Notification pushed to SNS successfully" )
78-
79104 return nil
80105}
81106
@@ -96,3 +121,26 @@ func parseSNSARN(snsARN string) snsData {
96121 endpoint : fmt .Sprintf ("https://sns.%v.amazonaws.com/%v/%v" , region , accountID , name ),
97122 }
98123}
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