jetcheck 1.0.4 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/index.js +22 -4
- package/config-client.js +81 -0
- package/config-example.js +60 -6
- package/config-server.js +76 -0
- package/config-simple.js +96 -0
- package/data/server.crt +31 -0
- package/data/server.csr +27 -0
- package/data/server.key +52 -0
- package/index.js +12 -3
- package/lib/exec.js +4 -2
- package/package.json +5 -1
- package/services/builtin/cmd.js +1 -1
- package/services/builtin/email.js +28 -0
- package/services/builtin/jetcheck.js +65 -0
- package/services/builtin/ovh.js +116 -0
- package/services/builtin/ping.js +1 -1
- package/services/client.js +141 -0
- package/services/server.js +87 -0
- package/services/tests.js +31 -24
- package/services/web.js +110 -0
- package/config-wan.js +0 -21
package/bin/index.js
CHANGED
|
@@ -13,16 +13,34 @@ const configFile = path.resolve(
|
|
|
13
13
|
process.env.CONFIG || `${os.homedir()}/.jetcheck/config.js`
|
|
14
14
|
)
|
|
15
15
|
|
|
16
|
+
// load early modules
|
|
17
|
+
try {
|
|
18
|
+
const config = require(configFile)
|
|
19
|
+
if (Array.isArray(config.modules)) {
|
|
20
|
+
for (var module of config.modules) {
|
|
21
|
+
try {
|
|
22
|
+
const file = `${module}/bin/index.js`
|
|
23
|
+
const st = fs.statSync(file)
|
|
24
|
+
if (st.isFile()) {
|
|
25
|
+
// console.log(`Loading bin file from ${file}`)
|
|
26
|
+
require(file)(jetcheck, sc, configFile)
|
|
27
|
+
}
|
|
28
|
+
} catch (e) { }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
} catch (e) { }
|
|
32
|
+
|
|
33
|
+
|
|
16
34
|
sc.command('version', {
|
|
17
|
-
desc: '
|
|
35
|
+
desc: 'Get Jetcheck versions',
|
|
18
36
|
callback: async function (options) {
|
|
19
|
-
const kernel = new jetcheck({
|
|
37
|
+
const kernel = new jetcheck({})
|
|
20
38
|
console.log(`Jetcheck v${kernel.version}\n`)
|
|
21
39
|
console.log(`Program under GPL-3.0 license`)
|
|
22
40
|
console.log(`(c) ${new Date().getFullYear()} Michael VERGOZ`)
|
|
23
41
|
console.log(`And other components:`)
|
|
24
|
-
console.log(Object.keys(kernel.packages).map((key)=>{
|
|
25
|
-
return(` - ${key}=${kernel.packages[key]}`)
|
|
42
|
+
console.log(Object.keys(kernel.packages).map((key) => {
|
|
43
|
+
return (` - ${key}=${kernel.packages[key]}`)
|
|
26
44
|
}).join("\n"))
|
|
27
45
|
}
|
|
28
46
|
})
|
package/config-client.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
|
|
2
|
+
const OVH_BeysIO = {
|
|
3
|
+
name: "TC Access",
|
|
4
|
+
description: "Update for HA",
|
|
5
|
+
endpoint: 'ovh-eu',
|
|
6
|
+
appKey: "5b41bd0b749cb5e9",
|
|
7
|
+
appSecret: "9ddbece04918f75dad9e64c66041b4cd",
|
|
8
|
+
consumerKey: "fd339af5dfa29b75b734dd3fd29c2386"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const OVH_BeysIO_DNS = {
|
|
12
|
+
subDomain: "jetcheck",
|
|
13
|
+
fieldType: "A",
|
|
14
|
+
target: "9.9.9.9",
|
|
15
|
+
ttl: 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const OVH_BeysIO_TEST = {
|
|
19
|
+
subDomain: "jetcheck",
|
|
20
|
+
fieldType: "A",
|
|
21
|
+
target: "1.1.1.1",
|
|
22
|
+
ttl: 0
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = {
|
|
26
|
+
dataDir: "./data",
|
|
27
|
+
client: {
|
|
28
|
+
url: "https://127.0.0.1:7039",
|
|
29
|
+
fingerprint: "15:CC:B5:77:59:12:BD:4D:E9:40:62:49:D6:55:B7:30:96:BF:49:3A:B8:64:81:3A:89:C5:18:E9:77:A3:0C:2A",
|
|
30
|
+
token: "vSYGm1G6mNlZYElFtDkX",
|
|
31
|
+
},
|
|
32
|
+
tests: {
|
|
33
|
+
wan_netplus: {
|
|
34
|
+
// init: "DEGRADED",
|
|
35
|
+
init: "WORKING",
|
|
36
|
+
interval: 5,
|
|
37
|
+
tasks: [
|
|
38
|
+
// { type: "ping", host: "8.8.8.8", count: 3 },
|
|
39
|
+
{ type: "ping", host: "54.43.5.5", count: 3 },
|
|
40
|
+
],
|
|
41
|
+
|
|
42
|
+
// failed: [
|
|
43
|
+
// // {
|
|
44
|
+
// // type: "ovh.dns.zone.unset",
|
|
45
|
+
// // account: OVH_BeysIO,
|
|
46
|
+
// // zone: "be-ys.io",
|
|
47
|
+
// // config: OVH_BeysIO_DNS
|
|
48
|
+
// // },
|
|
49
|
+
// // {
|
|
50
|
+
// // type: "ovh.dns.zone.unset",
|
|
51
|
+
// // account: OVH_BeysIO,
|
|
52
|
+
// // zone: "be-ys.io",
|
|
53
|
+
// // config: OVH_BeysIO_TEST
|
|
54
|
+
// // },
|
|
55
|
+
// // { type: "cmd", cmd: `logger "TEST: Failing"` }
|
|
56
|
+
// ],
|
|
57
|
+
// succeed: [
|
|
58
|
+
// // {
|
|
59
|
+
// // type: "ovh.dns.zone.set",
|
|
60
|
+
// // account: OVH_BeysIO,
|
|
61
|
+
// // zone: "be-ys.io",
|
|
62
|
+
// // config: OVH_BeysIO_DNS
|
|
63
|
+
// // },
|
|
64
|
+
// // {
|
|
65
|
+
// // type: "ovh.dns.zone.set",
|
|
66
|
+
// // account: OVH_BeysIO,
|
|
67
|
+
// // zone: "be-ys.io",
|
|
68
|
+
// // config: OVH_BeysIO_DNS
|
|
69
|
+
// // },
|
|
70
|
+
// // {
|
|
71
|
+
// // type: "ovh.dns.zone.set",
|
|
72
|
+
// // account: OVH_BeysIO,
|
|
73
|
+
// // zone: "be-ys.io",
|
|
74
|
+
// // config: OVH_BeysIO_TEST
|
|
75
|
+
// // },
|
|
76
|
+
// // { type: "cmd", cmd: `logger "TEST: Succeed"` },
|
|
77
|
+
// ],
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
}
|
package/config-example.js
CHANGED
|
@@ -1,28 +1,82 @@
|
|
|
1
|
+
const OVH_test = {
|
|
2
|
+
name: "Access",
|
|
3
|
+
description: "Update for HA",
|
|
4
|
+
endpoint: 'ovh-eu',
|
|
5
|
+
appKey: "XXXX",
|
|
6
|
+
appSecret: "XXXX",
|
|
7
|
+
consumerKey: "XXXX"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const OVH_test_DNS = {
|
|
11
|
+
subDomain: "jetcheck",
|
|
12
|
+
fieldType: "A",
|
|
13
|
+
target: "9.9.9.9",
|
|
14
|
+
ttl: 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const OVH_test_TEST = {
|
|
18
|
+
subDomain: "jetcheck",
|
|
19
|
+
fieldType: "A",
|
|
20
|
+
target: "1.1.1.1",
|
|
21
|
+
ttl: 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// seo nodemailer' configuration https://www.nodemailer.com/smtp/
|
|
25
|
+
const emailDestination = {
|
|
26
|
+
host: "my.smtp.server",
|
|
27
|
+
port: 25,
|
|
28
|
+
secure: false,
|
|
29
|
+
}
|
|
30
|
+
|
|
1
31
|
module.exports = {
|
|
2
32
|
tests: {
|
|
3
33
|
myCheck: {
|
|
4
34
|
// start from degraded mode
|
|
5
|
-
init: "DEGRADED",
|
|
35
|
+
// init: "DEGRADED",
|
|
6
36
|
|
|
7
37
|
// test every 15 seconds
|
|
8
38
|
interval: 15,
|
|
9
39
|
|
|
10
40
|
// checker tasks
|
|
11
41
|
tasks: [
|
|
12
|
-
{ type: "ping", host: "8.8.8.8", count: 2 },
|
|
13
|
-
|
|
14
|
-
{ type: "http", url: "https://8.8.8.8" },
|
|
15
|
-
{ type: "http", url: "https://1.1.1.1" },
|
|
16
|
-
{ type: "http", url: "https://1.2.4.1" },
|
|
42
|
+
// { type: "ping", host: "8.8.8.8", count: 2 },
|
|
43
|
+
{ type: "ping", host: "54.43.5.5" },
|
|
44
|
+
// { type: "http", url: "https://8.8.8.8" },
|
|
45
|
+
// { type: "http", url: "https://1.1.1.1" },
|
|
46
|
+
// { type: "http", url: "https://1.2.4.1" },
|
|
17
47
|
],
|
|
18
48
|
|
|
19
49
|
// when system fails
|
|
20
50
|
failed: [
|
|
51
|
+
{
|
|
52
|
+
type: "email",
|
|
53
|
+
transporter: emailDestination,
|
|
54
|
+
content: {
|
|
55
|
+
from: "alert@tc.none.com",
|
|
56
|
+
to: "noreply@nothing.com",
|
|
57
|
+
subject: "[FAILED] Dev test",
|
|
58
|
+
text: `Hi, the 'Dev test' fails at ${new Date().toLocaleString()}`
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
{
|
|
63
|
+
type: "ovh.dns.zone.unset",
|
|
64
|
+
account: OVH_test,
|
|
65
|
+
zone: "none.com",
|
|
66
|
+
config: OVH_test_DNS
|
|
67
|
+
},
|
|
68
|
+
|
|
21
69
|
{ type: "cmd", cmd: `logger "TEST: Disconnected from HTTP"` }
|
|
22
70
|
],
|
|
23
71
|
|
|
24
72
|
// when system succeed
|
|
25
73
|
succeed: [
|
|
74
|
+
{
|
|
75
|
+
type: "ovh.dns.zone.set",
|
|
76
|
+
account: OVH_test,
|
|
77
|
+
zone: "none.com",
|
|
78
|
+
config: OVH_test_DNS
|
|
79
|
+
},
|
|
26
80
|
{ type: "cmd", cmd: `logger "TEST: Connected from HTTP"` },
|
|
27
81
|
{ type: "cmd", cmd: `logger "TEST: secondary command"` }
|
|
28
82
|
],
|
package/config-server.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
|
|
2
|
+
const OVH_BeysIO = {
|
|
3
|
+
name: "TC Access",
|
|
4
|
+
description: "Update for HA",
|
|
5
|
+
endpoint: 'ovh-eu',
|
|
6
|
+
appKey: "5b41bd0b749cb5e9",
|
|
7
|
+
appSecret: "9ddbece04918f75dad9e64c66041b4cd",
|
|
8
|
+
consumerKey: "fd339af5dfa29b75b734dd3fd29c2386"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const OVH_BeysIO_DNS = {
|
|
12
|
+
subDomain: "jetcheck",
|
|
13
|
+
fieldType: "A",
|
|
14
|
+
target: "9.9.9.9",
|
|
15
|
+
ttl: 0
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const OVH_BeysIO_TEST = {
|
|
19
|
+
subDomain: "jetcheck",
|
|
20
|
+
fieldType: "A",
|
|
21
|
+
target: "1.1.1.1",
|
|
22
|
+
ttl: 0
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const relay_test = {
|
|
26
|
+
url: "https://127.0.0.1:7039",
|
|
27
|
+
fingerprint: "jc",
|
|
28
|
+
bearer: "super",
|
|
29
|
+
key: "wan-test"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
dataDir: "./data",
|
|
34
|
+
// dataDir: __dirname+"/data",
|
|
35
|
+
server: {
|
|
36
|
+
port: 7039,
|
|
37
|
+
agentTimeout: 10,
|
|
38
|
+
apiKeys: {
|
|
39
|
+
vSYGm1G6mNlZYElFtDkX: {
|
|
40
|
+
name: "Testing API key"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
tests: {
|
|
45
|
+
wan: {
|
|
46
|
+
init: "DEGRADED",
|
|
47
|
+
// init: "WORKING",
|
|
48
|
+
interval: 5,
|
|
49
|
+
tasks: [
|
|
50
|
+
// { type: "ping", host: "8.8.8.8", count: 3 },
|
|
51
|
+
// { type: "ping", host: "54.43.5.5" },
|
|
52
|
+
{ type: "jetcheck.verify", test: "wan_netplus" },
|
|
53
|
+
],
|
|
54
|
+
|
|
55
|
+
failed: [
|
|
56
|
+
{
|
|
57
|
+
type: "ovh.dns.zone.unset",
|
|
58
|
+
account: OVH_BeysIO,
|
|
59
|
+
zone: "be-ys.io",
|
|
60
|
+
config: OVH_BeysIO_DNS
|
|
61
|
+
},
|
|
62
|
+
{ type: "cmd", cmd: `logger "TEST: Failing"` }
|
|
63
|
+
],
|
|
64
|
+
succeed: [
|
|
65
|
+
{
|
|
66
|
+
type: "ovh.dns.zone.set",
|
|
67
|
+
account: OVH_BeysIO,
|
|
68
|
+
zone: "be-ys.io",
|
|
69
|
+
config: OVH_BeysIO_DNS
|
|
70
|
+
},
|
|
71
|
+
{ type: "cmd", cmd: `logger "TEST: Succeed"` },
|
|
72
|
+
],
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
}
|
package/config-simple.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
const OVH_BeysIO = {
|
|
2
|
+
name: "TC Access",
|
|
3
|
+
description: "Update for HA",
|
|
4
|
+
endpoint: 'ovh-eu',
|
|
5
|
+
appKey: "5b41bd0b749cb5e9",
|
|
6
|
+
appSecret: "9ddbece04918f75dad9e64c66041b4cd",
|
|
7
|
+
consumerKey: "fd339af5dfa29b75b734dd3fd29c2386"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const OVH_BeysIO_DNS = {
|
|
11
|
+
subDomain: "jetcheck",
|
|
12
|
+
fieldType: "A",
|
|
13
|
+
target: "9.9.9.9",
|
|
14
|
+
ttl: 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const OVH_BeysIO_TEST = {
|
|
18
|
+
subDomain: "jetcheck",
|
|
19
|
+
fieldType: "A",
|
|
20
|
+
target: "1.1.1.1",
|
|
21
|
+
ttl: 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// seo nodemailer' configuration https://www.nodemailer.com/smtp/
|
|
25
|
+
const emailDestination = {
|
|
26
|
+
host: "smarthost.tc.beys.lo",
|
|
27
|
+
port: 25,
|
|
28
|
+
secure: false,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
tests: {
|
|
33
|
+
myCheck: {
|
|
34
|
+
// start from degraded mode
|
|
35
|
+
init: "DEGRADED",
|
|
36
|
+
|
|
37
|
+
// test every 15 seconds
|
|
38
|
+
interval: 15,
|
|
39
|
+
|
|
40
|
+
// checker tasks
|
|
41
|
+
tasks: [
|
|
42
|
+
{ type: "ping", host: "8.8.8.8", count: 2 },
|
|
43
|
+
// { type: "ping", host: "54.43.5.5" },
|
|
44
|
+
// { type: "http", url: "https://8.8.8.8" },
|
|
45
|
+
// { type: "http", url: "https://1.1.1.1" },
|
|
46
|
+
// { type: "http", url: "https://1.2.4.1" },
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
// when system fails
|
|
50
|
+
failed: [
|
|
51
|
+
{
|
|
52
|
+
type: "email",
|
|
53
|
+
transporter: emailDestination,
|
|
54
|
+
content: {
|
|
55
|
+
from: "alert@tc.be-ys.io",
|
|
56
|
+
to: "m.vergoz@protonmail.com",
|
|
57
|
+
subject: "[FAILED] Dev test",
|
|
58
|
+
text: `Hi, the 'Dev test' fails at ${new Date().toLocaleString()}`
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
{
|
|
63
|
+
type: "ovh.dns.zone.unset",
|
|
64
|
+
account: OVH_BeysIO,
|
|
65
|
+
zone: "be-ys.io",
|
|
66
|
+
config: OVH_BeysIO_DNS
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
{ type: "cmd", cmd: `logger "TEST: Disconnected from HTTP"` }
|
|
70
|
+
],
|
|
71
|
+
|
|
72
|
+
// when system succeed
|
|
73
|
+
succeed: [
|
|
74
|
+
{
|
|
75
|
+
type: "email",
|
|
76
|
+
transporter: emailDestination,
|
|
77
|
+
content: {
|
|
78
|
+
from: "alert@tc.be-ys.io",
|
|
79
|
+
to: "m.vergoz@protonmail.com",
|
|
80
|
+
subject: "[RESOLVED] Dev test",
|
|
81
|
+
text: `Hi, the 'Dev test' has been resolved at ${new Date().toLocaleString()}`
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
{
|
|
86
|
+
type: "ovh.dns.zone.set",
|
|
87
|
+
account: OVH_BeysIO,
|
|
88
|
+
zone: "be-ys.io",
|
|
89
|
+
config: OVH_BeysIO_DNS
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
{ type: "cmd", cmd: `logger "TEST: Connected from HTTP"` },
|
|
93
|
+
],
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
package/data/server.crt
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
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
|
|
30
|
+
VkIpU7bvueW/3LkMZUG1xTeQojChRFo=
|
|
31
|
+
-----END CERTIFICATE-----
|
package/data/server.csr
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE REQUEST-----
|
|
2
|
+
MIIElzCCAn8CAQAwUjELMAkGA1UEBhMCQ0gxDzANBgNVBAgMBlZhbGFpczENMAsG
|
|
3
|
+
A1UEBwwEU2lvbjERMA8GA1UECgwISmV0Y2hlY2sxEDAOBgNVBAMMB2F1dG9nZW4w
|
|
4
|
+
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDAVgbbN9dvuMwp0E5Jx/qD
|
|
5
|
+
lM7vII19TzxsQdmj0ev2OLrVPCGpabEO4MJBRlEH+uBODgNFiJB26JcdavMXZSDa
|
|
6
|
+
ytA8xBBVfYVuTdeRJVeqIoftReF2glTkRTJ68RXV6JDI5Xjlkuel66R8oKZjOq4I
|
|
7
|
+
me8VT+OO+gYTm7AdJW27M+7bc5k77lEKj9Vho2c5O021uAlbmSq/aU4tT8Vg02t8
|
|
8
|
+
e+6e4dNSKyCBeGNvAJkwPT7ZEcCVQq/OljocUkMPtLXu9OLudcALaUYKI1qGSqKd
|
|
9
|
+
fHhx6CkDbItQ/I7HE3v5YjCVXwMcTq6OLl6xnlgXWPxojvoqvgvEtYewONwCE0ct
|
|
10
|
+
SERObc0VjMAPzvT1BEcf8qwWy5Nv2IR/C1WEKeVRnhLylHKv8KMSAK4cEvzVYSvA
|
|
11
|
+
pLJUDJLAjTi/3QCBy9I13iVGn5n5VJH2VwR+T5nrQkyMwtKIOSPPh7XXZn0GC1dJ
|
|
12
|
+
ZZFTe23havJ2mka9B+CN80iOlX9SquVOZW1IVop45O39i1WtbPPP/ob8NV2vUEPj
|
|
13
|
+
YRDWqirTTx3ApvgnyireZO5JjIOcA/ZAGyzxUGBURMFA/uiESIDF8Mi42SDKuHGr
|
|
14
|
+
iRRSsMrO658eYCYPgbxY4dgkP8ef0IWaI2rYjdCpiW5G4xsg0V26r59JxiuNPd8G
|
|
15
|
+
82XFMDocO7d7iaqWJCJeMwIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBADYHxe9h
|
|
16
|
+
wLiTBbhHv17J2sjSIRNsVfhvW1fOYxKN+dp8W2V9WlbfI9k/5q72ghfnDTNMKhmr
|
|
17
|
+
AxttR4YFOLBdMMwa6rOX1MVk2k1+uYkJInnrsogY8Q8o8tM4oWZRtwaQ4P53C1Jr
|
|
18
|
+
Y+1i4UXGvHaBK7j2ijTmYyl/BWtYgNubgDXW2xLZBCGKsgpRqs3LnbzShCc5HhPt
|
|
19
|
+
vEMAEEx67zrzF/6QRHLvZiH2BFNzC9l9G/fb2oaSHkIPNjBoDuPgHcmaHtqxyuca
|
|
20
|
+
nHEeS9J6Hl7vACxmibHt8r01Hm6xJsMsMFMSLR51kdwK9t125PUdRgw7K23wlATJ
|
|
21
|
+
n2OhsdoTwTn/45LEe3PjM9vfhCQNOjm0Ocmy4oDoHpyoPo26aSKGzVsD9f1VLcBV
|
|
22
|
+
+O4gJ9M87wBv9iZXexec2ABj7bWpUVO90P438gc3WHJEpbT3Js+9SctowjchH8bg
|
|
23
|
+
069EnwFOYLIvLABz6YCnRBQuuORkqbus6cNYd6rOzeVt8swVNk7ecjiCl/o9c68J
|
|
24
|
+
/9Gt58pA5jDwMbl3ET2dT0Wg/MW2KCLGrbmSozvy3eJwSGqC37pz7gUyINVsq+oT
|
|
25
|
+
f2JRLgxBgLpvSRU5/q4tIBSaatJyKHJ6m8JbprsZbAcmwBecADwNWl2KGoyF9zbq
|
|
26
|
+
A8x3KfV1irq9X0jJq/OT09j9eRgIiRoL/39l
|
|
27
|
+
-----END CERTIFICATE REQUEST-----
|
package/data/server.key
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
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
|
|
51
|
+
0RkOot+IajgpOwLEVzjIA6nVJ++T6g==
|
|
52
|
+
-----END PRIVATE KEY-----
|
package/index.js
CHANGED
|
@@ -25,8 +25,6 @@ class jetcheck {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
async start(overwrite) {
|
|
28
|
-
|
|
29
|
-
|
|
30
28
|
// load configuration
|
|
31
29
|
if (this.options.configFile) {
|
|
32
30
|
this.configFile = path.resolve(process.cwd(), this.options.configFile);
|
|
@@ -40,6 +38,14 @@ class jetcheck {
|
|
|
40
38
|
else
|
|
41
39
|
this.config = {}
|
|
42
40
|
|
|
41
|
+
// rewrite data dir
|
|
42
|
+
if (!this.config.dataDir) {
|
|
43
|
+
this.config.dataDir = path.dirname(this.configFile)
|
|
44
|
+
console.log(`Defaulting dataDir to ${this.config.dataDir}`)
|
|
45
|
+
}
|
|
46
|
+
else
|
|
47
|
+
console.log(`Data dir is set to ${this.config.dataDir}`)
|
|
48
|
+
|
|
43
49
|
// overwrite feature
|
|
44
50
|
if (overwrite)
|
|
45
51
|
this.config = { ...this.config, ...overwrite }
|
|
@@ -48,9 +54,12 @@ class jetcheck {
|
|
|
48
54
|
this.config.modules = []
|
|
49
55
|
|
|
50
56
|
// load basic services
|
|
57
|
+
await (require("./services/web"))(this)
|
|
58
|
+
await (require("./services/server"))(this)
|
|
59
|
+
await (require("./services/client"))(this)
|
|
51
60
|
await (require("./services/tests"))(this)
|
|
52
61
|
|
|
53
|
-
// load modules
|
|
62
|
+
// late load modules
|
|
54
63
|
if (this.config.modules) {
|
|
55
64
|
for (var module of this.config.modules) {
|
|
56
65
|
await require(module)(this)
|
package/lib/exec.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
const { spawn } = require('child_process');
|
|
2
2
|
|
|
3
|
-
async function detachedExec(cmd, detached = true) {
|
|
3
|
+
async function detachedExec(cmd, detached = true, cwd) {
|
|
4
|
+
// console.log("CMD: "+cmd)
|
|
4
5
|
return new Promise((resolve) => {
|
|
5
6
|
// Split the command into the executable and its arguments
|
|
6
7
|
const [command, ...args] = cmd.split(' ')
|
|
7
8
|
|
|
8
9
|
// Launch the detached process
|
|
9
10
|
const child = spawn(command, args, {
|
|
11
|
+
cwd,
|
|
10
12
|
detached, // Detach the child process from the parent
|
|
11
|
-
stdio: ['
|
|
13
|
+
stdio: ['pipe', 'pipe', 'pipe'], // Ignore stdin and stderr, capture stdout
|
|
12
14
|
})
|
|
13
15
|
|
|
14
16
|
let stdout = ''
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jetcheck",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Javascript based Network & System checker",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
"license": "GPL-3.0",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"axios": "^1.7.9",
|
|
17
|
+
"body-parser": "^1.20.3",
|
|
17
18
|
"ejs": "^3.1.10",
|
|
19
|
+
"express": "^4.21.2",
|
|
18
20
|
"mkdirp": "^3.0.1",
|
|
21
|
+
"nodemailer": "^6.9.16",
|
|
22
|
+
"ovh": "^2.0.3",
|
|
19
23
|
"subcommander": "^1.0.0"
|
|
20
24
|
},
|
|
21
25
|
"devDependencies": {
|
package/services/builtin/cmd.js
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const NodeMailer = require("nodemailer")
|
|
2
|
+
|
|
3
|
+
async function sender(options) {
|
|
4
|
+
console.log(options)
|
|
5
|
+
const ret = {}
|
|
6
|
+
try {
|
|
7
|
+
const transporter = NodeMailer.createTransport(options.transporter);
|
|
8
|
+
await transporter.sendMail(options.content);
|
|
9
|
+
ret.status = "sent"
|
|
10
|
+
} catch (err) {
|
|
11
|
+
ret.status = "error"
|
|
12
|
+
ret.error = err.response || err.message
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
console.log(`Sending to=${options.content.to} title=${options.content.subject} status=${ret.status} error=${ret.error}`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = async function (kernel) {
|
|
19
|
+
kernel.tests.plugins.email = {
|
|
20
|
+
toString: function (options) {
|
|
21
|
+
return (`email(${options.content?.to})`)
|
|
22
|
+
},
|
|
23
|
+
trigger: async function (task, state) {
|
|
24
|
+
await sender(task)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
console.log("Loading Email plugin")
|
|
28
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module.exports = async function (kernel) {
|
|
6
|
+
kernel.tests.jetcheck = {
|
|
7
|
+
ctrls: {}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// kernel.tests.plugins['jetcheck.send'] = {
|
|
11
|
+
// toString: function (options) {
|
|
12
|
+
// return (`jetcheck.send(${options.url})`)
|
|
13
|
+
// },
|
|
14
|
+
// trigger: async function (task, state) {
|
|
15
|
+
// if (!kernel.tests.jetcheck.ctrls[task.account.appKey])
|
|
16
|
+
// kernel.tests.jetcheck.ctrls[task.account.appKey] = new asyncJetcheckAPI(task.account)
|
|
17
|
+
|
|
18
|
+
// const ctrl = kernel.tests.jetcheck.ctrls[task.account.appKey]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
// }
|
|
22
|
+
// }
|
|
23
|
+
|
|
24
|
+
kernel.tests.plugins['jetcheck.verify'] = {
|
|
25
|
+
toString: function (options) {
|
|
26
|
+
return (`jetcheck.verify(${options.test})`)
|
|
27
|
+
},
|
|
28
|
+
run: async function (options, task, state) {
|
|
29
|
+
|
|
30
|
+
if (!kernel.server.hosts)
|
|
31
|
+
throw Error("No host connected yet")
|
|
32
|
+
|
|
33
|
+
const found = []
|
|
34
|
+
for (var agentName in kernel.server.hosts) {
|
|
35
|
+
const agent = kernel.server.hosts[agentName]
|
|
36
|
+
for (var test of agent.tests) {
|
|
37
|
+
if (test.name === options.test)
|
|
38
|
+
found.push({ agent: agentName, ...test })
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (found.length === 0)
|
|
43
|
+
throw Error(`No test found under ${options.test}`)
|
|
44
|
+
|
|
45
|
+
if (found.length === 0)
|
|
46
|
+
throw Error(`No task found in test "${options.test}" from agent "${found.agent}"`)
|
|
47
|
+
|
|
48
|
+
const balance = {
|
|
49
|
+
s: 0,
|
|
50
|
+
f: 0
|
|
51
|
+
}
|
|
52
|
+
for (var test of found) {
|
|
53
|
+
balance.s += test.lastSucceed
|
|
54
|
+
balance.f += test.lastFailed
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if(balance.s === 0 && balance.f > 0)
|
|
58
|
+
return(`test failed s=0 and f>0`)
|
|
59
|
+
|
|
60
|
+
return(null)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log("Loading Jetcheck plugin")
|
|
65
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const axios = require('axios')
|
|
2
|
+
const ovh = require('ovh')
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class asyncOVH {
|
|
6
|
+
constructor(account) {
|
|
7
|
+
this.account = account
|
|
8
|
+
this.handler = ovh(account)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async get(rcs) {
|
|
12
|
+
console.log(`OVH-${this.account.appKey}: GET ${rcs}`)
|
|
13
|
+
return (new Promise((accept) => {
|
|
14
|
+
this.handler.request('GET', rcs, function (err, data) {
|
|
15
|
+
accept({ err, data })
|
|
16
|
+
})
|
|
17
|
+
}))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async post(rcs, data) {
|
|
21
|
+
console.log(`OVH-${this.account.appKey}: POST ${rcs}`)
|
|
22
|
+
return (new Promise((accept) => {
|
|
23
|
+
this.handler.request('POST', rcs, data, function (err, data) {
|
|
24
|
+
accept({ err, data })
|
|
25
|
+
})
|
|
26
|
+
}))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async del(rcs) {
|
|
30
|
+
console.log(`OVH-${this.account.appKey}: DELETE ${rcs}`)
|
|
31
|
+
return (new Promise((accept) => {
|
|
32
|
+
this.handler.request('DELETE', rcs, function (err, data) {
|
|
33
|
+
accept({ err, data })
|
|
34
|
+
})
|
|
35
|
+
}))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = async function (kernel) {
|
|
40
|
+
kernel.tests.ovh = {
|
|
41
|
+
ctrls: {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
kernel.tests.plugins['ovh.dns.zone.set'] = {
|
|
45
|
+
toString: function (options) {
|
|
46
|
+
return (`ovh.dns.zone.set(${options.host})`)
|
|
47
|
+
},
|
|
48
|
+
trigger: async function (task, state) {
|
|
49
|
+
if (!kernel.tests.ovh.ctrls[task.account.appKey])
|
|
50
|
+
kernel.tests.ovh.ctrls[task.account.appKey] = new asyncOVH(task.account)
|
|
51
|
+
|
|
52
|
+
const ctrl = kernel.tests.ovh.ctrls[task.account.appKey]
|
|
53
|
+
|
|
54
|
+
var found = null
|
|
55
|
+
const list = await ctrl.get(`/domain/zone/${task.zone}/record?subDomain=${task.config.subDomain || ""}`)
|
|
56
|
+
if (Array.isArray(list)) {
|
|
57
|
+
for (var item of list.data) {
|
|
58
|
+
const info = await ctrl.get(`/domain/zone/be-ys.io/record/${item}`)
|
|
59
|
+
|
|
60
|
+
if (task.config.subDomain && info.data.subDomain !== task.config.subDomain)
|
|
61
|
+
continue
|
|
62
|
+
if (task.config.fieldType && info.data.fieldType !== task.config.fieldType)
|
|
63
|
+
continue
|
|
64
|
+
if (task.config.target && info.data.target !== task.config.target)
|
|
65
|
+
continue
|
|
66
|
+
found = info
|
|
67
|
+
break
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!found) {
|
|
72
|
+
console.log(`[${state.name}] OVH DNS Entry "${task.config.subDomain}" set in zone "${task.zone}"`)
|
|
73
|
+
await ctrl.post(`/domain/zone/be-ys.io/record`, task.config)
|
|
74
|
+
await ctrl.post(`/domain/zone/${task.zone}/refresh`)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
kernel.tests.plugins['ovh.dns.zone.unset'] = {
|
|
80
|
+
toString: function (options) {
|
|
81
|
+
return (`ovh.dns.zone.unset(${options.host})`)
|
|
82
|
+
},
|
|
83
|
+
trigger: async function (task, state) {
|
|
84
|
+
if (!kernel.tests.ovh.ctrls[task.account.appKey])
|
|
85
|
+
kernel.tests.ovh.ctrls[task.account.appKey] = new asyncOVH(task.account)
|
|
86
|
+
|
|
87
|
+
const ctrl = kernel.tests.ovh.ctrls[task.account.appKey]
|
|
88
|
+
|
|
89
|
+
var found = null
|
|
90
|
+
const list = await ctrl.get(`/domain/zone/${task.zone}/record`)
|
|
91
|
+
if (Array.isArray(list)) {
|
|
92
|
+
for (var item of list.data) {
|
|
93
|
+
const info = await ctrl.get(`/domain/zone/${task.zone}/record/${item}`)
|
|
94
|
+
|
|
95
|
+
if (task.config.subDomain && info.data.subDomain !== task.config.subDomain)
|
|
96
|
+
continue
|
|
97
|
+
if (task.config.fieldType && info.data.fieldType !== task.config.fieldType)
|
|
98
|
+
continue
|
|
99
|
+
if (task.config.target && info.data.target !== task.config.target)
|
|
100
|
+
continue
|
|
101
|
+
found = info.data
|
|
102
|
+
break
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (found) {
|
|
107
|
+
console.log(`[${state.name}] OVH DNS Entry "${task.config.subDomain}" unset from zone "${task.zone}"`)
|
|
108
|
+
console.log(`/domain/zone/${task.zone}/record/${found.id}`)
|
|
109
|
+
await ctrl.del(`/domain/zone/${task.zone}/record/${found.id}`)
|
|
110
|
+
await ctrl.post(`/domain/zone/${task.zone}/refresh`)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
console.log("Loading PING plugin")
|
|
116
|
+
}
|
package/services/builtin/ping.js
CHANGED
|
@@ -6,7 +6,7 @@ module.exports = async function (kernel) {
|
|
|
6
6
|
return (`ping(${options.host})`)
|
|
7
7
|
},
|
|
8
8
|
run: async function (options, task, state) {
|
|
9
|
-
const count = options.count ? options.count :
|
|
9
|
+
const count = options.count ? options.count : 3
|
|
10
10
|
const ret = await kernel.lib.exec(`ping -c ${count} ${options.host}`)
|
|
11
11
|
if(ret.error > 0)
|
|
12
12
|
return("Host down")
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const https = require('https')
|
|
3
|
+
const crypto = require('crypto')
|
|
4
|
+
const os = require('os')
|
|
5
|
+
|
|
6
|
+
class JetcheckAPI {
|
|
7
|
+
constructor(kernel, account) {
|
|
8
|
+
this.kernel = kernel
|
|
9
|
+
this.account = account;
|
|
10
|
+
this.endpoint = "/api/v1"
|
|
11
|
+
|
|
12
|
+
// Initializing Axios instance with base configuration
|
|
13
|
+
this.handler = axios.create({
|
|
14
|
+
baseURL: account.url, // Replace with the base URL of the API
|
|
15
|
+
headers: {
|
|
16
|
+
'Authorization': `${account.token}`, // Example of token-based authentication
|
|
17
|
+
'User-Agent': `Jetcheck client v${this.kernel.version}`, // Add appKey in headers
|
|
18
|
+
},
|
|
19
|
+
timeout: account.timeout || 2000, // Default timeout of 5 seconds
|
|
20
|
+
validateStatus: () => true,
|
|
21
|
+
httpsAgent: new https.Agent({
|
|
22
|
+
rejectUnauthorized: false,
|
|
23
|
+
}).on('keylog', (line, tlsSocket) => {
|
|
24
|
+
const cert = tlsSocket.getPeerCertificate(false)
|
|
25
|
+
if (!cert || !cert.fingerprint256)
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
if (this.account.fingerprint !== cert.fingerprint256) {
|
|
29
|
+
console.log(`Bad fingerprint on certificate ${this.account.url} local=${this.account.fingerprint} remote=${cert.fingerprint256}`)
|
|
30
|
+
tlsSocket.destroy()
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async get(rcs) {
|
|
38
|
+
// console.log(`GET ${this.account.url}${this.endpoint}${rcs}`);
|
|
39
|
+
try {
|
|
40
|
+
const response = await this.handler.get(`${this.endpoint}${rcs}`);
|
|
41
|
+
return { err: null, data: response.data };
|
|
42
|
+
} catch (err) {
|
|
43
|
+
return { err: err.message, data: null };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async post(rcs, data) {
|
|
48
|
+
// console.log(`POST ${this.account.url}${this.endpoint}${rcs}`);
|
|
49
|
+
try {
|
|
50
|
+
const response = await this.handler.post(`${this.endpoint}${rcs}`, data);
|
|
51
|
+
return { err: null, data: response.data };
|
|
52
|
+
} catch (err) {
|
|
53
|
+
return { err: err.message, data: null };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = async function (kernel) {
|
|
59
|
+
if (kernel.options.headless === true)
|
|
60
|
+
return
|
|
61
|
+
if (!kernel.config.client)
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
console.log("Loading client module")
|
|
65
|
+
|
|
66
|
+
kernel.client = {
|
|
67
|
+
list: []
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
kernel.client.get = async function (rcs, cb) {
|
|
71
|
+
const ret = []
|
|
72
|
+
for (var server of kernel.client.list) {
|
|
73
|
+
const sret = await server.get(rcs)
|
|
74
|
+
if (cb)
|
|
75
|
+
await cb(sret)
|
|
76
|
+
ret.push(sret)
|
|
77
|
+
}
|
|
78
|
+
return (ret)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
kernel.client.post = async function (rcs, data, cb) {
|
|
82
|
+
const ret = []
|
|
83
|
+
for (var server of kernel.client.list) {
|
|
84
|
+
const sret = await server.post(rcs, data)
|
|
85
|
+
if (cb)
|
|
86
|
+
await cb(sret)
|
|
87
|
+
ret.push(sret)
|
|
88
|
+
}
|
|
89
|
+
return (ret)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function load(config) {
|
|
93
|
+
console.log(`Loading Jetcheck client ${config.url}`)
|
|
94
|
+
kernel.client.list.push(new JetcheckAPI(kernel, config))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (Array.isArray(kernel.config.client)) {
|
|
98
|
+
for (var config of kernel.config.client)
|
|
99
|
+
load(config)
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
load(kernel.config.client)
|
|
103
|
+
|
|
104
|
+
// send host heartbeat
|
|
105
|
+
async function hostHeartbeat() {
|
|
106
|
+
const info = os.hostname()
|
|
107
|
+
await kernel.client.post("/agent/heartbeat", {
|
|
108
|
+
agent: os.hostname(),
|
|
109
|
+
type: "jetcheck",
|
|
110
|
+
version: kernel.version,
|
|
111
|
+
})
|
|
112
|
+
setTimeout(hostHeartbeat, 5000)
|
|
113
|
+
}
|
|
114
|
+
setTimeout(hostHeartbeat, 100)
|
|
115
|
+
|
|
116
|
+
// send host state
|
|
117
|
+
async function hostState() {
|
|
118
|
+
const payload = []
|
|
119
|
+
|
|
120
|
+
for(var testName in kernel.tests.states) {
|
|
121
|
+
const ptr = kernel.tests.states[testName]
|
|
122
|
+
payload.push({
|
|
123
|
+
name: testName,
|
|
124
|
+
status: ptr.status,
|
|
125
|
+
mode: ptr.mode,
|
|
126
|
+
startTime: ptr.startTime,
|
|
127
|
+
lastTime: ptr.lastTime,
|
|
128
|
+
original: ptr.original.length,
|
|
129
|
+
lastSucceed: ptr.lastSucceed.length,
|
|
130
|
+
lastFailed: ptr.lastFailed.length,
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const r = await kernel.client.post("/agent/states", {
|
|
135
|
+
agent: os.hostname(),
|
|
136
|
+
tests: payload
|
|
137
|
+
})
|
|
138
|
+
setTimeout(hostState, 1000)
|
|
139
|
+
}
|
|
140
|
+
setTimeout(hostState, 1500)
|
|
141
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
async function init(kernel) {
|
|
5
|
+
if (kernel.options.headless === true)
|
|
6
|
+
return
|
|
7
|
+
if (!kernel.config.server)
|
|
8
|
+
return
|
|
9
|
+
|
|
10
|
+
kernel.server = {
|
|
11
|
+
hosts: {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (!kernel.config.server.apiKeys)
|
|
15
|
+
kernel.config.server.apiKeys = {}
|
|
16
|
+
|
|
17
|
+
kernel.web.filters.isServerAPI = (req, res, next) => {
|
|
18
|
+
if (!kernel.config.server.apiKeys[req.headers.authorization])
|
|
19
|
+
return (res.error("Invalid credential", null, true))
|
|
20
|
+
|
|
21
|
+
req.apiKey = {
|
|
22
|
+
...kernel.config.server.apiKeys[req.headers.authorization],
|
|
23
|
+
key: req.headers.authorization
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
next()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function pruneHosts() {
|
|
30
|
+
const toDel = []
|
|
31
|
+
for (var agent in kernel.server.hosts) {
|
|
32
|
+
const data = kernel.server.hosts[agent]
|
|
33
|
+
const timeout = kernel.config.server.agentTimeout ? kernel.config.server.agentTimeout * 1000 : 5000
|
|
34
|
+
if (Date.now() - data.lastBeat > timeout)
|
|
35
|
+
toDel.push(agent)
|
|
36
|
+
}
|
|
37
|
+
for (var item of toDel)
|
|
38
|
+
delete kernel.server.hosts[item]
|
|
39
|
+
setTimeout(pruneHosts, 1000)
|
|
40
|
+
}
|
|
41
|
+
setTimeout(pruneHosts, 1000)
|
|
42
|
+
|
|
43
|
+
kernel.web.post(
|
|
44
|
+
"/api/v1/agent/heartbeat",
|
|
45
|
+
kernel.web.filters.isServerAPI,
|
|
46
|
+
kernel.web.filters.jsonParser,
|
|
47
|
+
async (req, res) => {
|
|
48
|
+
if (!kernel.server.hosts[req.body.agent])
|
|
49
|
+
kernel.server.hosts[req.body.agent] = {}
|
|
50
|
+
const host = kernel.server.hosts[req.body.agent]
|
|
51
|
+
host.agent = req.body.agent
|
|
52
|
+
host.type = req.body.type
|
|
53
|
+
host.version = req.body.version
|
|
54
|
+
host.lastBeat = Date.now()
|
|
55
|
+
res.success({})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
kernel.web.post(
|
|
59
|
+
"/api/v1/agent/states",
|
|
60
|
+
kernel.web.filters.isServerAPI,
|
|
61
|
+
kernel.web.filters.jsonParser,
|
|
62
|
+
async (req, res) => {
|
|
63
|
+
if (!kernel.server.hosts[req.body.agent])
|
|
64
|
+
kernel.server.hosts[req.body.agent] = {}
|
|
65
|
+
const host = kernel.server.hosts[req.body.agent]
|
|
66
|
+
host.agent = req.body.agent
|
|
67
|
+
host.lastBeat = Date.now()
|
|
68
|
+
host.tests = []
|
|
69
|
+
|
|
70
|
+
if (Array.isArray(req.body.tests))
|
|
71
|
+
for (var test of req.body.tests)
|
|
72
|
+
host.tests.push({
|
|
73
|
+
name: test.name,
|
|
74
|
+
status: test.status,
|
|
75
|
+
mode: test.mode,
|
|
76
|
+
startTime: test.startTime,
|
|
77
|
+
lastTime: test.lastTime,
|
|
78
|
+
original: test.original,
|
|
79
|
+
lastSucceed: test.lastSucceed,
|
|
80
|
+
lastFailed: test.lastFailed,
|
|
81
|
+
})
|
|
82
|
+
res.success({})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = init;
|
package/services/tests.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const path = require("path")
|
|
2
|
-
const { start } = require("repl")
|
|
3
2
|
|
|
4
3
|
module.exports = async function (kernel) {
|
|
5
4
|
kernel.tests = {
|
|
@@ -10,17 +9,17 @@ module.exports = async function (kernel) {
|
|
|
10
9
|
// tester
|
|
11
10
|
kernel.config.modules.push(__dirname + "/builtin/http.js")
|
|
12
11
|
kernel.config.modules.push(__dirname + "/builtin/ping.js")
|
|
12
|
+
kernel.config.modules.push(__dirname + "/builtin/jetcheck.js")
|
|
13
13
|
|
|
14
14
|
// triggers
|
|
15
15
|
kernel.config.modules.push(__dirname + "/builtin/cmd.js")
|
|
16
|
+
kernel.config.modules.push(__dirname + "/builtin/email.js")
|
|
17
|
+
kernel.config.modules.push(__dirname + "/builtin/ovh.js")
|
|
16
18
|
|
|
17
19
|
kernel.events.on("kernel.init", async function () {
|
|
18
|
-
|
|
19
20
|
if (kernel.options.headless === true)
|
|
20
21
|
return
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
23
|
// prepare initial states
|
|
25
24
|
for (var testName in kernel.config.tests) {
|
|
26
25
|
const test = kernel.config.tests[testName]
|
|
@@ -30,6 +29,7 @@ module.exports = async function (kernel) {
|
|
|
30
29
|
test.interval = test.interval * 1000
|
|
31
30
|
|
|
32
31
|
kernel.tests.states[testName] = {
|
|
32
|
+
name: testName,
|
|
33
33
|
status: "INIT",
|
|
34
34
|
mode: "INIT",
|
|
35
35
|
startTime: Date.now(),
|
|
@@ -42,9 +42,9 @@ module.exports = async function (kernel) {
|
|
|
42
42
|
}
|
|
43
43
|
const state = kernel.tests.states[testName]
|
|
44
44
|
|
|
45
|
-
if(test.init
|
|
45
|
+
if (test.init?.toLowerCase() === "working")
|
|
46
46
|
state.mode = "WORKING"
|
|
47
|
-
else if(test.init
|
|
47
|
+
else if (test.init?.toLowerCase() === "degraded")
|
|
48
48
|
state.mode = "DEGRADED"
|
|
49
49
|
else
|
|
50
50
|
state.mode = "WORKING"
|
|
@@ -90,37 +90,39 @@ module.exports = async function (kernel) {
|
|
|
90
90
|
async function pop() {
|
|
91
91
|
const task = state.current.pop()
|
|
92
92
|
if (!task) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
if(state.succeed.length === 0 && state.failed.length === 0) {
|
|
94
|
+
// do nothing
|
|
95
|
+
}
|
|
96
|
+
else if (state.succeed.length === 0) {
|
|
97
|
+
if (state.mode === "WORKING") {
|
|
96
98
|
console.log(`System "${testName}" is degraded`)
|
|
97
|
-
if(test.failed) {
|
|
98
|
-
for(var item of test.failed) {
|
|
99
|
+
if (test.failed) {
|
|
100
|
+
for (var item of test.failed) {
|
|
99
101
|
const module = kernel.tests.plugins[item.type]
|
|
100
|
-
if(module && module.trigger)
|
|
102
|
+
if (module && module.trigger)
|
|
101
103
|
await module.trigger(item, state)
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
|
-
}
|
|
106
|
+
}
|
|
105
107
|
state.mode = "DEGRADED"
|
|
106
108
|
}
|
|
107
109
|
else {
|
|
108
|
-
if(state.mode === "DEGRADED") {
|
|
110
|
+
if (state.mode === "DEGRADED") {
|
|
109
111
|
console.log(`System ${testName} is restored`)
|
|
110
|
-
if(test.succeed) {
|
|
111
|
-
for(var item of test.succeed) {
|
|
112
|
+
if (test.succeed) {
|
|
113
|
+
for (var item of test.succeed) {
|
|
112
114
|
const module = kernel.tests.plugins[item.type]
|
|
113
|
-
if(module && module.trigger)
|
|
115
|
+
if (module && module.trigger)
|
|
114
116
|
await module.trigger(item, state)
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
|
-
}
|
|
119
|
+
}
|
|
118
120
|
state.mode = "WORKING"
|
|
119
121
|
}
|
|
120
122
|
|
|
121
123
|
state.lastSucceed = state.succeed
|
|
122
124
|
state.lastFailed = state.failed
|
|
123
|
-
|
|
125
|
+
|
|
124
126
|
state.startTime = Date.now()
|
|
125
127
|
state.lastTime = Date.now()
|
|
126
128
|
state.status = "PENDING"
|
|
@@ -129,11 +131,16 @@ module.exports = async function (kernel) {
|
|
|
129
131
|
|
|
130
132
|
const module = kernel.tests.plugins[task.type]
|
|
131
133
|
// console.log(`Executing ${testName} > ${module.toString(task)}`)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
try {
|
|
135
|
+
const error = await module.run(task, test, state)
|
|
136
|
+
if (!error)
|
|
137
|
+
state.succeed.push(task)
|
|
138
|
+
else
|
|
139
|
+
state.failed.push({ ...task, error })
|
|
140
|
+
} catch(e) {
|
|
141
|
+
console.log(`Test "${testName}" failed: ${e.message}`)
|
|
142
|
+
}
|
|
143
|
+
|
|
137
144
|
|
|
138
145
|
setTimeout(pop, 10)
|
|
139
146
|
}
|
package/services/web.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const crypto = require('crypto')
|
|
4
|
+
const https = require('https')
|
|
5
|
+
|
|
6
|
+
const express = require('express')
|
|
7
|
+
const bodyParser = require('body-parser')
|
|
8
|
+
|
|
9
|
+
function getCertificateFingerprint(certString) {
|
|
10
|
+
const baseString = certString.match(/-----BEGIN CERTIFICATE-----\s*([\s\S]+?)\s*-----END CERTIFICATE-----/i);
|
|
11
|
+
const rawCert = Buffer.from(baseString[1], "base64");
|
|
12
|
+
const sha256sum = crypto.createHash("sha256").update(rawCert).digest("hex");
|
|
13
|
+
return sha256sum.toUpperCase().replace(/(.{2})(?!$)/g, "$1:");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async function init(kernel) {
|
|
17
|
+
// load express application
|
|
18
|
+
kernel.web = express()
|
|
19
|
+
|
|
20
|
+
kernel.web.filters = {
|
|
21
|
+
jsonParser: bodyParser.json({ limit: '10mb' }),
|
|
22
|
+
postURLParser: bodyParser.urlencoded({ limit: '10mb', extended: true }),
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// log all calls
|
|
26
|
+
kernel.web.use((req, res, next) => {
|
|
27
|
+
// console.log(`${req.method} ${req.url} ${req.socket.remoteAddress}`, ['web'])
|
|
28
|
+
next()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Control CORS
|
|
32
|
+
kernel.web.use((req, res, next) => {
|
|
33
|
+
res.success = (data) => {
|
|
34
|
+
res.json({ error: null, data })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
res.error = (error, fields, login) => {
|
|
38
|
+
res.json({ error, fields, login })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
res.setHeader("Access-Control-Allow-Headers", 'Content-Type, Content-Length, Authorization')
|
|
42
|
+
res.setHeader("Access-Control-Allow-Methods", 'GET, POST')
|
|
43
|
+
res.setHeader("Access-Control-Allow-Origin", '*')
|
|
44
|
+
next()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
kernel.web.get(
|
|
48
|
+
"/api/v1/version",
|
|
49
|
+
async (req, res) => {
|
|
50
|
+
res.success({
|
|
51
|
+
software: kernel.version
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
if (kernel.options.headless !== true) {
|
|
56
|
+
if (!kernel.config.server)
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
console.log("Loading Web service")
|
|
60
|
+
const port = kernel.config?.server?.port || 7039
|
|
61
|
+
|
|
62
|
+
const keyFile = `${kernel.config.dataDir}/server.key`
|
|
63
|
+
const ctrFile = `${kernel.config.dataDir}/server.crt`
|
|
64
|
+
const csrFile = `${kernel.config.dataDir}/server.csr`
|
|
65
|
+
var autoCreate = false
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
fs.statSync(keyFile)
|
|
69
|
+
} catch (e) { autoCreate = true }
|
|
70
|
+
try {
|
|
71
|
+
fs.statSync(ctrFile)
|
|
72
|
+
} catch (e) { autoCreate = true }
|
|
73
|
+
|
|
74
|
+
if (autoCreate === true) {
|
|
75
|
+
console.log("Building server Self-Signed")
|
|
76
|
+
console.log(`Generating 4k RSA Key in ${keyFile}`)
|
|
77
|
+
await kernel.lib.exec(
|
|
78
|
+
`openssl genrsa -out ./server.key 4096`,
|
|
79
|
+
false, kernel.config.dataDir)
|
|
80
|
+
console.log(`Building CSR in ${csrFile}`)
|
|
81
|
+
await kernel.lib.exec(
|
|
82
|
+
`openssl req -new -key ./server.key -out ./server.csr -subj /C=CH/ST=Valais/L=Sion/O=Jetcheck/CN=autogen`,
|
|
83
|
+
false, kernel.config.dataDir
|
|
84
|
+
)
|
|
85
|
+
console.log(`Self Signing ${ctrFile}`)
|
|
86
|
+
await kernel.lib.exec(
|
|
87
|
+
`openssl x509 -req -days 365 -in ./server.csr -signkey ./server.key -out ./server.crt`,
|
|
88
|
+
false, kernel.config.dataDir
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log("Loading server certificate")
|
|
93
|
+
const privateKey = fs.readFileSync(keyFile).toString();
|
|
94
|
+
const certificate = fs.readFileSync(ctrFile).toString();
|
|
95
|
+
|
|
96
|
+
const fingerprint = getCertificateFingerprint(certificate)
|
|
97
|
+
|
|
98
|
+
kernel.web.server = https.createServer({
|
|
99
|
+
key: privateKey,
|
|
100
|
+
cert: certificate
|
|
101
|
+
}, kernel.web);
|
|
102
|
+
|
|
103
|
+
kernel.web.server.listen(port, () => {
|
|
104
|
+
console.log(`Web server binded on port ${port}`)
|
|
105
|
+
console.log(`Server fingerprint is ${fingerprint}`)
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
module.exports = init;
|
package/config-wan.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
tests: {
|
|
3
|
-
wan: {
|
|
4
|
-
init: "WORKING",
|
|
5
|
-
interval: 5,
|
|
6
|
-
tasks: [
|
|
7
|
-
{ type: "ping", host: "8.8.8.8", count: 3 },
|
|
8
|
-
{ type: "http", url: "https://8.8.8.8" },
|
|
9
|
-
{ type: "http", url: "https://1.1.1.1" },
|
|
10
|
-
],
|
|
11
|
-
|
|
12
|
-
failed: [
|
|
13
|
-
{ type: "cmd", cmd: `systemctl stop frr` }
|
|
14
|
-
],
|
|
15
|
-
succeed: [
|
|
16
|
-
{ type: "cmd", cmd: `systemctl start frr` },
|
|
17
|
-
],
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
}
|