diff --git a/examples/Hashcat/README.md b/examples/Hashcat/README.md new file mode 100644 index 0000000..59ee9c8 --- /dev/null +++ b/examples/Hashcat/README.md @@ -0,0 +1,6 @@ +Hashcat dictionary: +npm install +hflow run . + +Workflow diagram: +![img.png](hashcat.png) \ No newline at end of file diff --git a/examples/Hashcat/filter.js b/examples/Hashcat/filter.js new file mode 100644 index 0000000..3be577a --- /dev/null +++ b/examples/Hashcat/filter.js @@ -0,0 +1,28 @@ +const fs = require('fs'); + +function filterHashes() { + const hashes = fs.readFileSync("hashes.txt", 'utf8').trim().split('\n'); + + const groupedHashes = { + md5: [], + sha1: [], + sha256: [], + sha512: [], + 'sha3-256': [] + }; + + hashes.forEach(line => { + const [hash, algorithm] = line.split(' '); + if (groupedHashes[algorithm]) { + groupedHashes[algorithm].push(hash); + } + }); + + // Write hashes to separate files by algorithm + Object.keys(groupedHashes).forEach(algorithm => { + const filename = `${algorithm}_hashes.txt`; + fs.writeFileSync(filename, groupedHashes[algorithm].join('\n'), 'utf8'); + }); +} + +filterHashes() \ No newline at end of file diff --git a/examples/Hashcat/functions.js b/examples/Hashcat/functions.js new file mode 100644 index 0000000..fc249b4 --- /dev/null +++ b/examples/Hashcat/functions.js @@ -0,0 +1,83 @@ +var spawn = require('child_process').spawn; +var log4js = require('log4js'); +var createJobMessage = require('../../common/jobMessage.js').createJobMessage; + + +// Spawns a job "node handler.js" and waits for the notification of its +// completion using the Redis job status notification mechanism +async function submitRemoteJob(ins, outs, context, cb) { + let fname='wftrace-' + context.hfId + '-' + context.appId + '.log'; + log4js.configure({ + appenders: { hftrace: { type: 'file', filename: fname } }, + categories: { default: { appenders: ['hftrace'], level: 'error' } } + }); + + var logger = log4js.getLogger(); + + logger.level = 'debug'; + console.log("Spawning process..."); + + //console.log(ins.map(i => i)); + + var input_dir = context.executor.input_dir, + work_dir = context.executor.work_dir, + output_dir = context.executor.output_dir; + + let jobMessage = JSON.stringify(createJobMessage(ins, outs, context)); + + var cmd; + + // if 'container' is present, run through Docker, mounting all directories if necessary + if (context.container) { + cmd = 'docker run '; + if (input_dir) cmd += ' -v ' + input_dir + ':/input_dir '; + if (work_dir) cmd += ' -v ' + work_dir + ':/work_dir '; + if (output_dir) cmd += ' -v ' + output_dir + ':/output_dir '; + cmd += container + ' node'; + } else cmd = 'node' + + try { + if (work_dir) { process.chdir(work_dir); } + } catch (error) { + throw error; + } + + // "submit" job (start the handler process) + var proc = spawn(cmd, ['../../../hyperflow-job-executor/jobexec.js', context.taskId, context.redis_url], {shell: true}); + + proc.stderr.on('data', function(data) { + logger.debug(data.toString()); + console.log(data.toString()); + }); + + proc.stdout.on('data', function(data) { + logger.debug(data.toString()); + console.log(data.toString()); + }); + + proc.on('exit', function(code) { + logger.debug('Process exited with code', code); + }); + + // send message to the job (command to be executed) + try { + await context.sendMsgToJob(jobMessage, context.taskId); + logger.info('[' + context.taskId + '] job message sent'); + } catch(err) { + console.error(err); + throw err; + } + + // wait for the job to finish (timeout=0 means indefinite) + try { + var jobResult = await context.jobResult(0, context.taskId); + logger.info('[' + context.taskId + '] job result received:', jobResult); + console.log('Received job result:', jobResult); + cb(null, outs); + } catch(err) { + console.error(err); + throw err; + } +} + +exports.submitRemoteJob = submitRemoteJob; diff --git a/examples/Hashcat/generate.js b/examples/Hashcat/generate.js new file mode 100644 index 0000000..0d424ea --- /dev/null +++ b/examples/Hashcat/generate.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const crypto = require('crypto'); + +function randomString(maxLength) { + const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + let result = ''; + for (let i = 0; i < maxLength; i++) { + result += chars[Math.floor(Math.random() * chars.length)]; + } + return result; +} + +function generateHashes() { + const algorithms = ['md5', 'sha1', 'sha256', 'sha512', 'sha3-256']; + const proportions = [35, 25, 15, 15, 10]; // Percentages for each algorithm + + const totalHashes = 100; + const hashCounts = proportions.map(p => Math.floor((p / 100) * totalHashes)); + + const hashes = []; + + for (let i = 0; i < algorithms.length; i++) { + for (let j = 0; j < hashCounts[i]; j++) { + const randomStr = randomString(5); + const hash = crypto.createHash(algorithms[i]).update(randomStr).digest('hex'); + hashes.push({ hash, algorithm: algorithms[i] }); + } + } + + // Write all hashes to a single file + const allHashes = hashes.map(h => `${h.hash} ${h.algorithm}`).join('\n'); + fs.writeFileSync('hashes.txt', allHashes, 'utf8'); +} + +generateHashes() \ No newline at end of file diff --git a/examples/Hashcat/handler.js b/examples/Hashcat/handler.js new file mode 100644 index 0000000..e7bbb48 --- /dev/null +++ b/examples/Hashcat/handler.js @@ -0,0 +1,76 @@ +// Executor of 'jobs' using the Redis task status notification mechanism +const redis = require('redis'); +const { spawn } = require('child_process'); + +if (process.argv.length < 4) { + console.error("Usage: node handler.js "); + process.exit(1); +} + +// 'taskId' is the name of the Redis list to use for the notification +var taskId = process.argv[2], +redis_url = process.argv[3]; + +//console.log("taskId", taskId); +//console.log("redis_url", redis_url); + +var rcl = redis.createClient(redis_url); + +// get job message from Redis +var getJobMessage = async function (timeout) { + return new Promise(function (resolve, reject) { + const jobMsgKey = taskId + "_msg"; + rcl.brpop(jobMsgKey, timeout, function (err, reply) { + err ? reject(err): resolve(reply) + }); + }); +} + +// send notification about job completion to Redis +var notifyJobCompletion = async function () { + return new Promise(function (resolve, reject) { + rcl.rpush(taskId, "OK", function (err, reply) { + err ? reject(err): resolve(reply) + }); + }); +} + + +async function executeJob() { + + // 1. get job message + try { + var jobMessage = await getJobMessage(10); + } catch (err) { + console.error(err); + throw err; + } + //console.log("Received job message:", jobMessage); + + // 2. Execute job + var jm = JSON.parse(jobMessage[1]); + + const cmd = spawn(jm["executable"], jm["args"]); + + cmd.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cmd.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + cmd.on('close', async(code) => { + console.log(`child process exited with code ${code}`); + // 3. Notify job completion + try { + await notifyJobCompletion(); + } catch (err) { + console.error("Redis notification failed", err); + throw err; + } + process.exit(0); + }); + } + +executeJob() diff --git a/examples/Hashcat/hashcat.js b/examples/Hashcat/hashcat.js new file mode 100644 index 0000000..33d9af2 --- /dev/null +++ b/examples/Hashcat/hashcat.js @@ -0,0 +1,44 @@ +const { exec } = require('child_process'); + +function runHashcat(algorithm) { + const hashesFile = algorithm + '_hashes.txt'; // Hashes file // Algorithm name (e.g., 'md5', 'sha1') + const crackedFile = 'cracked.txt'; // Output file for cracked hashes + + // Map algorithms to Hashcat mode IDs + const algorithmModeMap = { + md5: 0, + sha1: 100, + sha256: 1400, + sha512: 1700, + 'sha3-256': 17400 + }; + + const hashcatMode = algorithmModeMap[algorithm]; + if (hashcatMode === undefined) { + const error = new Error(`Unsupported algorithm: ${algorithm}`); + console.error(error.message); + return; + } + + const mask = '?a?a?a?a?a'; + console.log(`Running Hashcat for ${algorithm}...`); + + // Construct the Hashcat command + const command = `hashcat --potfile-disable -m ${hashcatMode} -a 3 -o ${crackedFile} ${hashesFile} ${mask}`; + + // Execute the Hashcat command + exec(command, (error, stdout, stderr) => { + if (error) { + console.error(`Hashcat Error: ${error.message}`); + return; + } + if (stderr) { + console.error(`Hashcat Stderr: ${stderr}`); + } + + console.log(`Hashcat Output:\n${stdout}`); + }); +} + +const args = process.argv.slice(2); +runHashcat(args[0]); \ No newline at end of file diff --git a/examples/Hashcat/hashcat.png b/examples/Hashcat/hashcat.png new file mode 100644 index 0000000..056bce3 Binary files /dev/null and b/examples/Hashcat/hashcat.png differ diff --git a/examples/Hashcat/package-lock.json b/examples/Hashcat/package-lock.json new file mode 100644 index 0000000..91bc622 --- /dev/null +++ b/examples/Hashcat/package-lock.json @@ -0,0 +1,322 @@ +{ + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "dependencies": { + "@stroncium/procfs": "^1.0.0", + "async": "^2.6.4", + "log4js": "^6.4.0", + "redis": "^3.1.1" + } + }, + "node_modules/@stroncium/procfs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@stroncium/procfs/-/procfs-1.2.1.tgz", + "integrity": "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==" + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + } + }, + "dependencies": { + "@stroncium/procfs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@stroncium/procfs/-/procfs-1.2.1.tgz", + "integrity": "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA==" + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==" + }, + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" + } + }, + "denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, + "flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "requires": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + } + }, + "redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "requires": { + "redis-errors": "^1.0.0" + } + }, + "rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } + } +} diff --git a/examples/Hashcat/package.json b/examples/Hashcat/package.json new file mode 100644 index 0000000..bef6116 --- /dev/null +++ b/examples/Hashcat/package.json @@ -0,0 +1,14 @@ +{ + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "main": "handler.js", + "scripts": { + "start": "node handler.js" + }, + "dependencies": { + "@stroncium/procfs": "^1.0.0", + "async": "^2.6.4", + "log4js": "^6.4.0", + "redis": "^3.1.1" + } +} \ No newline at end of file diff --git a/examples/Hashcat/summarize.js b/examples/Hashcat/summarize.js new file mode 100644 index 0000000..2e2cacc --- /dev/null +++ b/examples/Hashcat/summarize.js @@ -0,0 +1,17 @@ +const fs = require('fs'); + +function summarizeResults() { + const crackedHashes = fs.readFileSync("cracked.txt", 'utf8').trim().split('\n'); + + console.log('Cracked hashes:', crackedHashes); + + const summary = { + cracked: crackedHashes.length, + total: crackedHashes.length, // For simplicity, assume all hashes are cracked + details: crackedHashes + }; + + console.log('Summary:', summary); +} + +summarizeResults() \ No newline at end of file diff --git a/examples/Hashcat/workflow.json b/examples/Hashcat/workflow.json new file mode 100644 index 0000000..7a177eb --- /dev/null +++ b/examples/Hashcat/workflow.json @@ -0,0 +1,140 @@ +{ + "name": "PasswordAudit", + "processes": [ + { + "name": "GenerateHashes", + "type": "dataflow", + "function": "submitRemoteJob", + "firingLimit": 1, + "config": { + "executor": { + "executable": "node", + "args": ["./generate.js"] + } + }, + "ins": [], + "outs": [0] + }, + { + "name": "FilterHashes", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./filter.js"] + } + }, + "ins": [0], + "outs": [1] + }, + { + "name": "RunHashcatMD5", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./hashcat.js", "md5"] + } + }, + "ins": [1], + "outs": [2] + }, + { + "name": "RunHashcatSHA1", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./hashcat.js", "sha1"] + } + }, + "ins": [1], + "outs": [3] + }, + { + "name": "RunHashcatSHA256", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./hashcat.js", "sha256"] + } + }, + "ins": [1], + "outs": [4] + }, + { + "name": "RunHashcatSHA512", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./hashcat.js", "sha512"] + } + }, + "ins": [1], + "outs": [5] + }, + { + "name": "RunHashcatSHA3-256", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./hashcat.js", "sha3-256"] + } + }, + "ins": [1], + "outs": [6] + }, + { + "name": "SummarizeResults", + "type": "dataflow", + "function": "submitRemoteJob", + "config": { + "executor": { + "executable": "node", + "args": ["./summarize.js"] + } + }, + "ins": [2, 3, 4, 5, 6], + "outs": [7] + } + ], + "signals": [ + + { + "name": 0 + }, + { + "name": 1 + }, + { + "name": 2 + }, + { + "name": 3 + }, + { + "name": 4 + }, + { + "name": 5 + }, + { + "name": 6 + }, + { + "name": 7 + } + ], + "ins": [], + "outs": [7] + } + \ No newline at end of file diff --git a/examples/HashcatKubernetes/Dockerfile b/examples/HashcatKubernetes/Dockerfile new file mode 100644 index 0000000..555213c --- /dev/null +++ b/examples/HashcatKubernetes/Dockerfile @@ -0,0 +1,50 @@ +FROM node:22-bullseye + +# Set npm registry +RUN npm config set registry https://registry.npmjs.org/ + +# Install job-executor globally +RUN npm install -g --loglevel verbose @marsel888/job-executor@1.4.8 + +# Update package lists and install required dependencies +RUN apt-get update && apt-get install -y \ + bash \ + coreutils \ + pciutils \ + build-essential \ + git \ + openssl \ + libssl-dev \ + libpcre3 \ + libpcre3-dev \ + zlib1g \ + zlib1g-dev \ + curl \ + p7zip-full \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Download and install pre-built Hashcat binaries +RUN curl -LO https://hashcat.net/files/hashcat-2.00.7z \ + && 7z x hashcat-2.00.7z -o/opt/ \ + && mv /opt/hashcat-2.00 /opt/hashcat \ + && chmod +x /opt/hashcat/hashcat-cli64.bin \ + && ln -s /opt/hashcat/hashcat-cli64.bin /usr/bin/hashcat \ + && chmod 755 /usr/bin/hashcat \ + && rm hashcat-2.00.7z + +# Verify installation +RUN echo $PATH +RUN which hashcat || echo "hashcat not in PATH" + +# Create a wrapper script for hashcat +RUN echo '#!/bin/bash' > /usr/local/bin/hashcat \ + && echo 'exec /opt/hashcat/hashcat-cli64.bin "$@"' >> /usr/local/bin/hashcat \ + && chmod +x /usr/local/bin/hashcat + +# Set up environment +ENV PATH="/opt/hashcat:${PATH}" + +RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 +RUN chmod +x /usr/local/bin/dumb-init +ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] \ No newline at end of file diff --git a/examples/HashcatKubernetes/DockerfileData b/examples/HashcatKubernetes/DockerfileData new file mode 100644 index 0000000..7775888 --- /dev/null +++ b/examples/HashcatKubernetes/DockerfileData @@ -0,0 +1,4 @@ +FROM busybox + +RUN mkdir /data +COPY * /data/ \ No newline at end of file diff --git a/examples/HashcatKubernetes/filter.js b/examples/HashcatKubernetes/filter.js new file mode 100755 index 0000000..24c2bfe --- /dev/null +++ b/examples/HashcatKubernetes/filter.js @@ -0,0 +1,27 @@ +const fs = require('fs'); + +function filterHashes() { + const hashes = fs.readFileSync("hashes.txt", 'utf8').trim().split('\n'); + + const groupedHashes = { + md5: [], + sha1: [], + sha256: [], + sha512: [], + }; + + hashes.forEach(line => { + const [hash, algorithm] = line.split(' '); + if (groupedHashes[algorithm]) { + groupedHashes[algorithm].push(hash); + } + }); + + // Write hashes to separate files by algorithm + Object.keys(groupedHashes).forEach(algorithm => { + const filename = `${algorithm}_hashes.txt`; + fs.writeFileSync(filename, groupedHashes[algorithm].join('\n'), 'utf8'); + }); +} + +filterHashes() \ No newline at end of file diff --git a/examples/HashcatKubernetes/generate.js b/examples/HashcatKubernetes/generate.js new file mode 100755 index 0000000..0d424ea --- /dev/null +++ b/examples/HashcatKubernetes/generate.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const crypto = require('crypto'); + +function randomString(maxLength) { + const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + let result = ''; + for (let i = 0; i < maxLength; i++) { + result += chars[Math.floor(Math.random() * chars.length)]; + } + return result; +} + +function generateHashes() { + const algorithms = ['md5', 'sha1', 'sha256', 'sha512', 'sha3-256']; + const proportions = [35, 25, 15, 15, 10]; // Percentages for each algorithm + + const totalHashes = 100; + const hashCounts = proportions.map(p => Math.floor((p / 100) * totalHashes)); + + const hashes = []; + + for (let i = 0; i < algorithms.length; i++) { + for (let j = 0; j < hashCounts[i]; j++) { + const randomStr = randomString(5); + const hash = crypto.createHash(algorithms[i]).update(randomStr).digest('hex'); + hashes.push({ hash, algorithm: algorithms[i] }); + } + } + + // Write all hashes to a single file + const allHashes = hashes.map(h => `${h.hash} ${h.algorithm}`).join('\n'); + fs.writeFileSync('hashes.txt', allHashes, 'utf8'); +} + +generateHashes() \ No newline at end of file diff --git a/examples/HashcatKubernetes/handler.js b/examples/HashcatKubernetes/handler.js new file mode 100644 index 0000000..e7bbb48 --- /dev/null +++ b/examples/HashcatKubernetes/handler.js @@ -0,0 +1,76 @@ +// Executor of 'jobs' using the Redis task status notification mechanism +const redis = require('redis'); +const { spawn } = require('child_process'); + +if (process.argv.length < 4) { + console.error("Usage: node handler.js "); + process.exit(1); +} + +// 'taskId' is the name of the Redis list to use for the notification +var taskId = process.argv[2], +redis_url = process.argv[3]; + +//console.log("taskId", taskId); +//console.log("redis_url", redis_url); + +var rcl = redis.createClient(redis_url); + +// get job message from Redis +var getJobMessage = async function (timeout) { + return new Promise(function (resolve, reject) { + const jobMsgKey = taskId + "_msg"; + rcl.brpop(jobMsgKey, timeout, function (err, reply) { + err ? reject(err): resolve(reply) + }); + }); +} + +// send notification about job completion to Redis +var notifyJobCompletion = async function () { + return new Promise(function (resolve, reject) { + rcl.rpush(taskId, "OK", function (err, reply) { + err ? reject(err): resolve(reply) + }); + }); +} + + +async function executeJob() { + + // 1. get job message + try { + var jobMessage = await getJobMessage(10); + } catch (err) { + console.error(err); + throw err; + } + //console.log("Received job message:", jobMessage); + + // 2. Execute job + var jm = JSON.parse(jobMessage[1]); + + const cmd = spawn(jm["executable"], jm["args"]); + + cmd.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cmd.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + cmd.on('close', async(code) => { + console.log(`child process exited with code ${code}`); + // 3. Notify job completion + try { + await notifyJobCompletion(); + } catch (err) { + console.error("Redis notification failed", err); + throw err; + } + process.exit(0); + }); + } + +executeJob() diff --git a/examples/HashcatKubernetes/hashcat.js b/examples/HashcatKubernetes/hashcat.js new file mode 100755 index 0000000..ab4cdfd --- /dev/null +++ b/examples/HashcatKubernetes/hashcat.js @@ -0,0 +1,44 @@ +const { execSync } = require('child_process'); + +function runHashcat(algorithm) { + const hashesFile = algorithm + '_hashes.txt'; // Hashes file // Algorithm name (e.g., 'md5', 'sha1') + const crackedFile = 'cracked.txt'; // Output file for cracked hashes + + // Map algorithms to Hashcat mode IDs + const algorithmModeMap = { + md5: 0, + sha1: 100, + sha256: 1400, + sha512: 1700 + }; + + const hashcatMode = algorithmModeMap[algorithm]; + if (hashcatMode === undefined) { + const error = new Error(`Unsupported algorithm: ${algorithm}`); + console.error(error.message); + return; + } + + const mask = '?a?a?a?a?a'; + console.log(`Running Hashcat for ${algorithm}...`); + + // Construct the Hashcat command + const command = `hashcat --potfile-disable -m ${hashcatMode} -a 3 -o ${crackedFile} ${hashesFile} ${mask}`; + + // Execute the Hashcat command + execSync(command, (error, stdout, stderr) => { + + if (error) { + console.error(`Hashcat Error: ${error.message}`); + return; + } + if (stderr) { + console.error(`Hashcat Stderr: ${stderr}`); + } + + console.log(`Hashcat Output:\n${stdout}`); + }); +} + +const args = process.argv.slice(2); +runHashcat(args[0]); \ No newline at end of file diff --git a/examples/HashcatKubernetes/package-lock.json b/examples/HashcatKubernetes/package-lock.json new file mode 100644 index 0000000..91bc622 --- /dev/null +++ b/examples/HashcatKubernetes/package-lock.json @@ -0,0 +1,322 @@ +{ + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "dependencies": { + "@stroncium/procfs": "^1.0.0", + "async": "^2.6.4", + "log4js": "^6.4.0", + "redis": "^3.1.1" + } + }, + "node_modules/@stroncium/procfs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@stroncium/procfs/-/procfs-1.2.1.tgz", + "integrity": "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==" + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + } + }, + "dependencies": { + "@stroncium/procfs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@stroncium/procfs/-/procfs-1.2.1.tgz", + "integrity": "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA==" + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + }, + "date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==" + }, + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "requires": { + "ms": "^2.1.3" + } + }, + "denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, + "flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "requires": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + } + }, + "redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "requires": { + "redis-errors": "^1.0.0" + } + }, + "rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==" + }, + "streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } + } +} diff --git a/examples/HashcatKubernetes/package.json b/examples/HashcatKubernetes/package.json new file mode 100644 index 0000000..bef6116 --- /dev/null +++ b/examples/HashcatKubernetes/package.json @@ -0,0 +1,14 @@ +{ + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "main": "handler.js", + "scripts": { + "start": "node handler.js" + }, + "dependencies": { + "@stroncium/procfs": "^1.0.0", + "async": "^2.6.4", + "log4js": "^6.4.0", + "redis": "^3.1.1" + } +} \ No newline at end of file diff --git a/examples/HashcatKubernetes/summarize.js b/examples/HashcatKubernetes/summarize.js new file mode 100755 index 0000000..2e2cacc --- /dev/null +++ b/examples/HashcatKubernetes/summarize.js @@ -0,0 +1,17 @@ +const fs = require('fs'); + +function summarizeResults() { + const crackedHashes = fs.readFileSync("cracked.txt", 'utf8').trim().split('\n'); + + console.log('Cracked hashes:', crackedHashes); + + const summary = { + cracked: crackedHashes.length, + total: crackedHashes.length, // For simplicity, assume all hashes are cracked + details: crackedHashes + }; + + console.log('Summary:', summary); +} + +summarizeResults() \ No newline at end of file diff --git a/examples/HashcatKubernetes/workflow.json b/examples/HashcatKubernetes/workflow.json new file mode 100644 index 0000000..21344a6 --- /dev/null +++ b/examples/HashcatKubernetes/workflow.json @@ -0,0 +1,177 @@ +{ + "name": "PasswordAudit", + "processes": [ + { + "name": "GenerateHashes", + "type": "dataflow", + "function": "{{function}}", + "firingLimit": 1, + "config": { + "executor": { + "executable": "node", + "args": [ + "./generate.js" + ] + } + }, + "ins": [], + "outs": [ + "hashes" + ] + }, + { + "name": "FilterHashes", + "type": "dataflow", + "firingLimit": 1, + "function": "{{function}}", + "config": { + "executor": { + "executable": "node", + "args": [ + "./filter.js" + ] + } + }, + "ins": [ + "hashes" + ], + "outs": [ + "filteredHashes" + ] + }, + { + "name": "RunHashcatMD5", + "type": "dataflow", + "firingLimit": 1, + "function": "{{function}}", + "config": { + "executor": { + "executable": "node", + "args": [ + "./hashcat.js", + "md5" + ] + } + }, + "ins": [ + "filteredHashes" + ], + "outs": [ + "crackedMD5" + ] + }, + { + "name": "RunHashcatSHA1", + "type": "dataflow", + "firingLimit": 1, + "function": "{{function}}", + "config": { + "executor": { + "executable": "node", + "args": [ + "./hashcat.js", + "sha1" + ] + } + }, + "ins": [ + "filteredHashes" + ], + "outs": [ + "crackedSHA1" + ] + }, + { + "name": "RunHashcatSHA256", + "type": "dataflow", + "firingLimit": 1, + "function": "{{function}}", + "config": { + "executor": { + "executable": "node", + "args": [ + "./hashcat.js", + "sha256" + ] + } + }, + "ins": [ + "filteredHashes" + ], + "outs": [ + "crackedSHA256" + ] + }, + { + "name": "RunHashcatSHA512", + "type": "dataflow", + "firingLimit": 1, + "function": "{{function}}", + "config": { + "executor": { + "executable": "node", + "args": [ + "./hashcat.js", + "sha512" + ] + } + }, + "ins": [ + "filteredHashes" + ], + "outs": [ + "crackedSHA512" + ] + }, + { + "name": "SummarizeResults", + "type": "dataflow", + "firingLimit": 1, + "function": "{{function}}", + "config": { + "executor": { + "executable": "node", + "args": [ + "./summarize.js" + ] + } + }, + "ins": [ + "crackedMD5", + "crackedSHA1", + "crackedSHA256", + "crackedSHA512" + ], + "outs": [ + "summary" + ] + } + ], + "signals": [ + { + "name": "hashes" + }, + { + "name": "filteredHashes" + }, + { + "name": "crackedMD5" + }, + { + "name": "crackedSHA1" + }, + { + "name": "crackedSHA256" + }, + { + "name": "crackedSHA512" + }, + { + "name": "summary" + } + ], + "ins": [], + "outs": [ + "summary" + ] +} diff --git a/examples/SpeedTest/Dockerfile b/examples/SpeedTest/Dockerfile new file mode 100644 index 0000000..189517b --- /dev/null +++ b/examples/SpeedTest/Dockerfile @@ -0,0 +1,34 @@ +FROM node:22-bullseye + +# Set npm registry +RUN npm config set registry https://registry.npmjs.org/ + +# Install job-executor globally +RUN npm install -g --loglevel verbose @marsel888/job-executor@1.4.8 + +# Update package lists and install required dependencies +RUN apt-get update && apt-get install -y \ + python3 \ + python3-pip \ + curl \ + dumb-init \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install speedtest-cli via pip +RUN pip3 install speedtest-cli + +# Verify installation +RUN which speedtest-cli || echo "speedtest-cli not in PATH" + +# Create a wrapper script for speedtest +RUN echo '#!/bin/bash' > /usr/local/bin/speedtest \ + && echo 'exec speedtest-cli "$@"' >> /usr/local/bin/speedtest \ + && chmod +x /usr/local/bin/speedtest + +# Download and configure dumb-init manually +RUN wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v1.2.5/dumb-init_1.2.5_x86_64 +RUN chmod +x /usr/local/bin/dumb-init + +# Set entrypoint +ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] diff --git a/examples/SpeedTest/DockerfileData b/examples/SpeedTest/DockerfileData new file mode 100644 index 0000000..7775888 --- /dev/null +++ b/examples/SpeedTest/DockerfileData @@ -0,0 +1,4 @@ +FROM busybox + +RUN mkdir /data +COPY * /data/ \ No newline at end of file diff --git a/examples/SpeedTest/handler.js b/examples/SpeedTest/handler.js new file mode 100644 index 0000000..e7bbb48 --- /dev/null +++ b/examples/SpeedTest/handler.js @@ -0,0 +1,76 @@ +// Executor of 'jobs' using the Redis task status notification mechanism +const redis = require('redis'); +const { spawn } = require('child_process'); + +if (process.argv.length < 4) { + console.error("Usage: node handler.js "); + process.exit(1); +} + +// 'taskId' is the name of the Redis list to use for the notification +var taskId = process.argv[2], +redis_url = process.argv[3]; + +//console.log("taskId", taskId); +//console.log("redis_url", redis_url); + +var rcl = redis.createClient(redis_url); + +// get job message from Redis +var getJobMessage = async function (timeout) { + return new Promise(function (resolve, reject) { + const jobMsgKey = taskId + "_msg"; + rcl.brpop(jobMsgKey, timeout, function (err, reply) { + err ? reject(err): resolve(reply) + }); + }); +} + +// send notification about job completion to Redis +var notifyJobCompletion = async function () { + return new Promise(function (resolve, reject) { + rcl.rpush(taskId, "OK", function (err, reply) { + err ? reject(err): resolve(reply) + }); + }); +} + + +async function executeJob() { + + // 1. get job message + try { + var jobMessage = await getJobMessage(10); + } catch (err) { + console.error(err); + throw err; + } + //console.log("Received job message:", jobMessage); + + // 2. Execute job + var jm = JSON.parse(jobMessage[1]); + + const cmd = spawn(jm["executable"], jm["args"]); + + cmd.stdout.on('data', (data) => { + console.log(`stdout: ${data}`); + }); + + cmd.stderr.on('data', (data) => { + console.error(`stderr: ${data}`); + }); + + cmd.on('close', async(code) => { + console.log(`child process exited with code ${code}`); + // 3. Notify job completion + try { + await notifyJobCompletion(); + } catch (err) { + console.error("Redis notification failed", err); + throw err; + } + process.exit(0); + }); + } + +executeJob() diff --git a/examples/SpeedTest/package.json b/examples/SpeedTest/package.json new file mode 100644 index 0000000..bef6116 --- /dev/null +++ b/examples/SpeedTest/package.json @@ -0,0 +1,14 @@ +{ + "name": "aws-posixfs-executor-test", + "version": "1.0.0", + "main": "handler.js", + "scripts": { + "start": "node handler.js" + }, + "dependencies": { + "@stroncium/procfs": "^1.0.0", + "async": "^2.6.4", + "log4js": "^6.4.0", + "redis": "^3.1.1" + } +} \ No newline at end of file diff --git a/examples/SpeedTest/speedtest.js b/examples/SpeedTest/speedtest.js new file mode 100644 index 0000000..b81c3b4 --- /dev/null +++ b/examples/SpeedTest/speedtest.js @@ -0,0 +1,34 @@ +const { exec } = require('child_process'); + +function runSpeedTestForDuration(durationSeconds = 10) { + console.log(`Running speed tests for ${durationSeconds} seconds...`); + + const endTime = Date.now() + durationSeconds * 1000; + + function runOnce() { + if (Date.now() >= endTime) { + console.log('Finished speed tests.'); + return; + } + + console.log(`Running speedtest-cli...`); + exec('speedtest-cli --bytes', (error, stdout, stderr) => { + if (error) { + console.error(`Speedtest error: ${error.message}`); + return; + } + if (stderr) { + console.error(`Speedtest stderr: ${stderr}`); + } + + console.log(`Speedtest output:\n${stdout}`); + + // Chain the next test + runOnce(); + }); + } + + runOnce(); +} + +runSpeedTestForDuration(60); \ No newline at end of file diff --git a/examples/SpeedTest/workflow.json b/examples/SpeedTest/workflow.json new file mode 100644 index 0000000..41285cd --- /dev/null +++ b/examples/SpeedTest/workflow.json @@ -0,0 +1,28 @@ +{ + "name": "SpeedTest", + "processes": [ + { + "name": "SpeedTest", + "type": "dataflow", + "function": "{{function}}", + "firingLimit": 1, + "config": { + "executor": { + "executable": "node", + "args": ["./speedtest.js"] + } + }, + "ins": [], + "outs": [0] + } + ], + "signals": [ + + { + "name": 0 + } + ], + "ins": [], + "outs": [0] + } + \ No newline at end of file