create-oss-store 1.0.0
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/create-oss-store.js +8 -0
- package/package.json +37 -0
- package/src/index.js +143 -0
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-oss-store",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Create a new OSS – OopsSec Store instance for web security CTF training",
|
|
6
|
+
"author": "kOaDT",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/kOaDT/oss-oopssec-store"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"ctf",
|
|
14
|
+
"security",
|
|
15
|
+
"vulnerable",
|
|
16
|
+
"web-security",
|
|
17
|
+
"owasp",
|
|
18
|
+
"penetration-testing",
|
|
19
|
+
"create",
|
|
20
|
+
"cli"
|
|
21
|
+
],
|
|
22
|
+
"bin": {
|
|
23
|
+
"create-oss-store": "./bin/create-oss-store.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"chalk": "^5.3.0",
|
|
34
|
+
"degit": "^2.8.4",
|
|
35
|
+
"ora": "^8.1.1"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { spawn } from "child_process";
|
|
2
|
+
import { writeFileSync, existsSync } from "fs";
|
|
3
|
+
import { resolve, join } from "path";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
import degit from "degit";
|
|
7
|
+
|
|
8
|
+
const REPO = "kOaDT/oss-oopssec-store";
|
|
9
|
+
|
|
10
|
+
export async function createOssStore(projectName) {
|
|
11
|
+
console.log();
|
|
12
|
+
console.log(chalk.bold("OSS – OopsSec Store"));
|
|
13
|
+
console.log(chalk.dim("Vulnerable Web Application for Security Training"));
|
|
14
|
+
console.log();
|
|
15
|
+
|
|
16
|
+
if (!projectName) {
|
|
17
|
+
projectName = "oss-oopssec-store";
|
|
18
|
+
console.log(
|
|
19
|
+
chalk.yellow(`No project name provided, using "${projectName}"`)
|
|
20
|
+
);
|
|
21
|
+
console.log();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const targetPath = resolve(process.cwd(), projectName);
|
|
25
|
+
|
|
26
|
+
if (existsSync(targetPath)) {
|
|
27
|
+
console.log(chalk.red(`Error: Directory "${projectName}" already exists.`));
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Clone repository
|
|
32
|
+
const cloneSpinner = ora("Cloning repository...").start();
|
|
33
|
+
try {
|
|
34
|
+
const emitter = degit(REPO, { cache: false, force: true });
|
|
35
|
+
await emitter.clone(targetPath);
|
|
36
|
+
cloneSpinner.succeed("Repository cloned");
|
|
37
|
+
} catch (error) {
|
|
38
|
+
cloneSpinner.fail("Failed to clone repository");
|
|
39
|
+
console.error(chalk.red(error.message));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Create .env file
|
|
44
|
+
const envSpinner = ora("Creating .env file...").start();
|
|
45
|
+
try {
|
|
46
|
+
const envPath = join(targetPath, ".env");
|
|
47
|
+
const dbPath = join(targetPath, "prisma", "dev.db");
|
|
48
|
+
writeFileSync(envPath, `DATABASE_URL="file:${dbPath}"\n`);
|
|
49
|
+
envSpinner.succeed(".env file created");
|
|
50
|
+
} catch (error) {
|
|
51
|
+
envSpinner.fail("Failed to create .env file");
|
|
52
|
+
console.error(chalk.red(error.message));
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Install dependencies
|
|
57
|
+
const installSpinner = ora("Installing dependencies...").start();
|
|
58
|
+
try {
|
|
59
|
+
await runCommand("npm", ["install"], targetPath);
|
|
60
|
+
installSpinner.succeed("Dependencies installed");
|
|
61
|
+
} catch (error) {
|
|
62
|
+
installSpinner.fail("Failed to install dependencies");
|
|
63
|
+
console.error(chalk.red(error.message));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Generate Prisma client
|
|
68
|
+
const prismaSpinner = ora("Generating Prisma client...").start();
|
|
69
|
+
try {
|
|
70
|
+
await runCommand("npm", ["run", "db:generate"], targetPath);
|
|
71
|
+
prismaSpinner.succeed("Prisma client generated");
|
|
72
|
+
} catch (error) {
|
|
73
|
+
prismaSpinner.fail("Failed to generate Prisma client");
|
|
74
|
+
console.error(chalk.red(error.message));
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Push database schema
|
|
79
|
+
const dbSpinner = ora("Setting up database...").start();
|
|
80
|
+
try {
|
|
81
|
+
await runCommand("npm", ["run", "db:push"], targetPath);
|
|
82
|
+
dbSpinner.succeed("Database schema pushed");
|
|
83
|
+
} catch (error) {
|
|
84
|
+
dbSpinner.fail("Failed to push database schema");
|
|
85
|
+
console.error(chalk.red(error.message));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Seed database
|
|
90
|
+
const seedSpinner = ora("Seeding database with CTF flags...").start();
|
|
91
|
+
try {
|
|
92
|
+
await runCommand("npm", ["run", "db:seed"], targetPath);
|
|
93
|
+
seedSpinner.succeed("Database seeded");
|
|
94
|
+
} catch (error) {
|
|
95
|
+
seedSpinner.fail("Failed to seed database");
|
|
96
|
+
console.error(chalk.red(error.message));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Success message
|
|
101
|
+
console.log();
|
|
102
|
+
console.log(chalk.green.bold("Setup complete!"));
|
|
103
|
+
console.log();
|
|
104
|
+
console.log("To start hunting for flags:");
|
|
105
|
+
console.log();
|
|
106
|
+
console.log(chalk.cyan(` cd ${projectName}`));
|
|
107
|
+
console.log(chalk.cyan(" npm run dev"));
|
|
108
|
+
console.log();
|
|
109
|
+
console.log(
|
|
110
|
+
`Then open ${chalk.underline("http://localhost:3000")} in your browser.`
|
|
111
|
+
);
|
|
112
|
+
console.log();
|
|
113
|
+
console.log(chalk.dim("Good luck finding all the flags!"));
|
|
114
|
+
console.log();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function runCommand(command, args, cwd) {
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
const child = spawn(command, args, {
|
|
120
|
+
cwd,
|
|
121
|
+
stdio: "pipe",
|
|
122
|
+
shell: process.platform === "win32",
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
let stderr = "";
|
|
126
|
+
|
|
127
|
+
child.stderr.on("data", (data) => {
|
|
128
|
+
stderr += data.toString();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
child.on("close", (code) => {
|
|
132
|
+
if (code === 0) {
|
|
133
|
+
resolve();
|
|
134
|
+
} else {
|
|
135
|
+
reject(new Error(stderr || `Command failed with code ${code}`));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
child.on("error", (error) => {
|
|
140
|
+
reject(error);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|