|
2 | 2 | // |
3 | 3 | // SPDX-License-Identifier: Apache-2.0 |
4 | 4 |
|
5 | | -const sqlite3 = require('sqlite3').verbose(); |
6 | | -const fs = require('fs'); |
7 | | -const path = require('path'); |
8 | | -const os = require('os'); |
9 | | - |
10 | | -async function checkifTableExists(db) { |
11 | | - const query = `select count(*) from sqlite_master m where m.name="assets" OR m.name="relations"` |
| 5 | +const sqlite3 = require("sqlite3").verbose(); |
| 6 | +const fs = require("node:fs/promises"); |
| 7 | +const path = require("node:path"); |
| 8 | +const os = require("node:os"); |
| 9 | + |
| 10 | +async function checkIfTableExists(db) { |
| 11 | + const query = `select count(*) from sqlite_master m where m.name="assets" OR m.name="relations"`; |
| 12 | + const [row] = await queryAll(db, query); |
| 13 | + return row["count(*)"] === 2; |
| 14 | +} |
12 | 15 |
|
| 16 | +function queryAll(db, query) { |
13 | 17 | return new Promise((resolve, reject) => { |
14 | | - db.get(query, [], (err, row) => { |
| 18 | + db.all(query, [], (err, rows) => { |
15 | 19 | if (err) { |
16 | 20 | reject(err); |
17 | 21 | return; |
18 | 22 | } |
19 | | - resolve(row["count(*)"] === 2); |
| 23 | + resolve(rows); |
20 | 24 | }); |
21 | 25 | }); |
22 | | - |
23 | 26 | } |
24 | 27 |
|
25 | 28 | async function openDatabase(fileContent) { |
26 | | - const tempFilePath = path.join(os.tmpdir(), 'temp-sqlite' + '.sqlite'); |
| 29 | + const tempFilePath = path.join(os.tmpdir(), "temp-sqlite" + ".sqlite"); |
27 | 30 | // Write the content to a temporary file |
28 | | - await fs.promises.writeFile(tempFilePath, fileContent); |
| 31 | + await fs.writeFile(tempFilePath, fileContent); |
| 32 | + |
| 33 | + return await new Promise((resolve, reject) => { |
| 34 | + const db = new sqlite3.Database( |
| 35 | + tempFilePath, |
| 36 | + sqlite3.OPEN_READONLY, |
| 37 | + (err) => { |
| 38 | + if (err) { |
| 39 | + reject(err.message); |
| 40 | + return; |
| 41 | + } |
| 42 | + } |
| 43 | + ); |
| 44 | + resolve(db); |
| 45 | + }); |
| 46 | +} |
29 | 47 |
|
| 48 | +function closeDatabase(db) { |
30 | 49 | return new Promise((resolve, reject) => { |
31 | | - const db = new sqlite3.Database(tempFilePath, sqlite3.OPEN_READONLY, (err) => { |
| 50 | + db.close((err) => { |
| 51 | + resolve(); |
32 | 52 | if (err) { |
33 | | - reject(err.message); |
34 | | - return; |
| 53 | + reject(err); |
35 | 54 | } |
36 | 55 | }); |
37 | | - resolve(db); |
38 | 56 | }); |
39 | 57 | } |
40 | 58 |
|
41 | 59 | async function parse(fileContent) { |
42 | 60 | const db = await openDatabase(fileContent); |
43 | | - const tableExists = await checkifTableExists(db); |
| 61 | + const tableExists = await checkIfTableExists(db); |
44 | 62 | if (!tableExists) return []; |
45 | 63 |
|
46 | | - return new Promise((resolve, reject) => { |
47 | | - |
48 | | - const query = ` |
| 64 | + const query = ` |
49 | 65 | WITH relation_chain AS ( |
50 | 66 | SELECT |
51 | 67 | fqdn.content AS subdomain, |
@@ -77,54 +93,40 @@ async function parse(fileContent) { |
77 | 93 | LEFT JOIN relations r ON rc.asn_id = r.from_asset_id AND r.type = 'managed_by' |
78 | 94 | LEFT JOIN assets a ON r.to_asset_id = a.id;`; |
79 | 95 |
|
80 | | - db.all(query, [], (err, rows) => { |
81 | | - if (err) { |
82 | | - reject(err); |
83 | | - return; |
84 | | - } |
85 | | - |
86 | | - const results = rows.map((row) => { |
87 | | - // Parse the stringified JSON values |
88 | | - const domainObj = JSON.parse(row.domain); |
89 | | - const subdomainObj = JSON.parse(row.subdomain); |
90 | | - const ipObj = JSON.parse(row.ip); |
91 | | - const cidrObj = JSON.parse(row.cidr); |
92 | | - const asnObj = JSON.parse(row.asn); |
93 | | - const managedByObj = JSON.parse(row.managed_by); |
94 | | - |
95 | | - return { |
96 | | - name: subdomainObj.name, |
97 | | - identified_at: null, |
98 | | - description: `Found subdomain ${subdomainObj.name}`, |
99 | | - category: "Subdomain", |
100 | | - location: subdomainObj.name, |
101 | | - osi_layer: "NETWORK", |
102 | | - severity: "INFORMATIONAL", |
103 | | - attributes: { |
104 | | - addresses: { |
105 | | - ip: ipObj?.address || null, |
106 | | - cidr: cidrObj?.cidr || null, |
107 | | - asn: asnObj?.number || null, |
108 | | - desc: managedByObj?.name || null |
109 | | - }, |
110 | | - domain: domainObj?.name || null, |
111 | | - hostname: subdomainObj?.name || null, |
112 | | - ip_addresses: ipObj?.address || null, |
113 | | - }, |
114 | | - }; |
115 | | - }); |
116 | | - |
117 | | - resolve(results); |
118 | | - |
119 | | - db.close((closeErr) => { |
120 | | - if (closeErr) { |
121 | | - reject(closeErr.message); |
122 | | - } |
123 | | - }); |
124 | | - }); |
| 96 | + const rows = await queryAll(db, query); |
| 97 | + |
| 98 | + await closeDatabase(db); |
| 99 | + |
| 100 | + return rows.map((row) => { |
| 101 | + // Parse the stringified JSON values |
| 102 | + const domainObj = JSON.parse(row.domain); |
| 103 | + const subdomainObj = JSON.parse(row.subdomain); |
| 104 | + const ipObj = JSON.parse(row.ip); |
| 105 | + const cidrObj = JSON.parse(row.cidr); |
| 106 | + const asnObj = JSON.parse(row.asn); |
| 107 | + const managedByObj = JSON.parse(row.managed_by); |
| 108 | + |
| 109 | + return { |
| 110 | + name: subdomainObj.name, |
| 111 | + identified_at: null, |
| 112 | + description: `Found subdomain ${subdomainObj.name}`, |
| 113 | + category: "Subdomain", |
| 114 | + location: subdomainObj.name, |
| 115 | + osi_layer: "NETWORK", |
| 116 | + severity: "INFORMATIONAL", |
| 117 | + attributes: { |
| 118 | + addresses: { |
| 119 | + ip: ipObj?.address || null, |
| 120 | + cidr: cidrObj?.cidr || null, |
| 121 | + asn: asnObj?.number || null, |
| 122 | + desc: managedByObj?.name || null, |
| 123 | + }, |
| 124 | + domain: domainObj?.name || null, |
| 125 | + hostname: subdomainObj?.name || null, |
| 126 | + ip_addresses: ipObj?.address || null, |
| 127 | + }, |
| 128 | + }; |
125 | 129 | }); |
126 | 130 | } |
127 | 131 |
|
128 | | - |
129 | | - |
130 | 132 | module.exports.parse = parse; |
0 commit comments