diff --git a/README.md b/README.md index bc2e163..7e3e616 100644 --- a/README.md +++ b/README.md @@ -72,16 +72,18 @@ cd dist && zip deployment.zip bootstrap && cd .. ```json { "source": ["aws.securityhub"], - "detail-type": ["Security Hub Findings - Imported"] + "detail-type": ["Findings Imported V2"] } ``` Optional: Filter by severity (recommended for high-volume environments): ```json { "source": ["aws.securityhub"], - "detail-type": ["Security Hub Findings - Imported"], + "detail-type": ["Findings Imported V2"], "detail": { - "severity": ["Critical", "High"] + "findings": { + "severity": ["Critical", "High"] + } } } ``` @@ -89,11 +91,13 @@ cd dist && zip deployment.zip bootstrap && cd .. ```json { "source": ["aws.securityhub"], - "detail-type": ["Security Hub Findings - Imported"], + "detail-type": ["Findings Imported V2"], "detail": { - "metadata": { - "product": { - "name": ["GuardDuty", "Inspector"] + "findings": { + "metadata": { + "product": { + "name": ["GuardDuty", "Inspector"] + } } } } diff --git a/cmd/sample/main.go b/cmd/sample/main.go index 335ff71..a99d87c 100644 --- a/cmd/sample/main.go +++ b/cmd/sample/main.go @@ -38,14 +38,22 @@ func main() { } for i, finding := range findings { + detail := map[string]interface{}{ + "findings": []json.RawMessage{finding}, + } + detailBytes, err := json.Marshal(detail) + if err != nil { + log.Fatalf("marshal detail: %v", err) + } + evt := awsevents.CloudWatchEvent{ Version: "0", ID: fmt.Sprintf("sample-%d", i), - DetailType: "Security Hub Findings - Imported", + DetailType: "Findings Imported V2", Source: "aws.securityhub", AccountID: "123456789012", Region: "us-east-1", - Detail: finding, + Detail: detailBytes, } if err := a.Process(evt); err != nil { diff --git a/internal/app/app.go b/internal/app/app.go index a723de3..e94aee4 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -1,6 +1,7 @@ package app import ( + "encoding/json" "fmt" awsEvent "github.com/aws/aws-lambda-go/events" @@ -20,10 +21,21 @@ func New(cfg *Config) *App { } } +type EventDetail struct { + Findings []json.RawMessage `json:"findings"` +} + func (a *App) ParseEvent(e awsEvent.CloudWatchEvent) (events.SecurityHubEvent, error) { switch e.DetailType { - case "Security Hub Findings - Imported": - return events.NewSecurityHubFinding(e.Detail) + case "Findings Imported V2": + var detail EventDetail + if err := json.Unmarshal(e.Detail, &detail); err != nil { + return nil, fmt.Errorf("failed to unmarshal event detail: %w", err) + } + if len(detail.Findings) == 0 { + return nil, fmt.Errorf("no findings in event") + } + return events.NewSecurityHubFinding(detail.Findings[0]) default: return nil, fmt.Errorf("unknown cloudwatch event type: %s", e.DetailType) }