/
config.go
150 lines (127 loc) · 3.72 KB
/
config.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package types
import (
"errors"
"log"
"path/filepath"
"runtime"
"strings"
"time"
)
type ServerConfig struct {
Port int `yaml:"port"`
Workdir string `yaml:"workdir"`
BinaryPath string `yaml:"binary_path"`
MetricsReportInterval time.Duration `yaml:"metrics_report_interval"`
Fuzzer FuzzerConfig `yaml:"fuzzer"`
Archive ArchiveConfig `yaml:"archive"`
}
// A FuzzerConfig is initially constructed from a config file by
// roving-srv. roving-client retrieves it from roving-srv over HTTP.
type FuzzerConfig struct {
UseBinary bool `yaml:"use_binary"`
UseDict bool `yaml:"use_dict"`
SyncInterval time.Duration `yaml:"sync_interval"`
Command []string `yaml:"command"`
MemLimitMb int `yaml:"mem_limit_mb"`
TimeoutMs int `yaml:"timeout_ms"`
}
type ArchiveConfig struct {
Type string `yaml:"type"`
Interval time.Duration `yaml:"interval"`
Disk DiskArchiveConfig `yaml:"disk"`
S3 S3ArchiveConfig `yaml:"s3"`
}
type DiskArchiveConfig struct {
DstRoot string `yaml:"dst_root"`
}
type S3ArchiveConfig struct {
RootKey string `yaml:"root_key"`
BucketName string `yaml:"bucket_name"`
AwsRegion string `yaml:"aws_region"`
IsLocal bool `yaml:"is_local"`
}
func (r *ServerConfig) ValidateConfig() error {
err := r.makePathsAbsolute()
if err != nil {
return err
}
if r.Workdir == "" {
return errors.New("Must specify workdir!")
}
if r.Fuzzer.UseBinary && len(r.Fuzzer.Command) > 0 {
return errors.New("Can only specify target_command if binary_path is not set")
}
switch r.Archive.Type {
case "disk":
archiveDst := r.Archive.Disk.DstRoot
if archiveDst == "" {
log.Fatal("Must specify dst_root if archiving to disk!")
}
case "s3":
if r.Archive.S3.RootKey == "" {
return errors.New("Must specify root_key if archiving to S3!")
}
if r.Archive.S3.BucketName == "" {
return errors.New("Must specify bucket_name if archiving to S3!")
}
if r.Archive.S3.AwsRegion == "" {
return errors.New("Must specify aws_region if archiving to S3!")
}
case "":
default:
log.Fatalf("Unrecognized archive type: %s", r.Archive.Type)
}
return nil
}
// makePathsAbsolute converts paths that were specified relative to the
// current working directory to absolute paths.
func (r *ServerConfig) makePathsAbsolute() error {
if r.Archive.Type == "disk" {
absDst, err := filepath.Abs(r.Archive.Disk.DstRoot)
if err != nil {
return err
}
r.Archive.Disk.DstRoot = absDst
}
if r.Workdir != "" {
workdir, err := filepath.Abs(r.Workdir)
if err != nil {
return err
}
r.Workdir = workdir
}
return nil
}
// A ClientConfig is loaded from a config file on the client itself,
// unlike FuzzerConfig.
type ClientConfig struct {
ServerAddress string `yaml:"server_address"`
Parallelism int `yaml:"parallelism"`
}
func (r *ClientConfig) ValidateConfig() error {
r.canonicalizeServerAddress()
r.setDefaultParallelism()
if r.ServerAddress == "" {
return errors.New("Must specify server_address")
}
return nil
}
// canonicalizeServerAddress ensures that the server address has
// an "http://" prefix. Note that roving does not currently support
// HTTPS.
func (r *ClientConfig) canonicalizeServerAddress() {
httpPrefix := "http://"
if !strings.HasPrefix(r.ServerAddress, httpPrefix) {
r.ServerAddress = httpPrefix + r.ServerAddress
}
}
// setDefaultParallelism sets the client's parallelism to
// the number of CPUs on the machine if the value from the config
// is -1.
func (r *ClientConfig) setDefaultParallelism() {
if r.Parallelism == -1 {
numCPU := runtime.NumCPU()
log.Printf("Parallelism not set - defaulting to %d (num CPUs)", numCPU)
r.Parallelism = numCPU
}
}