-
Notifications
You must be signed in to change notification settings - Fork 16
/
simplomon.hh
363 lines (312 loc) · 9.74 KB
/
simplomon.hh
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#pragma once
#include <mutex>
#include <regex>
#include <string>
#include "record-types.hh"
#include "sclasses.hh"
#include "notifiers.hh"
#include "sol/sol.hpp"
#include "nlohmann/json.hpp"
#include <fmt/chrono.h>
#include <fmt/ranges.h>
#include "sqlwriter.hh"
#include "peglib.h"
extern sol::state g_lua;
void initLua();
struct CheckResult
{
CheckResult() {}
CheckResult(const char* reason) : d_reasons({{"", {reason}}})
{
if(!*reason)
d_reasons.clear();
}
CheckResult(const std::string& reason) : d_reasons({{"", {reason}}})
{
if(reason.empty())
d_reasons.clear();
}
std::map<std::string,std::vector<std::string>> d_reasons;
};
extern std::vector<std::shared_ptr<Notifier>> g_notifiers;
class Checker
{
public:
Checker(sol::table& data, int minFailures = -1)
{
if(minFailures >= 0)
d_minfailures = minFailures;
d_minfailures = data.get_or("minFailures", d_minfailures);
d_failurewin = data.get_or("failureWindow", d_failurewin);
d_mute = data.get_or("mute", false);
data["mute"] = sol::lua_nil;
data["subject"] = sol::lua_nil;
data["minFailures"] = sol::lua_nil;
data["failureWindow"] = sol::lua_nil;
// bake in
// fmt::print("Baking in {} notifiers\n", g_notifiers.size());
std::optional<std::vector<std::shared_ptr<Notifier>>> spec = data["notifiers"];
if(spec) {
// fmt::print("Got {} specific notifiers\n", spec->size());
notifiers.push_back(g_notifiers[0]);
notifiers.push_back(g_notifiers[1]);
for(auto& n : *spec)
notifiers.push_back(n);
data["notifiers"] = sol::lua_nil;
}
else notifiers = g_notifiers;
// for(const auto& n : notifiers)
// fmt::print("Adding notifier {}\n", n->getNotifierName());
}
Checker(const Checker&) = delete;
virtual ~Checker() = default;
void Perform()
{
d_reasons = this->perform();
}
virtual CheckResult perform() = 0;
virtual std::string getDescription() = 0;
virtual std::string getCheckerName() = 0;
std::map<std::string, SQLiteWriter::var_t> d_attributes;
std::map<std::string, std::map<std::string, SQLiteWriter::var_t>> d_results;
int d_minfailures=1;
int d_failurewin = 120;
std::vector<std::shared_ptr<Notifier>> notifiers;
bool d_mute = false;
CheckResult d_reasons;
private:
std::mutex d_m;
};
// sets alert status if there have been more than x alerts in y seconds
struct CheckResultFilter
{
explicit CheckResultFilter(int maxseconds=3600) : d_maxseconds(maxseconds) {}
void reportResult(Checker* source, const std::string& subject, const std::string& cr, time_t t)
{
d_reports[source][subject][cr].insert(t);
}
void reportResult(Checker* source, const std::string& subject, const std::string& cr)
{
reportResult(source, subject, cr, time(nullptr));
}
std::set<std::pair<Checker*, std::string>> getFilteredResults();
std::map<Checker*, std::map<std::string, std::map<std::string, std::set<time_t>> >> d_reports;
int d_maxseconds;
};
class DNSChecker : public Checker
{
public:
DNSChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "dns"; }
std::string getDescription() override
{
return fmt::format("DNS check, server {}, qname {}, qtype {}, acceptable: {}",
d_nsip.toStringWithPort(), d_qname.toString(), toString(d_qtype), d_acceptable);
}
private:
ComboAddress d_nsip;
std::optional<ComboAddress> d_localIP;
DNSName d_qname;
DNSType d_qtype;
std::set<std::string> d_acceptable;
bool d_rd = true;
};
class RRSIGChecker : public Checker
{
public:
RRSIGChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "rrsig"; }
std::string getDescription() override
{
return fmt::format("RRSIG check, server {}, qname {}, qtype {}, minDays: {}",
d_nsip.toStringWithPort(), d_qname.toString(), toString(d_qtype), d_minDays);
}
private:
ComboAddress d_nsip;
DNSName d_qname;
DNSType d_qtype;
int d_minDays=0;
};
class DNSSOAChecker : public Checker
{
public:
DNSSOAChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "dnssoa"; }
std::string getDescription() override
{
std::vector<std::string> servers;
for(const auto& s : d_servers) servers.push_back(s.toStringWithPort());
return fmt::format("DNS SOA check, servers {}, domain {}",
servers, d_domain.toString());
}
private:
DNSName d_domain;
std::set<ComboAddress> d_servers;
};
class TCPPortClosedChecker : public Checker
{
public:
TCPPortClosedChecker(const std::set<std::string>& servers,
const std::set<int>& ports);
TCPPortClosedChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "tcpportclosed"; }
std::string getDescription() override
{
std::vector<std::string> servers;
for(const auto& s : d_servers) servers.push_back(s.toString());
return fmt::format("TCP closed check, servers {}, ports {}",
servers, d_ports);
}
private:
std::set<ComboAddress> d_servers;
std::set<int> d_ports;
};
class PINGChecker : public Checker
{
public:
PINGChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "ping"; }
std::string getDescription() override
{
std::vector<std::string> servers;
for(const auto& s : d_servers) servers.push_back(s.toString());
return fmt::format("PING check, servers {}", servers);
}
private:
std::set<ComboAddress> d_servers;
std::optional<ComboAddress> d_localIP;
double d_timeout;
size_t d_size;
bool d_dontFragment;
};
class HTTPSChecker : public Checker
{
public:
HTTPSChecker(sol::table data);
~HTTPSChecker()
{
}
CheckResult perform() override;
std::string getCheckerName() override { return "https"; }
std::string getDescription() override
{
return fmt::format("HTTPS check, URL {}, method {}",
d_url, d_method); // XX needs more
}
private:
std::string d_url;
int d_maxAgeMinutes = 0;
unsigned int d_minBytes = 0;
unsigned int d_minCertDays = 14;
std::optional<ComboAddress> d_serverIP, d_localIP4, d_localIP6;
std::vector<ComboAddress> d_dns;
std::string d_regexStr;
std::regex d_regex;
std::string d_method;
std::string d_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36";
};
class PrometheusParser
{
public:
PrometheusParser();
void parse(const std::string& cont);
typedef std::map<std::string, std::map<std::map<std::string,std::string>, double>> prom_t;
prom_t d_prom;
private:
peg::parser d_parser;
};
struct PromCheck
{
virtual ~PromCheck() = default;
virtual void doCheck(CheckResult& cr, const PrometheusParser::prom_t & prom, const std::string& id,
std::map<std::string, std::map<std::string, SQLiteWriter::var_t>>& results) = 0;
};
class PrometheusChecker : public Checker
{
public:
PrometheusChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "prometheus"; }
std::string getDescription() override
{
return fmt::format("Prometheus check, url {}",
d_url);
}
private:
std::string d_url;
PrometheusParser d_parser;
std::vector<std::unique_ptr<PromCheck>> d_checkers;
};
class HTTPRedirChecker : public Checker
{
public:
HTTPRedirChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "redir"; }
std::string getDescription() override
{
return fmt::format("HTTP(s) redir check, from {}, to{}",
d_fromhostpart+d_frompath, d_tourl);
}
private:
std::string d_fromhostpart, d_frompath, d_tourl;
};
class SMTPChecker : public Checker
{
public:
SMTPChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "smtp"; }
std::string getDescription() override
{
return fmt::format("SMTP check for {}",
d_server.toStringWithPort());
}
private:
ComboAddress d_server;
DNSName d_servername;
std::string d_from, d_to;
unsigned int d_minCertDays = 14;
};
class IMAPChecker : public Checker
{
public:
IMAPChecker(sol::table data);
CheckResult perform() override;
std::string getCheckerName() override { return "imap"; }
std::string getDescription() override
{
return fmt::format("IMAP check for {}",
d_server.toStringWithPort());
}
private:
ComboAddress d_server;
DNSName d_servername;
std::string d_user, d_password;
unsigned int d_minCertDays = 14;
};
extern std::vector<std::unique_ptr<Checker>> g_checkers;
extern std::unique_ptr<SQLiteWriter> g_sqlw;
extern std::optional<bool> g_haveIPv6;
extern int g_intervalSeconds;
extern int g_maxWorkers;
void checkLuaTable(sol::table data,
const std::set<std::string>& mandatory,
const std::set<std::string>& opt = std::set<std::string>());
void startWebService(sol::table data);
void giveToWebService(const std::set<std::pair<Checker*, std::string>>&,
const std::map<std::string, time_t>& startAlerts);
void updateWebService();
bool checkForWorkingIPv6();
std::vector<ComboAddress> DNSResolveAt(const DNSName& name, const DNSType& type,
const std::vector<ComboAddress>& servers,
std::optional<ComboAddress> local4 = std::optional<ComboAddress>(),
std::optional<ComboAddress> local6 = std::optional<ComboAddress>()
);
std::vector<ComboAddress> getResolvers();
std::string getAgeDesc(time_t then);