s3db.js 13.6.0 → 14.0.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/README.md +139 -43
- package/dist/s3db.cjs +72425 -38970
- package/dist/s3db.cjs.map +1 -1
- package/dist/s3db.es.js +72177 -38764
- package/dist/s3db.es.js.map +1 -1
- package/mcp/lib/base-handler.js +157 -0
- package/mcp/lib/handlers/connection-handler.js +280 -0
- package/mcp/lib/handlers/query-handler.js +533 -0
- package/mcp/lib/handlers/resource-handler.js +428 -0
- package/mcp/lib/tool-registry.js +336 -0
- package/mcp/lib/tools/connection-tools.js +161 -0
- package/mcp/lib/tools/query-tools.js +267 -0
- package/mcp/lib/tools/resource-tools.js +404 -0
- package/package.json +94 -49
- package/src/clients/memory-client.class.js +346 -191
- package/src/clients/memory-storage.class.js +300 -84
- package/src/clients/s3-client.class.js +7 -6
- package/src/concerns/geo-encoding.js +19 -2
- package/src/concerns/ip.js +59 -9
- package/src/concerns/money.js +8 -1
- package/src/concerns/password-hashing.js +49 -8
- package/src/concerns/plugin-storage.js +186 -18
- package/src/concerns/storage-drivers/filesystem-driver.js +284 -0
- package/src/database.class.js +139 -29
- package/src/errors.js +332 -42
- package/src/plugins/api/auth/oidc-auth.js +66 -17
- package/src/plugins/api/auth/strategies/base-strategy.class.js +74 -0
- package/src/plugins/api/auth/strategies/factory.class.js +63 -0
- package/src/plugins/api/auth/strategies/global-strategy.class.js +44 -0
- package/src/plugins/api/auth/strategies/path-based-strategy.class.js +83 -0
- package/src/plugins/api/auth/strategies/path-rules-strategy.class.js +118 -0
- package/src/plugins/api/concerns/failban-manager.js +106 -57
- package/src/plugins/api/concerns/opengraph-helper.js +116 -0
- package/src/plugins/api/concerns/route-context.js +601 -0
- package/src/plugins/api/concerns/state-machine.js +288 -0
- package/src/plugins/api/index.js +180 -41
- package/src/plugins/api/routes/auth-routes.js +198 -30
- package/src/plugins/api/routes/resource-routes.js +19 -4
- package/src/plugins/api/server/health-manager.class.js +163 -0
- package/src/plugins/api/server/middleware-chain.class.js +310 -0
- package/src/plugins/api/server/router.class.js +472 -0
- package/src/plugins/api/server.js +280 -1303
- package/src/plugins/api/utils/custom-routes.js +17 -5
- package/src/plugins/api/utils/guards.js +76 -17
- package/src/plugins/api/utils/openapi-generator-cached.class.js +133 -0
- package/src/plugins/api/utils/openapi-generator.js +7 -6
- package/src/plugins/api/utils/template-engine.js +77 -3
- package/src/plugins/audit.plugin.js +30 -8
- package/src/plugins/backup.plugin.js +110 -14
- package/src/plugins/cache/cache.class.js +22 -5
- package/src/plugins/cache/filesystem-cache.class.js +116 -19
- package/src/plugins/cache/memory-cache.class.js +211 -57
- package/src/plugins/cache/multi-tier-cache.class.js +371 -0
- package/src/plugins/cache/partition-aware-filesystem-cache.class.js +168 -47
- package/src/plugins/cache/redis-cache.class.js +552 -0
- package/src/plugins/cache/s3-cache.class.js +17 -8
- package/src/plugins/cache.plugin.js +176 -61
- package/src/plugins/cloud-inventory/drivers/alibaba-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/aws-driver.js +60 -29
- package/src/plugins/cloud-inventory/drivers/azure-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/base-driver.js +16 -2
- package/src/plugins/cloud-inventory/drivers/cloudflare-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/digitalocean-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/hetzner-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/linode-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/mongodb-atlas-driver.js +8 -1
- package/src/plugins/cloud-inventory/drivers/vultr-driver.js +8 -1
- package/src/plugins/cloud-inventory/index.js +29 -8
- package/src/plugins/cloud-inventory/registry.js +64 -42
- package/src/plugins/cloud-inventory.plugin.js +240 -138
- package/src/plugins/concerns/plugin-dependencies.js +54 -0
- package/src/plugins/concerns/resource-names.js +100 -0
- package/src/plugins/consumers/index.js +10 -2
- package/src/plugins/consumers/sqs-consumer.js +12 -2
- package/src/plugins/cookie-farm-suite.plugin.js +278 -0
- package/src/plugins/cookie-farm.errors.js +73 -0
- package/src/plugins/cookie-farm.plugin.js +869 -0
- package/src/plugins/costs.plugin.js +7 -1
- package/src/plugins/eventual-consistency/analytics.js +94 -19
- package/src/plugins/eventual-consistency/config.js +15 -7
- package/src/plugins/eventual-consistency/consolidation.js +29 -11
- package/src/plugins/eventual-consistency/garbage-collection.js +3 -1
- package/src/plugins/eventual-consistency/helpers.js +39 -14
- package/src/plugins/eventual-consistency/install.js +21 -2
- package/src/plugins/eventual-consistency/utils.js +32 -10
- package/src/plugins/fulltext.plugin.js +38 -11
- package/src/plugins/geo.plugin.js +61 -9
- package/src/plugins/identity/concerns/config.js +61 -0
- package/src/plugins/identity/concerns/mfa-manager.js +15 -2
- package/src/plugins/identity/concerns/rate-limit.js +124 -0
- package/src/plugins/identity/concerns/resource-schemas.js +9 -1
- package/src/plugins/identity/concerns/token-generator.js +29 -4
- package/src/plugins/identity/drivers/auth-driver.interface.js +76 -0
- package/src/plugins/identity/drivers/client-credentials-driver.js +127 -0
- package/src/plugins/identity/drivers/index.js +18 -0
- package/src/plugins/identity/drivers/password-driver.js +122 -0
- package/src/plugins/identity/email-service.js +17 -2
- package/src/plugins/identity/index.js +413 -69
- package/src/plugins/identity/oauth2-server.js +413 -30
- package/src/plugins/identity/oidc-discovery.js +16 -8
- package/src/plugins/identity/rsa-keys.js +115 -35
- package/src/plugins/identity/server.js +166 -45
- package/src/plugins/identity/session-manager.js +53 -7
- package/src/plugins/identity/ui/pages/mfa-verification.js +17 -15
- package/src/plugins/identity/ui/routes.js +363 -255
- package/src/plugins/importer/index.js +153 -20
- package/src/plugins/index.js +9 -2
- package/src/plugins/kubernetes-inventory/index.js +6 -0
- package/src/plugins/kubernetes-inventory/k8s-driver.js +867 -0
- package/src/plugins/kubernetes-inventory/resource-types.js +274 -0
- package/src/plugins/kubernetes-inventory.plugin.js +980 -0
- package/src/plugins/metrics.plugin.js +64 -16
- package/src/plugins/ml/base-model.class.js +25 -15
- package/src/plugins/ml/regression-model.class.js +1 -1
- package/src/plugins/ml.errors.js +57 -25
- package/src/plugins/ml.plugin.js +28 -4
- package/src/plugins/namespace.js +210 -0
- package/src/plugins/plugin.class.js +180 -8
- package/src/plugins/puppeteer/console-monitor.js +729 -0
- package/src/plugins/puppeteer/cookie-manager.js +492 -0
- package/src/plugins/puppeteer/network-monitor.js +816 -0
- package/src/plugins/puppeteer/performance-manager.js +746 -0
- package/src/plugins/puppeteer/proxy-manager.js +478 -0
- package/src/plugins/puppeteer/stealth-manager.js +556 -0
- package/src/plugins/puppeteer.errors.js +81 -0
- package/src/plugins/puppeteer.plugin.js +1327 -0
- package/src/plugins/queue-consumer.plugin.js +69 -14
- package/src/plugins/recon/behaviors/uptime-behavior.js +691 -0
- package/src/plugins/recon/concerns/command-runner.js +148 -0
- package/src/plugins/recon/concerns/diff-detector.js +372 -0
- package/src/plugins/recon/concerns/fingerprint-builder.js +307 -0
- package/src/plugins/recon/concerns/process-manager.js +338 -0
- package/src/plugins/recon/concerns/report-generator.js +478 -0
- package/src/plugins/recon/concerns/security-analyzer.js +571 -0
- package/src/plugins/recon/concerns/target-normalizer.js +68 -0
- package/src/plugins/recon/config/defaults.js +321 -0
- package/src/plugins/recon/config/resources.js +370 -0
- package/src/plugins/recon/index.js +778 -0
- package/src/plugins/recon/managers/dependency-manager.js +174 -0
- package/src/plugins/recon/managers/scheduler-manager.js +179 -0
- package/src/plugins/recon/managers/storage-manager.js +745 -0
- package/src/plugins/recon/managers/target-manager.js +274 -0
- package/src/plugins/recon/stages/asn-stage.js +314 -0
- package/src/plugins/recon/stages/certificate-stage.js +84 -0
- package/src/plugins/recon/stages/dns-stage.js +107 -0
- package/src/plugins/recon/stages/dnsdumpster-stage.js +362 -0
- package/src/plugins/recon/stages/fingerprint-stage.js +71 -0
- package/src/plugins/recon/stages/google-dorks-stage.js +440 -0
- package/src/plugins/recon/stages/http-stage.js +89 -0
- package/src/plugins/recon/stages/latency-stage.js +148 -0
- package/src/plugins/recon/stages/massdns-stage.js +302 -0
- package/src/plugins/recon/stages/osint-stage.js +1373 -0
- package/src/plugins/recon/stages/ports-stage.js +169 -0
- package/src/plugins/recon/stages/screenshot-stage.js +94 -0
- package/src/plugins/recon/stages/secrets-stage.js +514 -0
- package/src/plugins/recon/stages/subdomains-stage.js +295 -0
- package/src/plugins/recon/stages/tls-audit-stage.js +78 -0
- package/src/plugins/recon/stages/vulnerability-stage.js +78 -0
- package/src/plugins/recon/stages/web-discovery-stage.js +113 -0
- package/src/plugins/recon/stages/whois-stage.js +349 -0
- package/src/plugins/recon.plugin.js +75 -0
- package/src/plugins/recon.plugin.js.backup +2635 -0
- package/src/plugins/relation.errors.js +87 -14
- package/src/plugins/replicator.plugin.js +514 -137
- package/src/plugins/replicators/base-replicator.class.js +89 -1
- package/src/plugins/replicators/bigquery-replicator.class.js +66 -22
- package/src/plugins/replicators/dynamodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mongodb-replicator.class.js +22 -15
- package/src/plugins/replicators/mysql-replicator.class.js +52 -17
- package/src/plugins/replicators/planetscale-replicator.class.js +30 -4
- package/src/plugins/replicators/postgres-replicator.class.js +62 -27
- package/src/plugins/replicators/s3db-replicator.class.js +25 -18
- package/src/plugins/replicators/schema-sync.helper.js +3 -3
- package/src/plugins/replicators/sqs-replicator.class.js +8 -2
- package/src/plugins/replicators/turso-replicator.class.js +23 -3
- package/src/plugins/replicators/webhook-replicator.class.js +42 -4
- package/src/plugins/s3-queue.plugin.js +464 -65
- package/src/plugins/scheduler.plugin.js +20 -6
- package/src/plugins/state-machine.plugin.js +40 -9
- package/src/plugins/tfstate/README.md +126 -126
- package/src/plugins/tfstate/base-driver.js +28 -4
- package/src/plugins/tfstate/errors.js +65 -10
- package/src/plugins/tfstate/filesystem-driver.js +52 -8
- package/src/plugins/tfstate/index.js +163 -90
- package/src/plugins/tfstate/s3-driver.js +64 -6
- package/src/plugins/ttl.plugin.js +72 -17
- package/src/plugins/vector/distances.js +18 -12
- package/src/plugins/vector/kmeans.js +26 -4
- package/src/resource.class.js +115 -19
- package/src/testing/factory.class.js +20 -3
- package/src/testing/seeder.class.js +7 -1
- package/src/clients/memory-client.md +0 -917
- package/src/plugins/cloud-inventory/drivers/mock-drivers.js +0 -449
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DependencyManager
|
|
3
|
+
*
|
|
4
|
+
* Validates tool availability and emits warnings:
|
|
5
|
+
* - Checks if reconnaissance tools are installed
|
|
6
|
+
* - Provides installation guidance
|
|
7
|
+
* - Emits detailed warnings for missing tools
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export class DependencyManager {
|
|
11
|
+
constructor(plugin) {
|
|
12
|
+
this.plugin = plugin;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Check all dependencies based on enabled features
|
|
17
|
+
*/
|
|
18
|
+
async checkAll() {
|
|
19
|
+
const features = this.plugin.config.features;
|
|
20
|
+
const warnings = [];
|
|
21
|
+
const available = {};
|
|
22
|
+
const missing = {};
|
|
23
|
+
|
|
24
|
+
const toolMap = {
|
|
25
|
+
'whois': 'whois',
|
|
26
|
+
'secrets.gitleaks': 'gitleaks',
|
|
27
|
+
'latency.ping': 'ping',
|
|
28
|
+
'latency.traceroute': ['mtr', 'traceroute'],
|
|
29
|
+
'http.curl': 'curl',
|
|
30
|
+
'ports.nmap': 'nmap',
|
|
31
|
+
'ports.masscan': 'masscan',
|
|
32
|
+
'subdomains.amass': 'amass',
|
|
33
|
+
'subdomains.subfinder': 'subfinder',
|
|
34
|
+
'subdomains.assetfinder': 'assetfinder',
|
|
35
|
+
'web.ffuf': 'ffuf',
|
|
36
|
+
'web.feroxbuster': 'feroxbuster',
|
|
37
|
+
'web.gobuster': 'gobuster',
|
|
38
|
+
'vulnerability.nikto': 'nikto',
|
|
39
|
+
'vulnerability.wpscan': 'wpscan',
|
|
40
|
+
'vulnerability.droopescan': 'droopescan',
|
|
41
|
+
'tlsAudit.openssl': 'openssl',
|
|
42
|
+
'tlsAudit.sslyze': 'sslyze',
|
|
43
|
+
'tlsAudit.testssl': 'testssl.sh',
|
|
44
|
+
'tlsAudit.sslscan': 'sslscan',
|
|
45
|
+
'fingerprint.whatweb': 'whatweb',
|
|
46
|
+
'screenshots.aquatone': 'aquatone',
|
|
47
|
+
'screenshots.eyewitness': 'EyeWitness',
|
|
48
|
+
'osint.theHarvester': 'theHarvester',
|
|
49
|
+
'osint.sherlock': 'sherlock',
|
|
50
|
+
'osint.maigret': 'maigret',
|
|
51
|
+
'asn': 'dig',
|
|
52
|
+
'massdns': 'massdns'
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
for (const [featurePath, commands] of Object.entries(toolMap)) {
|
|
56
|
+
const isEnabled = this._isFeatureEnabled(features, featurePath);
|
|
57
|
+
if (!isEnabled) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const commandList = Array.isArray(commands) ? commands : [commands];
|
|
62
|
+
let foundAny = false;
|
|
63
|
+
|
|
64
|
+
for (const cmd of commandList) {
|
|
65
|
+
const isAvailable = await this._checkTool(cmd);
|
|
66
|
+
if (isAvailable) {
|
|
67
|
+
foundAny = true;
|
|
68
|
+
available[cmd] = true;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!foundAny) {
|
|
74
|
+
const toolNames = commandList.join(' ou ');
|
|
75
|
+
warnings.push({
|
|
76
|
+
feature: featurePath,
|
|
77
|
+
tools: commandList,
|
|
78
|
+
message: `Ferramenta "${toolNames}" não encontrada no PATH`,
|
|
79
|
+
installGuide: this._getInstallGuide(commandList[0])
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
for (const cmd of commandList) {
|
|
83
|
+
missing[cmd] = true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.plugin.emit('recon:dependency-missing', {
|
|
87
|
+
feature: featurePath,
|
|
88
|
+
tools: commandList,
|
|
89
|
+
message: `Ferramenta "${toolNames}" não encontrada no PATH`,
|
|
90
|
+
installGuide: this._getInstallGuide(commandList[0])
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const availableTools = Object.keys(available);
|
|
96
|
+
const missingTools = Object.keys(missing);
|
|
97
|
+
|
|
98
|
+
this.plugin.emit('recon:dependencies-checked', {
|
|
99
|
+
available: availableTools.length,
|
|
100
|
+
missing: missingTools.length,
|
|
101
|
+
availableTools,
|
|
102
|
+
missingTools,
|
|
103
|
+
warnings
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return warnings;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Check if a specific tool is available
|
|
111
|
+
*/
|
|
112
|
+
async checkTool(toolName) {
|
|
113
|
+
return await this._checkTool(toolName);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ========================================
|
|
117
|
+
// Private Helper Methods
|
|
118
|
+
// ========================================
|
|
119
|
+
|
|
120
|
+
async _checkTool(command) {
|
|
121
|
+
const runner = this.plugin.commandRunner;
|
|
122
|
+
return await runner.isAvailable(command);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_isFeatureEnabled(features, path) {
|
|
126
|
+
const parts = path.split('.');
|
|
127
|
+
let current = features;
|
|
128
|
+
|
|
129
|
+
for (const part of parts) {
|
|
130
|
+
if (current == null || typeof current !== 'object') {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
current = current[part];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return current === true || (typeof current === 'object' && current !== null);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
_getInstallGuide(toolName) {
|
|
140
|
+
const guides = {
|
|
141
|
+
whois: 'Ubuntu: apt-get install whois | macOS: brew install whois',
|
|
142
|
+
gitleaks: 'https://github.com/gitleaks/gitleaks | go install github.com/gitleaks/gitleaks/v8@latest | brew install gitleaks',
|
|
143
|
+
ping: 'Geralmente pré-instalado. No Ubuntu: apt-get install iputils-ping',
|
|
144
|
+
mtr: 'Ubuntu: apt-get install mtr-tiny | macOS: brew install mtr',
|
|
145
|
+
traceroute: 'Ubuntu: apt-get install traceroute | macOS: Pré-instalado',
|
|
146
|
+
curl: 'Ubuntu: apt-get install curl | macOS: Pré-instalado',
|
|
147
|
+
nmap: 'Ubuntu: apt-get install nmap | macOS: brew install nmap',
|
|
148
|
+
masscan: 'Ubuntu: apt-get install masscan | macOS: brew install masscan',
|
|
149
|
+
amass: 'https://github.com/owasp-amass/amass | Ubuntu: apt install amass | macOS: brew install amass',
|
|
150
|
+
subfinder: 'https://github.com/projectdiscovery/subfinder | go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest',
|
|
151
|
+
assetfinder: 'https://github.com/tomnomnom/assetfinder | go install github.com/tomnomnom/assetfinder@latest',
|
|
152
|
+
ffuf: 'https://github.com/ffuf/ffuf | go install github.com/ffuf/ffuf/v2@latest',
|
|
153
|
+
feroxbuster: 'https://github.com/epi052/feroxbuster | Ubuntu: apt install feroxbuster | macOS: brew install feroxbuster',
|
|
154
|
+
gobuster: 'https://github.com/OJ/gobuster | go install github.com/OJ/gobuster/v3@latest',
|
|
155
|
+
nikto: 'Ubuntu: apt-get install nikto | macOS: brew install nikto',
|
|
156
|
+
wpscan: 'https://github.com/wpscanteam/wpscan | gem install wpscan',
|
|
157
|
+
droopescan: 'https://github.com/SamJoan/droopescan | pip install droopescan',
|
|
158
|
+
openssl: 'Ubuntu: apt-get install openssl | macOS: Pré-instalado',
|
|
159
|
+
sslyze: 'https://github.com/nabla-c0d3/sslyze | pip install sslyze',
|
|
160
|
+
'testssl.sh': 'https://github.com/drwetter/testssl.sh | git clone --depth 1 https://github.com/drwetter/testssl.sh.git',
|
|
161
|
+
sslscan: 'https://github.com/rbsec/sslscan | Ubuntu: apt-get install sslscan | macOS: brew install sslscan',
|
|
162
|
+
whatweb: 'https://github.com/urbanadventurer/WhatWeb | Ubuntu: apt-get install whatweb | macOS: brew install whatweb',
|
|
163
|
+
aquatone: 'https://github.com/michenriksen/aquatone | Download binário do GitHub Releases',
|
|
164
|
+
EyeWitness: 'https://github.com/FortyNorthSecurity/EyeWitness | git clone e seguir instruções',
|
|
165
|
+
theHarvester: 'https://github.com/laramies/theHarvester | pip install theHarvester',
|
|
166
|
+
sherlock: 'https://github.com/sherlock-project/sherlock | pip install sherlock-project',
|
|
167
|
+
maigret: 'https://github.com/soxoj/maigret | pip install maigret',
|
|
168
|
+
dig: 'Ubuntu: apt-get install dnsutils | macOS: Pré-instalado',
|
|
169
|
+
massdns: 'https://github.com/blechschmidt/massdns | git clone && make && sudo make install'
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
return guides[toolName] || `Consulte a documentação oficial da ferramenta "${toolName}" para instruções de instalação.`;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SchedulerManager
|
|
3
|
+
*
|
|
4
|
+
* Handles cron-based scheduled sweeps:
|
|
5
|
+
* - Manages cron job registration
|
|
6
|
+
* - Triggers scheduled target sweeps
|
|
7
|
+
* - Iterates over enabled targets
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { PromisePool } from '@supercharge/promise-pool';
|
|
11
|
+
|
|
12
|
+
export class SchedulerManager {
|
|
13
|
+
constructor(plugin) {
|
|
14
|
+
this.plugin = plugin;
|
|
15
|
+
this.cronJobId = null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Start the scheduler (register cron job)
|
|
20
|
+
*/
|
|
21
|
+
async start() {
|
|
22
|
+
if (!this.plugin.config.schedule.enabled) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const cronExpression = this.plugin.config.schedule.cron;
|
|
27
|
+
if (!cronExpression) {
|
|
28
|
+
this.plugin.emit('recon:scheduler-warning', {
|
|
29
|
+
message: 'Schedule enabled but no cron expression provided'
|
|
30
|
+
});
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Register cron job with SchedulerPlugin (if available)
|
|
35
|
+
if (this.plugin.database?.plugins?.scheduler) {
|
|
36
|
+
const scheduler = this.plugin.database.plugins.scheduler;
|
|
37
|
+
this.cronJobId = await scheduler.registerJob({
|
|
38
|
+
name: `recon-sweep-${this.plugin.namespace || 'default'}`,
|
|
39
|
+
cron: cronExpression,
|
|
40
|
+
handler: async () => {
|
|
41
|
+
await this.triggerSweep('scheduled');
|
|
42
|
+
},
|
|
43
|
+
enabled: true,
|
|
44
|
+
metadata: {
|
|
45
|
+
plugin: 'recon',
|
|
46
|
+
namespace: this.plugin.namespace
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
this.plugin.emit('recon:scheduler-started', {
|
|
51
|
+
cronJobId: this.cronJobId,
|
|
52
|
+
cron: cronExpression
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
// Fallback: use setInterval (less accurate, no persistence)
|
|
56
|
+
this._startFallbackScheduler(cronExpression);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Run on start if configured
|
|
60
|
+
if (this.plugin.config.schedule.runOnStart) {
|
|
61
|
+
await this.triggerSweep('startup');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Stop the scheduler (unregister cron job)
|
|
67
|
+
*/
|
|
68
|
+
async stop() {
|
|
69
|
+
if (this.cronJobId && this.plugin.database?.plugins?.scheduler) {
|
|
70
|
+
const scheduler = this.plugin.database.plugins.scheduler;
|
|
71
|
+
await scheduler.unregisterJob(this.cronJobId);
|
|
72
|
+
this.cronJobId = null;
|
|
73
|
+
|
|
74
|
+
this.plugin.emit('recon:scheduler-stopped', {});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (this._fallbackIntervalId) {
|
|
78
|
+
clearInterval(this._fallbackIntervalId);
|
|
79
|
+
this._fallbackIntervalId = null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Trigger a sweep of all enabled targets
|
|
85
|
+
*/
|
|
86
|
+
async triggerSweep(reason = 'manual') {
|
|
87
|
+
const targetManager = this.plugin._targetManager;
|
|
88
|
+
const activeTargets = await targetManager.list({ includeDisabled: false });
|
|
89
|
+
|
|
90
|
+
if (!activeTargets.length) {
|
|
91
|
+
this.plugin.emit('recon:no-active-targets', {
|
|
92
|
+
reason,
|
|
93
|
+
message: 'No active targets configured for sweep'
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.plugin.emit('recon:sweep-started', {
|
|
99
|
+
reason,
|
|
100
|
+
targetCount: activeTargets.length,
|
|
101
|
+
targets: activeTargets.map(t => t.id)
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await PromisePool.withConcurrency(this.plugin.config.concurrency || 1)
|
|
105
|
+
.for(activeTargets)
|
|
106
|
+
.process(async (targetEntry) => {
|
|
107
|
+
try {
|
|
108
|
+
const report = await this.plugin.runDiagnostics(targetEntry.target, {
|
|
109
|
+
behavior: targetEntry.behavior,
|
|
110
|
+
features: targetEntry.features,
|
|
111
|
+
tools: targetEntry.tools,
|
|
112
|
+
persist: targetEntry.persist ?? true
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
this.plugin.emit('recon:completed', {
|
|
116
|
+
reason,
|
|
117
|
+
target: report.target.host,
|
|
118
|
+
status: report.status,
|
|
119
|
+
scanCount: (targetEntry.scanCount || 0) + 1,
|
|
120
|
+
endedAt: report.endedAt
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Update target metadata
|
|
124
|
+
await targetManager.updateScanMetadata(targetEntry.id, report);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
this.plugin.emit('recon:target-error', {
|
|
127
|
+
reason,
|
|
128
|
+
target: targetEntry.target,
|
|
129
|
+
message: error?.message || 'Recon execution failed',
|
|
130
|
+
error
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
this.plugin.emit('recon:sweep-completed', {
|
|
136
|
+
reason,
|
|
137
|
+
targetCount: activeTargets.length
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ========================================
|
|
142
|
+
// Private Helper Methods
|
|
143
|
+
// ========================================
|
|
144
|
+
|
|
145
|
+
_startFallbackScheduler(cronExpression) {
|
|
146
|
+
// Simple fallback: parse cron and use setInterval
|
|
147
|
+
// NOTE: This is NOT production-ready - use SchedulerPlugin instead
|
|
148
|
+
const intervalMs = this._parseCronToInterval(cronExpression);
|
|
149
|
+
|
|
150
|
+
this._fallbackIntervalId = setInterval(async () => {
|
|
151
|
+
await this.triggerSweep('scheduled-fallback');
|
|
152
|
+
}, intervalMs);
|
|
153
|
+
|
|
154
|
+
this.plugin.emit('recon:scheduler-started', {
|
|
155
|
+
cronJobId: 'fallback',
|
|
156
|
+
cron: cronExpression,
|
|
157
|
+
warning: 'Using fallback scheduler - install SchedulerPlugin for accurate cron execution'
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
_parseCronToInterval(cronExpression) {
|
|
162
|
+
// Very basic cron parsing for fallback mode
|
|
163
|
+
// Format: minute hour day month weekday
|
|
164
|
+
const parts = cronExpression.split(' ');
|
|
165
|
+
|
|
166
|
+
if (parts[0].startsWith('*/')) {
|
|
167
|
+
const minutes = parseInt(parts[0].substring(2));
|
|
168
|
+
return minutes * 60 * 1000;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (parts[1].startsWith('*/')) {
|
|
172
|
+
const hours = parseInt(parts[1].substring(2));
|
|
173
|
+
return hours * 60 * 60 * 1000;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Default: every hour
|
|
177
|
+
return 60 * 60 * 1000;
|
|
178
|
+
}
|
|
179
|
+
}
|