-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
134 lines (113 loc) · 4.15 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package main
import (
"context"
"os"
"path"
"strings"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/CMSGov/security-hub-collector/internal/aws/client"
"github.com/CMSGov/security-hub-collector/pkg/helpers"
"github.com/CMSGov/security-hub-collector/pkg/securityhubcollector"
"github.com/CMSGov/security-hub-collector/pkg/teams"
flag "github.com/jessevdk/go-flags"
"log"
)
// Options describes the command line options available.
type Options struct {
OutputFileName string `short:"o" long:"output" required:"false" description:"File to direct output to." default:"SecurityHub-Findings.csv"`
S3Region string `short:"s" long:"s3-region" env:"AWS_REGION" required:"false" description:"AWS region to use for s3 uploads."`
SecurityHubRegions []string `short:"r" long:"sechub-regions" required:"false" default:"us-east-1" default:"us-west-2" description:"AWS regions to use for Security Hub findings."`
S3Bucket string `short:"b" long:"s3-bucket" required:"false" description:"S3 bucket to use to upload results. Optional, if not provided, results will not be uploaded to S3."`
S3Key string `short:"k" long:"s3-key" required:"false" description:"S3 bucket key, or path, to use to upload results."`
TeamMapFile string `short:"m" long:"team-map" required:"true" description:"JSON file containing team to account mappings."`
}
var options Options
// WriteFindingsToS3 - Writes the finding results file to an S3 bucket
func writeFindingsToS3() error {
s3uploader, err := client.MakeS3Uploader(options.S3Region)
if err != nil {
return err
}
// use Outfile name as the key by default
key := options.OutputFileName
// if the passed in key exists, use that
if options.S3Key != "" {
key = options.S3Key
}
// Carve up things and throw in timestamp in the key
current := time.Now()
suffix := current.Format("2006-01-02_15.04.05")
ext := path.Ext(key)
fn := strings.TrimSuffix(key, ext)
key = fn + "_" + suffix + ext
// open our local file for reading
f, err := os.Open(options.OutputFileName) //nolint
if err != nil {
return err
}
// This will automatically close the file when the function completes.
defer func() {
cerr := f.Close()
if cerr != nil {
err = helpers.CombineErrors(err, cerr)
}
}()
upParams := &s3.PutObjectInput{
Bucket: aws.String(options.S3Bucket),
Key: aws.String(key),
Body: f,
}
_, err = s3uploader.Upload(context.TODO(), upParams)
if err != nil {
return err
}
log.Printf("successfully uploaded findings to s3://%v/%v", options.S3Bucket, key)
return nil
}
// collectFindings is doing the bulk of our work here; it reads in the
// team map JSON file, builds the HubCollector object, writes headers to the output file, and processes findings
// depending on the definitions in the team map and the CLI options.
func collectFindings(secHubRegions []string) {
h := securityhubcollector.HubCollector{}
err := h.Initialize(options.OutputFileName)
if err != nil {
log.Fatalf("could not initialize HubCollector: %v", err)
}
// flush the buffer and close the file when the function completes.
defer func() {
ferr := h.FlushAndClose()
if ferr != nil {
log.Fatalf("could not flush buffer and close output file: %v", err)
}
}()
accountsToTeams, err := teams.ParseTeamMap(options.TeamMapFile)
if err != nil {
log.Fatalf("could not parse team map file: %v", err)
}
for account, teamName := range accountsToTeams {
roleArn := account.RoleARN
for _, secHubRegion := range secHubRegions {
log.Printf("getting findings for account %v in %v", account.ID, secHubRegion)
err = h.GetFindingsAndWriteToOutput(secHubRegion, teamName, account.Environment, roleArn)
if err != nil {
log.Fatalf("could not get findings for account %v in %v: %v", account.ID, secHubRegion, err)
}
}
}
}
func main() {
parser := flag.NewParser(&options, flag.Default)
_, err := parser.Parse()
if err != nil {
log.Fatalf("could not parse options: %v", err)
}
collectFindings(options.SecurityHubRegions)
if options.S3Bucket != "" {
err := writeFindingsToS3()
if err != nil {
log.Fatalf("could not upload findings to S3: %v", err)
}
}
}