forked from future-architect/vuls
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuuid.go
211 lines (181 loc) · 5.51 KB
/
uuid.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package saas
import (
"bytes"
"fmt"
"os"
"reflect"
"strings"
"github.com/BurntSushi/toml"
"github.com/future-architect/vuls/config"
"github.com/future-architect/vuls/logging"
"github.com/future-architect/vuls/models"
"github.com/hashicorp/go-uuid"
"golang.org/x/xerrors"
)
// EnsureUUIDs generate a new UUID of the scan target server if UUID is not assigned yet.
// And then set the generated UUID to config.toml and scan results.
func EnsureUUIDs(servers map[string]config.ServerInfo, path string, scanResults models.ScanResults) (err error) {
needsOverwrite, err := ensure(servers, scanResults, uuid.GenerateUUID)
if err != nil {
return xerrors.Errorf("Failed to ensure UUIDs. err: %w", err)
}
if !needsOverwrite {
return
}
return writeToFile(config.Conf, path)
}
func ensure(servers map[string]config.ServerInfo, scanResults models.ScanResults, generateFunc func() (string, error)) (needsOverwrite bool, err error) {
for i, r := range scanResults {
serverInfo := servers[r.ServerName]
if serverInfo.UUIDs == nil {
serverInfo.UUIDs = map[string]string{}
}
if r.IsContainer() {
if id, found := serverInfo.UUIDs[r.ServerName]; !found {
// Scanning with the -containers-only flag, the UUID of Host may not be generated,
// so check it. If not, create a UUID of the Host and set it.
serverInfo.UUIDs[r.ServerName], err = generateFunc()
if err != nil {
return false, err
}
needsOverwrite = true
} else if _, err := uuid.ParseUUID(id); err != nil {
// if the UUID of the host is invalid, re-generate it
logging.Log.Warnf("UUID `%s` is invalid. Re-generate and overwrite", id)
serverInfo.UUIDs[r.ServerName], err = generateFunc()
if err != nil {
return false, err
}
needsOverwrite = true
}
}
name := r.ServerName
if r.IsContainer() {
name = fmt.Sprintf("%s@%s", r.Container.Name, r.ServerName)
}
if id, ok := serverInfo.UUIDs[name]; ok {
if _, err := uuid.ParseUUID(id); err == nil {
if r.IsContainer() {
scanResults[i].Container.UUID = id
scanResults[i].ServerUUID = serverInfo.UUIDs[r.ServerName]
} else {
scanResults[i].ServerUUID = id
}
// continue if the UUID has already assigned and valid
continue
}
// re-generate
logging.Log.Warnf("UUID `%s` is invalid. Re-generate and overwrite", id)
}
// Generate a new UUID and set to config and scanResult
serverUUID, err := generateFunc()
if err != nil {
return false, err
}
serverInfo.UUIDs[name] = serverUUID
servers[r.ServerName] = serverInfo
if r.IsContainer() {
scanResults[i].Container.UUID = serverUUID
scanResults[i].ServerUUID = serverInfo.UUIDs[r.ServerName]
} else {
scanResults[i].ServerUUID = serverUUID
}
needsOverwrite = true
}
return needsOverwrite, nil
}
func writeToFile(cnf config.Config, path string) error {
for name, server := range cnf.Servers {
server = cleanForTOMLEncoding(server, cnf.Default)
cnf.Servers[name] = server
}
if cnf.Default.WordPress != nil && cnf.Default.WordPress.IsZero() {
cnf.Default.WordPress = nil
}
if cnf.Default.PortScan != nil && cnf.Default.PortScan.IsZero() {
cnf.Default.PortScan = nil
}
c := struct {
Saas *config.SaasConf `toml:"saas"`
Default config.ServerInfo `toml:"default"`
Servers map[string]config.ServerInfo `toml:"servers"`
}{
Saas: &cnf.Saas,
Default: cnf.Default,
Servers: cnf.Servers,
}
// rename the current config.toml to config.toml.bak
info, err := os.Lstat(path)
if err != nil {
return xerrors.Errorf("Failed to lstat %s: %w", path, err)
}
realPath := path
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
if realPath, err = os.Readlink(path); err != nil {
return xerrors.Errorf("Failed to Read link %s: %w", path, err)
}
}
if err := os.Rename(realPath, realPath+".bak"); err != nil {
return xerrors.Errorf("Failed to rename %s: %w", path, err)
}
var buf bytes.Buffer
if err := toml.NewEncoder(&buf).Encode(c); err != nil {
return xerrors.Errorf("Failed to encode to toml: %w", err)
}
str := strings.Replace(buf.String(), "\n [", "\n\n [", -1)
str = fmt.Sprintf("%s\n\n%s",
"# See README for details: https://vuls.io/docs/en/usage-settings.html",
str)
return os.WriteFile(realPath, []byte(str), 0600)
}
func cleanForTOMLEncoding(server config.ServerInfo, def config.ServerInfo) config.ServerInfo {
if reflect.DeepEqual(server.Optional, def.Optional) {
server.Optional = nil
}
if def.User == server.User {
server.User = ""
}
if def.Host == server.Host {
server.Host = ""
}
if def.Port == server.Port {
server.Port = ""
}
if def.KeyPath == server.KeyPath {
server.KeyPath = ""
}
if reflect.DeepEqual(server.ScanMode, def.ScanMode) {
server.ScanMode = nil
}
if def.Type == server.Type {
server.Type = ""
}
if reflect.DeepEqual(server.CpeNames, def.CpeNames) {
server.CpeNames = nil
}
if def.OwaspDCXMLPath == server.OwaspDCXMLPath {
server.OwaspDCXMLPath = ""
}
if reflect.DeepEqual(server.IgnoreCves, def.IgnoreCves) {
server.IgnoreCves = nil
}
if reflect.DeepEqual(server.Enablerepo, def.Enablerepo) {
server.Enablerepo = nil
}
for k, v := range def.Optional {
if vv, ok := server.Optional[k]; ok && v == vv {
delete(server.Optional, k)
}
}
if server.WordPress != nil {
if server.WordPress.IsZero() || reflect.DeepEqual(server.WordPress, def.WordPress) {
server.WordPress = nil
}
}
if server.PortScan != nil {
if server.PortScan.IsZero() || reflect.DeepEqual(server.PortScan, def.PortScan) {
server.PortScan = nil
}
}
return server
}