-
Notifications
You must be signed in to change notification settings - Fork 362
/
Copy pathclean.go
136 lines (110 loc) · 3.95 KB
/
clean.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
package commands
import (
"fmt"
"github.com/activecm/rita-legacy/resources"
"github.com/globalsign/mgo/bson"
"github.com/urfave/cli"
)
func init() {
clean := cli.Command{
Name: "clean",
Aliases: []string{"clean-databases"},
Usage: "Finds and removes broken databases. Prompts before deleting each database unless --force is provided.",
Flags: []cli.Flag{
ConfigFlag,
forceFlag,
},
Action: cleanDatabase,
}
bootstrapCommands(clean)
}
// cleanDatabase finds and removes broken databases created by RITA
func cleanDatabase(c *cli.Context) error {
res := resources.InitResources(getConfigFilePath(c))
force := c.Bool("force")
ritaAnalysisCollNames := map[string]string{
res.Config.T.Structure.UniqueConnTable: "Unique Connection Analysis",
res.Config.T.Structure.HostTable: "Host Analysis",
res.Config.T.DNS.HostnamesTable: "Hostnames Analysis",
res.Config.T.DNS.ExplodedDNSTable: "ExplodedDNS Analysis",
res.Config.T.Structure.UniqueConnProxyTable: "Uconn Proxy Analysis",
res.Config.T.BeaconProxy.BeaconProxyTable: "Proxy Beacon Analysis",
res.Config.T.Beacon.BeaconTable: "Beacon Analysis",
res.Config.T.Structure.SNIConnTable: "SNI Beacon Analysis",
res.Config.T.BeaconSNI.BeaconSNITable: "SNI Connection Analysis",
res.Config.T.UserAgent.UserAgentTable: "UserAgent Analysis",
res.Config.T.Cert.CertificateTable: "Certificate Analysis",
}
session := res.DB.Session.Copy()
allDBs, err := session.DatabaseNames()
if err != nil {
fmt.Print("Clean failed: Failed to fetch database list.\n")
return cli.NewExitError(err.Error(), -1)
}
// dbsWithRitaColls maps a dataset to the list of RITA collections it contains
dbsWithRitaColls := make(map[string][]string)
for _, db := range allDBs {
existsInMeta, err := res.MetaDB.DBExists(db)
if err != nil {
fmt.Print("Clean failed: Failed to query MetaDB.\n")
return cli.NewExitError(err.Error(), -1)
}
if existsInMeta { // only select datasets without MetaDB records
continue
}
collections, err := session.DB(db).CollectionNames()
if err != nil {
fmt.Print("Clean failed: Failed to fetch collection list.\n")
return cli.NewExitError(err.Error(), -1)
}
var ritaCollsFound []string
for _, collection := range collections {
for ritaColl := range ritaAnalysisCollNames {
if collection == ritaColl {
ritaCollsFound = append(ritaCollsFound, ritaColl)
}
}
}
if len(ritaCollsFound) > 0 {
dbsWithRitaColls[db] = ritaCollsFound
}
}
if len(dbsWithRitaColls) == 0 {
fmt.Print("Clean successful: Nothing to remove.\n")
return nil
}
fmt.Print("Deleting the following broken RITA datasets:\n")
var removedDBs []string
var removedTotalSize int64
for matchingDB, matchingColls := range dbsWithRitaColls {
var dbSize struct {
DataSize int64 `bson:"dataSize"`
IndexSize int64 `bson:"indexSize"`
}
err = session.DB(matchingDB).Run(bson.D{
{Name: "dbStats", Value: 1},
{Name: "scale", Value: 1024 * 1024},
}, &dbSize)
if err != nil {
fmt.Print("Clean failed: Failed to gather size of dataset\n")
return cli.NewExitError(err.Error(), -1)
}
fmt.Printf("\t[-] %s takes up %d MB on disk\n", matchingDB, dbSize.DataSize+dbSize.IndexSize)
fmt.Printf("\t[-] %s contains results from the following analyses:\n", matchingDB)
for _, matchingColl := range matchingColls {
fmt.Printf("\t\t[-] %s\n", ritaAnalysisCollNames[matchingColl])
}
if force || confirmAction("\t [?] Confirm we'll be deleting "+matchingDB) {
err = session.DB(matchingDB).DropDatabase()
if err != nil {
fmt.Print("Clean failed: Failed to delete dataset\n")
return cli.NewExitError(err.Error(), -1)
}
removedDBs = append(removedDBs, matchingDB)
removedTotalSize += dbSize.DataSize + dbSize.IndexSize
}
fmt.Println()
}
fmt.Printf("Clean successful: Removed %d dataset(s) totalling %d MB on disk.\n", len(removedDBs), removedTotalSize)
return nil
}