diff --git a/challenges_sample/knock/knock.tar.gz b/challenges_sample/knock/knock.tar.gz
new file mode 100644
index 00000000..2895b7f4
Binary files /dev/null and b/challenges_sample/knock/knock.tar.gz differ
diff --git a/challenges_sample/knock/knock/Dockerfile b/challenges_sample/knock/knock/Dockerfile
new file mode 100644
index 00000000..f14059ae
--- /dev/null
+++ b/challenges_sample/knock/knock/Dockerfile
@@ -0,0 +1,15 @@
+FROM node:17.4.0-buster-slim
+
+RUN mkdir -p /app
+
+WORKDIR /app
+
+COPY package.json .
+
+RUN yarn
+
+COPY . .
+
+USER node
+
+CMD ["node", "index.js"]
diff --git a/challenges_sample/knock/knock/challenge.yaml b/challenges_sample/knock/knock/challenge.yaml
new file mode 100644
index 00000000..60edf523
--- /dev/null
+++ b/challenges_sample/knock/knock/challenge.yaml
@@ -0,0 +1,26 @@
+name: knock-knock
+author: BrownieInMotion
+description: |-
+ Knock knock? Who's there? Another pastebin!!
+
+ ${link_main_0}
+
+flag: dice{1_d00r_y0u_d00r_w3_a11_d00r_f0r_1_d00r}
+
+provide:
+ - ./index.js
+ - ./Dockerfile
+
+containers:
+ main:
+ build: .
+ ports:
+ - 3000
+ environment:
+ FLAG: "dice{1_d00r_y0u_d00r_w3_a11_d00r_f0r_1_d00r}"
+
+expose:
+ main:
+ - target: 3000
+ http: knock-knock
+ healthContent: Create Paste
diff --git a/challenges_sample/knock/knock/index.js b/challenges_sample/knock/knock/index.js
new file mode 100644
index 00000000..82844e68
--- /dev/null
+++ b/challenges_sample/knock/knock/index.js
@@ -0,0 +1,62 @@
+const crypto = require('crypto');
+
+class Database {
+ constructor() {
+ this.notes = [];
+ this.secret = `secret-${crypto.randomUUID}`;
+ }
+
+ createNote({ data }) {
+ const id = this.notes.length;
+ this.notes.push(data);
+ return {
+ id,
+ token: this.generateToken(id),
+ };
+ }
+
+ getNote({ id, token }) {
+ if (token !== this.generateToken(id)) return { error: 'invalid token' };
+ if (id >= this.notes.length) return { error: 'note not found' };
+ return { data: this.notes[id] };
+ }
+
+ generateToken(id) {
+ return crypto
+ .createHmac('sha256', this.secret)
+ .update(id.toString())
+ .digest('hex');
+ }
+}
+
+const db = new Database();
+db.createNote({ data: process.env.FLAG });
+
+const express = require('express');
+const app = express();
+
+app.use(express.urlencoded({ extended: false }));
+app.use(express.static('public'));
+
+app.post('/create', (req, res) => {
+ const data = req.body.data ?? 'no data provided.';
+ const { id, token } = db.createNote({ data: data.toString() });
+ res.redirect(`/note?id=${id}&token=${token}`);
+});
+
+app.get('/note', (req, res) => {
+ const { id, token } = req.query;
+ const note = db.getNote({
+ id: parseInt(id ?? '-1'),
+ token: (token ?? '').toString(),
+ });
+ if (note.error) {
+ res.send(note.error);
+ } else {
+ res.send(note.data);
+ }
+});
+
+app.listen(3000, () => {
+ console.log('listening on port 3000');
+});
diff --git a/challenges_sample/knock/knock/package.json b/challenges_sample/knock/knock/package.json
new file mode 100644
index 00000000..d4227a06
--- /dev/null
+++ b/challenges_sample/knock/knock/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "knock-knock",
+ "version": "1.0.0",
+ "main": "index.js",
+ "license": "MIT",
+ "dependencies": {
+ "express": "^4.17.2"
+ }
+}
diff --git a/challenges_sample/knock/knock/public/index.html b/challenges_sample/knock/knock/public/index.html
new file mode 100644
index 00000000..526b2dc5
--- /dev/null
+++ b/challenges_sample/knock/knock/public/index.html
@@ -0,0 +1,45 @@
+
+
+
+
Create Paste
+
+
diff --git a/challenges_sample/knock/knock/yarn.lock b/challenges_sample/knock/knock/yarn.lock
new file mode 100644
index 00000000..1dd58a8c
--- /dev/null
+++ b/challenges_sample/knock/knock/yarn.lock
@@ -0,0 +1,352 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+accepts@~1.3.7:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
+ integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+ dependencies:
+ mime-types "~2.1.34"
+ negotiator "0.6.3"
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
+
+body-parser@1.19.1:
+ version "1.19.1"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4"
+ integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==
+ dependencies:
+ bytes "3.1.1"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "~1.1.2"
+ http-errors "1.8.1"
+ iconv-lite "0.4.24"
+ on-finished "~2.3.0"
+ qs "6.9.6"
+ raw-body "2.4.2"
+ type-is "~1.6.18"
+
+bytes@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a"
+ integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==
+
+content-disposition@0.5.4:
+ version "0.5.4"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
+ integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
+ dependencies:
+ safe-buffer "5.2.1"
+
+content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
+
+cookie@0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
+ integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
+
+debug@2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+
+destroy@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
+ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+
+encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+
+express@^4.17.2:
+ version "4.17.2"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3"
+ integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==
+ dependencies:
+ accepts "~1.3.7"
+ array-flatten "1.1.1"
+ body-parser "1.19.1"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.4.1"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "~1.1.2"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "~1.1.2"
+ fresh "0.5.2"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "~2.3.0"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.7"
+ qs "6.9.6"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.17.2"
+ serve-static "1.14.2"
+ setprototypeof "1.2.0"
+ statuses "~1.5.0"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+finalhandler@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
+ integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.3"
+ statuses "~1.5.0"
+ unpipe "~1.0.0"
+
+forwarded@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
+ integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
+
+http-errors@1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
+ integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.4"
+ setprototypeof "1.2.0"
+ statuses ">= 1.5.0 < 2"
+ toidentifier "1.0.1"
+
+iconv-lite@0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+inherits@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+ipaddr.js@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
+
+mime-db@1.51.0:
+ version "1.51.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c"
+ integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==
+
+mime-types@~2.1.24, mime-types@~2.1.34:
+ version "2.1.34"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24"
+ integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==
+ dependencies:
+ mime-db "1.51.0"
+
+mime@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@2.1.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+negotiator@0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+ integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
+on-finished@~2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
+ dependencies:
+ ee-first "1.1.1"
+
+parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+ integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
+
+proxy-addr@~2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
+ integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
+ dependencies:
+ forwarded "0.2.0"
+ ipaddr.js "1.9.1"
+
+qs@6.9.6:
+ version "6.9.6"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee"
+ integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==
+
+range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32"
+ integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==
+ dependencies:
+ bytes "3.1.1"
+ http-errors "1.8.1"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+safe-buffer@5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+"safer-buffer@>= 2.1.2 < 3":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+send@0.17.2:
+ version "0.17.2"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820"
+ integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==
+ dependencies:
+ debug "2.6.9"
+ depd "~1.1.2"
+ destroy "~1.0.4"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "1.8.1"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "~2.3.0"
+ range-parser "~1.2.1"
+ statuses "~1.5.0"
+
+serve-static@1.14.2:
+ version "1.14.2"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa"
+ integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.17.2"
+
+setprototypeof@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+ integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+
+toidentifier@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+ integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+type-is@~1.6.18:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
diff --git a/challenges_sample/vmcalc/vmcalc.tar.gz b/challenges_sample/vmcalc/vmcalc.tar.gz
new file mode 100644
index 00000000..bbb690f8
Binary files /dev/null and b/challenges_sample/vmcalc/vmcalc.tar.gz differ
diff --git a/challenges_sample/vmcalc/vmcalc/.dockerignore b/challenges_sample/vmcalc/vmcalc/.dockerignore
new file mode 100644
index 00000000..068a90cc
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/.dockerignore
@@ -0,0 +1,4 @@
+.dockerignore
+challenge.yaml
+dist.tar
+Dockerfile
\ No newline at end of file
diff --git a/challenges_sample/vmcalc/vmcalc/Dockerfile b/challenges_sample/vmcalc/vmcalc/Dockerfile
new file mode 100644
index 00000000..a73f8305
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/Dockerfile
@@ -0,0 +1,17 @@
+FROM --platform=linux/amd64 node:16.13.1-bullseye-slim
+
+RUN mkdir -p /app
+
+WORKDIR /app
+
+COPY package.json .
+
+RUN npm install
+
+COPY . .
+
+USER node
+
+EXPOSE 3000
+
+CMD ["node", "index.js"]
\ No newline at end of file
diff --git a/challenges_sample/vmcalc/vmcalc/challenge.yaml b/challenges_sample/vmcalc/vmcalc/challenge.yaml
new file mode 100644
index 00000000..be4e3614
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/challenge.yaml
@@ -0,0 +1,17 @@
+name: vm-calc
+deployed: false
+author: Strellic
+description: |-
+ A simple and very secure online calculator!
+
+ [instancer.mc.ax/vm-calc](https://instancer.mc.ax/vm-calc)
+
+flag:
+ file: flag.txt
+
+provide:
+ - ./dist.tar
+
+containers:
+ main:
+ build: .
diff --git a/challenges_sample/vmcalc/vmcalc/dist.tar b/challenges_sample/vmcalc/vmcalc/dist.tar
new file mode 100644
index 00000000..1e091ce3
Binary files /dev/null and b/challenges_sample/vmcalc/vmcalc/dist.tar differ
diff --git a/challenges_sample/vmcalc/vmcalc/flag.txt b/challenges_sample/vmcalc/vmcalc/flag.txt
new file mode 100644
index 00000000..00bb3c76
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/flag.txt
@@ -0,0 +1 @@
+dice{y0u_4re_a_tru3_vm2_j4ilbreak3r!!!}
\ No newline at end of file
diff --git a/challenges_sample/vmcalc/vmcalc/index.js b/challenges_sample/vmcalc/vmcalc/index.js
new file mode 100644
index 00000000..f5ddfa02
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/index.js
@@ -0,0 +1,69 @@
+const express = require('express');
+const fsp = require('fs/promises');
+const crypto = require('crypto');
+
+const { NodeVM } = require('vm2');
+const vm = new NodeVM({
+ eval: false,
+ wasm: false,
+ wrapper: 'none',
+ strict: true
+});
+
+const PORT = 3000;
+
+const users = [
+ { user: "strellic", pass: "4136805643780af20755baddcc947d20f7e38e52f421c3c89a5a8b9d8a8d1da7" },
+ { user: "ginkoid", pass: "cdf72d24394745eab295c6e047ee41aaec62f56bd41e2cea4ef7d244d96b51dd" }
+];
+
+const sha256 = (data) => crypto.createHash('sha256').update(data).digest('hex');
+
+const app = express();
+
+app.set("view engine", "hbs");
+
+app.use(express.urlencoded({ extended: false }));
+
+app.get("/", (req, res) => res.render("index"));
+app.post("/", (req, res) => {
+ const { calc } = req.body;
+
+ if(!calc) {
+ return res.render("index");
+ }
+
+ let result;
+ try {
+ result = vm.run(`return ${calc}`);
+ }
+ catch(err) {
+ console.log(err);
+ return res.render("index", { result: "There was an error running your calculation!"});
+ }
+
+ if(typeof result !== "number") {
+ return res.render("index", { result: "Nice try..."});
+ }
+
+ res.render("index", { result });
+});
+
+app.get("/admin", (req, res) => res.render("admin"));
+
+app.post("/admin", async (req, res) => {
+ let { user, pass } = req.body;
+ if(!user || !pass || typeof user !== "string" || typeof pass !== "string") {
+ return res.render("admin", { error: "Missing username or password!" });
+ }
+
+ let hash = sha256(pass);
+ if(users.filter(u => u.user === user && u.pass === hash)[0] !== undefined) {
+ res.render("admin", { flag: await fsp.readFile("flag.txt") });
+ }
+ else {
+ res.render("admin", { error: "Incorrect username or password!" });
+ }
+});
+
+app.listen(PORT, () => console.log(`vm-calc listening on port ${PORT}`));
\ No newline at end of file
diff --git a/challenges_sample/vmcalc/vmcalc/package.json b/challenges_sample/vmcalc/vmcalc/package.json
new file mode 100644
index 00000000..859d2aa3
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "vm-calc",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "Strellic",
+ "license": "ISC",
+ "dependencies": {
+ "express": "^4.17.2",
+ "hbs": "^4.2.0",
+ "vm2": "^3.9.5"
+ }
+}
diff --git a/challenges_sample/vmcalc/vmcalc/views/admin.hbs b/challenges_sample/vmcalc/vmcalc/views/admin.hbs
new file mode 100644
index 00000000..b2fc9dd9
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/views/admin.hbs
@@ -0,0 +1,33 @@
+
+
+
+ vm-calc | admin
+
+
+
+
+
+
+ Login:
+ {{#if error}}
+ Error: {{error}}
+ {{/if}}
+ {{#if flag}}
+ Flag: {{flag}}
+ {{/if}}
+
+
+
+
+
\ No newline at end of file
diff --git a/challenges_sample/vmcalc/vmcalc/views/index.hbs b/challenges_sample/vmcalc/vmcalc/views/index.hbs
new file mode 100644
index 00000000..b23ea779
--- /dev/null
+++ b/challenges_sample/vmcalc/vmcalc/views/index.hbs
@@ -0,0 +1,28 @@
+
+
+
+ vm-calc
+
+
+
+
+
+
+ Enter math expression here:
+
+ {{#if result}}
+ Result: {{result}}
+ {{/if}}
+
+
+
\ No newline at end of file
diff --git a/katana-services b/katana-services
index 34fb4743..a79e56b2 160000
--- a/katana-services
+++ b/katana-services
@@ -1 +1 @@
-Subproject commit 34fb47432e1118a50ca0f6f0a99e858a115b320f
+Subproject commit a79e56b2458f84a42fa51d293fa1bce036af57b5
diff --git a/kubernetes/manifests/wireguard-lb.yml b/kubernetes/manifests/wireguard-lb.yml
new file mode 100644
index 00000000..bdefc85e
--- /dev/null
+++ b/kubernetes/manifests/wireguard-lb.yml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ k8s-app: wireguard
+ name: wireguard
+ namespace: katana
+spec:
+ type: LoadBalancer
+ ports:
+ - port: 51820
+ protocol: UDP
+ targetPort: 51820
+ selector:
+ app: wireguard
diff --git a/kubernetes/templates/runtime/teams.yml b/kubernetes/templates/runtime/teams.yml
index b47b7e1c..82c4683c 100644
--- a/kubernetes/templates/runtime/teams.yml
+++ b/kubernetes/templates/runtime/teams.yml
@@ -52,4 +52,16 @@ spec:
valueFrom:
configMapKeyRef:
name: teamvm-config
- key: ssh_password
\ No newline at end of file
+ key: ssh_password
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: tsuka-svc
+spec:
+ selector:
+ app: {{.TeamLabel}}
+ ports:
+ - protocol: TCP
+ port: 22
+ type: ClusterIP
\ No newline at end of file
diff --git a/kubernetes/templates/runtime/wireguard.yml b/kubernetes/templates/runtime/wireguard.yml
new file mode 100644
index 00000000..aae6e8ab
--- /dev/null
+++ b/kubernetes/templates/runtime/wireguard.yml
@@ -0,0 +1,75 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: wireguard-configmap
+ namespace: katana
+data:
+ #REQUIRED VARIABLES
+ PUID: "1000" # User ID, default 1000
+ PGID: "1000" # Group ID
+ TZ: "Etc/UTC" # Timezone
+ PEERS: "2" # Comma separated list of peer names
+
+ #OPTIONAL VARIABLES
+ SERVERURL: "{{.WireguardIP}}" #if not set, container tries to determine auto and mostly tells wrong, use lb ip here , pass dynamically best
+ SERVERPORT: "51820"
+ INTERNAL_SUBNET: "10.13.13.0" #Wireguard tunnel's internal addresses
+ PEERDNS: "10.0.0.10"
+ INTERFACE: "katana_wg"
+ ALLOWEDIPS: "0.0.0.0/0" #This is set for users, they can obv change it, so better to give 0.0.0.0/0 as nahi to append karni padti cheezein
+ #PERSISTENTKEEPALIVE_PEERS: (optional) , it is set to 25 by default (confirm?)
+ LOG_CONFS: "true" #optional , true by default
+ # POSTUP: "echo 1 > /proc/sys/net/ipv4/ip_forward; iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE"
+ POSTUP : "iptables -I OUTPUT -i katana_wg -s 10.13.13.2/32 -j DROP; iptables -I INPUT -i katana_wg -s 10.13.13.2/32 -j DROP"
+ #iptables -I INPUT -i katana_wg -j DROP;
+ #-d 10.0.1.42
+ #iptables -I OUTPUT -i katana_wg -s 10.13.13.2/32 -j DROP
+ #POSTDOWN: "iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE"
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: wireguard-deployment
+ namespace: katana
+ labels:
+ app: wireguard
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: wireguard
+ template:
+ metadata:
+ labels:
+ app: wireguard
+ spec:
+ containers:
+ - name: wireguard
+ image: harbor.katana.local/katana/wireguard
+ imagePullPolicy: Always
+ envFrom:
+ - configMapRef:
+ name: wireguard-configmap
+ securityContext:
+ capabilities:
+ add:
+ - NET_ADMIN
+ - SYS_MODULE
+ privileged: true
+ volumeMounts:
+ - name: wg-config
+ mountPath: /config
+ ports:
+ - containerPort: 51820
+ protocol: UDP
+ resources:
+ requests:
+ memory: "64Mi"
+ cpu: "100m"
+ limits:
+ memory: "128Mi"
+ cpu: "200m"
+ volumes:
+ - name: wg-config
+ emptyDir: {}
\ No newline at end of file
diff --git a/lib/harbor/api.go b/lib/harbor/api.go
index 24ed505d..7207931f 100644
--- a/lib/harbor/api.go
+++ b/lib/harbor/api.go
@@ -56,7 +56,7 @@ func setAdminPassword() error {
resp, _ = httpClient.Do(req)
if resp.StatusCode != 200 {
- return fmt.Errorf("error changing admin password")
+ return fmt.Errorf("error changing admin password, response code is %d", resp.StatusCode)
}
return nil
diff --git a/lib/utils/crypto.go b/lib/utils/crypto.go
index 9a9d4055..b3a06323 100644
--- a/lib/utils/crypto.go
+++ b/lib/utils/crypto.go
@@ -42,6 +42,12 @@ func GenerateCerts(domain string, basePath string) error {
return err
}
+ // using -traditional flag to get PKCS#1 [different header], otherwise 500 Internal Error
+ cmd = "openssl rsa -in " + basePath + "/" + domain + ".key -out " + basePath + "/" + domain + ".key -traditional"
+ if err := RunCommand(cmd); err != nil {
+ return err
+ }
+
// Generate private key
cmd = "openssl genrsa -out " + basePath + "/" + domain + ".key 4096"
if err := RunCommand(cmd); err != nil {
diff --git a/lib/utils/docker.go b/lib/utils/docker.go
index 42eac8f9..48c51e85 100644
--- a/lib/utils/docker.go
+++ b/lib/utils/docker.go
@@ -38,6 +38,11 @@ func dockerLogin(username string, password string) {
log.Println("Logged into Harbor successfully")
}
+func CheckDockerfile(_DockerfilePath string) bool {
+ _, err := os.Stat(_DockerfilePath + "/Dockerfile")
+ return !os.IsNotExist(err)
+}
+
func BuildDockerImage(_ChallengeName string, _DockerfilePath string) {
buf := new(bytes.Buffer)
if err := Tar(_DockerfilePath, buf); err != nil {
@@ -50,6 +55,9 @@ func BuildDockerImage(_ChallengeName string, _DockerfilePath string) {
return
}
+ log.Println(_ChallengeName)
+ log.Println(_DockerfilePath)
+
log.Println("Building Docker image, Please wait......")
imageBuildResponse, err := cli.ImageBuild(
diff --git a/lib/utils/kube.go b/lib/utils/kube.go
index 921bf794..d5b1ebec 100644
--- a/lib/utils/kube.go
+++ b/lib/utils/kube.go
@@ -3,6 +3,7 @@ package utils
import (
"bytes"
"context"
+ "fmt"
"io"
"io/ioutil"
"log"
@@ -96,6 +97,88 @@ func GetMongoIP() string {
return service.Spec.ClusterIP
}
+func CopyFromPod(podName string, containerName string, pathInPod string, localFilePath string, ns ...string) error {
+ config, err := GetKubeConfig()
+ if err != nil {
+ return err
+ }
+
+ client, err := GetKubeClient()
+ if err != nil {
+ return err
+ }
+
+ namespace := "katana"
+ if len(ns) > 0 {
+ namespace = ns[0]
+ }
+
+ pod, err := client.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
+ if err != nil {
+ log.Printf("Error getting pod: %s\n", err)
+ }
+
+ // Find the container in the pod
+ var container *corev1.Container
+ for _, c := range pod.Spec.Containers {
+ if c.Name == containerName {
+ container = &c
+ break
+ }
+ }
+
+ if container == nil {
+ log.Printf("Container not found in pod\n")
+ err = fmt.Errorf("container not found in pod")
+ return err
+ }
+
+ // Create a stream to the container
+ req := client.CoreV1().RESTClient().Post().
+ Resource("pods").
+ Name(podName).
+ Namespace(namespace).
+ SubResource("exec").
+ Param("container", containerName)
+
+ req.VersionedParams(&corev1.PodExecOptions{
+ Container: containerName,
+ Command: []string{"cat", pathInPod},
+ Stdin: false,
+ Stdout: true,
+ Stderr: true,
+ TTY: false,
+ }, scheme.ParameterCodec)
+
+ exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
+ if err != nil {
+ log.Printf("Error creating executor: %s\n", err)
+ return err
+ }
+
+ localFile, err := os.Create(localFilePath)
+ if err != nil {
+ log.Printf("Error creating local file: %s\n", err)
+ return err
+ }
+ defer localFile.Close()
+
+ // Stream the file
+ err = exec.Stream(remotecommand.StreamOptions{
+ Stdin: nil,
+ Stdout: localFile,
+ Stderr: os.Stderr,
+ Tty: false,
+ })
+ if err != nil {
+ log.Printf("Error streaming the file: %s\n", err)
+ return err
+ }
+
+ log.Println("File copied successfully")
+ return nil
+}
+
func GetKatanaLoadbalancer() string {
client, err := GetKubeClient()
if err != nil {
@@ -135,6 +218,7 @@ func DeploymentConfig() types.ManifestConfig {
HarborCrt: "",
HarborCaCrt: "",
HarborIP: "",
+ WireguardIP: "",
NodeAffinityValue: "",
}
diff --git a/lib/wireguard/firewall.go b/lib/wireguard/firewall.go
new file mode 100644
index 00000000..ba78798f
--- /dev/null
+++ b/lib/wireguard/firewall.go
@@ -0,0 +1,87 @@
+package wireguard
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strconv"
+
+ g "github.com/sdslabs/katana/configs"
+)
+
+func ApplyFirewall() error {
+
+ //Read challenges folder
+ dir, err := os.Open("./challenges")
+
+ if err != nil {
+ log.Println("Error in opening challenges folder")
+ return err
+ }
+ defer dir.Close()
+
+ fileInfos, err := dir.Readdir(-1)
+ if err != nil {
+ log.Println("Error in reading challenges folder")
+ return err
+ }
+
+ //Store challenge names in a slice
+ challengeNames := make([]string, 0)
+ for _, fileInfo := range fileInfos {
+ if fileInfo.IsDir() {
+ challengeNames = append(challengeNames, fileInfo.Name())
+ }
+ }
+
+ numberOfTeams := g.ClusterConfig.TeamCount
+ teamIPs := make([]string, 0)
+
+ baseip := "10.13.13."
+ //add team ips to teamIPs
+ for i := 0; i < int(numberOfTeams); i++ {
+ teamIPs = append(teamIPs, baseip+strconv.Itoa(i+2)+"/32")
+ }
+
+ //create a slice of string to store iptables commands
+ IpTable := make([]string, 0)
+
+ //add iptables rules to block all internet traffic
+ for i := 0; i < int(numberOfTeams); i++ {
+ IpTable = append(IpTable, "iptables -I FORWARD -s "+teamIPs[i]+" -o eth+ -j DROP")
+ }
+
+ //add iptables rules to allow traffic to all challenges service
+ for i := 0; i < int(numberOfTeams); i++ {
+ for j := 0; j < len(challengeNames); j++ {
+ for k := 0; k < int(numberOfTeams); k++ {
+ IpTable = append(IpTable, "iptables -I FORWARD -s "+teamIPs[i]+" -d "+challengeNames[j]+"-svc-"+strconv.Itoa(k)+".katana-team-"+strconv.Itoa(k)+"-ns.svc.cluster.local -j ACCEPT")
+ }
+ }
+ }
+
+ //add iptables rules to allow access to masterpod
+ for i := 0; i < int(numberOfTeams); i++ {
+ IpTable = append(IpTable, "iptables -I FORWARD -s "+teamIPs[i]+" -d tsuka-svc.katana-team-"+strconv.Itoa(i)+"-ns.svc.cluster.local -j ACCEPT")
+ }
+
+ //append all iptables rules to a string
+ finalIprules := ""
+ for i := 0; i < len(IpTable); i++ {
+ finalIprules += IpTable[i] + "; "
+ }
+
+ //Overwrite firewall.conf by this string stored in the root directory
+ filepath, err := os.Getwd()
+ if err != nil {
+ log.Println(err)
+ }
+ filepath = filepath + "/katana-services/Wireguard/root/defaults/firewall.conf"
+ err = os.WriteFile(filepath, []byte(finalIprules), 0644)
+ if err != nil {
+ fmt.Println("Error writing to file:", err)
+ return err
+ }
+
+ return nil
+}
diff --git a/lib/wireguard/setup.go b/lib/wireguard/setup.go
new file mode 100644
index 00000000..45be9c98
--- /dev/null
+++ b/lib/wireguard/setup.go
@@ -0,0 +1,126 @@
+package wireguard
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "html/template"
+ "log"
+ "os"
+ "path/filepath"
+ "strconv"
+ "time"
+
+ "github.com/sdslabs/katana/configs"
+ "github.com/sdslabs/katana/lib/deployment"
+ "github.com/sdslabs/katana/lib/utils"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func SetupWireguard() error {
+ kubeConfig, _ := utils.GetKubeConfig()
+ kubeClient, _ := utils.GetKubeClient()
+
+ namespace := "katana"
+
+ manifest := &bytes.Buffer{}
+
+ tmpl, err := template.ParseFiles(filepath.Join(configs.ClusterConfig.TemplatedManifestDir, "runtime", "wireguard.yml"))
+ if err != nil {
+ return err
+ }
+
+ deploymentConfig := utils.DeploymentConfig()
+
+ serviceName := "wireguard"
+
+ service, err := kubeClient.CoreV1().Services(namespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
+ if err != nil {
+ return err
+ }
+
+ wireguard_lbIP := service.Status.LoadBalancer.Ingress
+
+ deploymentConfig.WireguardIP = wireguard_lbIP[0].IP
+
+ if err := tmpl.Execute(manifest, deploymentConfig); err != nil {
+ return err
+ }
+
+ if err = deployment.ApplyManifest(kubeConfig, kubeClient, manifest.Bytes(), namespace); err != nil {
+ return err
+ }
+
+ noOfTeams := int(configs.ClusterConfig.TeamCount)
+
+ configPath, err := os.Getwd()
+ if err != nil {
+ log.Println(err)
+ return err
+ }
+ configPath = configPath + "/peer_configs"
+ _, err = os.Stat(configPath)
+ if os.IsNotExist(err) {
+ err = os.MkdirAll(configPath, os.ModePerm)
+ if err != nil {
+ fmt.Printf("Error creating folder: %v\n", err)
+ } else {
+ fmt.Println("peer_configs folder created successfully.")
+ }
+ } else if err != nil {
+ fmt.Printf("Error checking folder existence: %v\n", err)
+ }
+
+ for i := 0; i < noOfTeams; i++ {
+ if err := GetConfigFiles(strconv.Itoa(i + 1)); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func GetConfigFiles(team_number string) error {
+
+ client, _ := utils.GetKubeClient()
+
+ deploymentNames := []string{
+ "wireguard-deployment",
+ }
+ namespace := "katana"
+
+ for _, deploymentName := range deploymentNames {
+ if err := utils.WaitForDeploymentReady(client, deploymentName, namespace); err != nil {
+ log.Printf("Error testing deployment '%s': %v\n", deploymentName, err)
+ }
+ }
+
+ //get pod in the wireguard deployment
+ pods, err := client.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{
+ LabelSelector: "app=wireguard",
+ })
+ if err != nil {
+ log.Printf("Error getting pod: %s\n", err)
+ }
+
+ wireguardPod := pods.Items[0]
+ wireguardContainer := wireguardPod.Spec.Containers[0]
+
+ pathInPod := "/config/peer" + team_number + "/peer" + team_number + ".conf"
+ localFilePath := "./peer_configs/peer" + team_number + ".conf"
+
+ //wait for container ready
+ time.Sleep(1 * time.Minute)
+ // [TODO] : Replace time.Sleep with waitForContainerRunning
+ // if err := waitForContainerRunning(client, wireguardPod.Name, wireguardContainer.Name, namespace, 10*time.Minute); err != nil {
+ // log.Printf("Error waiting for container to become running: %v\n", err)
+ // }
+
+ if err := utils.CopyFromPod(wireguardPod.Name, wireguardContainer.Name, pathInPod, localFilePath, namespace); err != nil {
+ log.Println(err)
+ return err
+ }
+
+ return nil
+
+}
diff --git a/services/challengedeployerservice/controller.go b/services/challengedeployerservice/controller.go
index d4185a1b..f46bff33 100644
--- a/services/challengedeployerservice/controller.go
+++ b/services/challengedeployerservice/controller.go
@@ -3,6 +3,12 @@ package challengedeployerservice
import (
"context"
"fmt"
+ "log"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+
git "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/gofiber/fiber/v2"
@@ -12,11 +18,6 @@ import (
"github.com/sdslabs/katana/lib/utils"
"github.com/sdslabs/katana/types"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "log"
- "os"
- "regexp"
- "strconv"
- "strings"
)
func Deploy(c *fiber.Ctx) error {
@@ -62,7 +63,7 @@ func Deploy(c *fiber.Ctx) error {
log.Println("Dockerfile not found in the " + folderName + " challenge folder. Please follow proper format.")
} else {
//Update challenge path to get dockerfile
- utils.BuildDockerImage(folderName, challengePath+"/"+folderName + "/" + folderName)
+ utils.BuildDockerImage(folderName, challengePath+"/"+folderName+"/"+folderName)
clusterConfig := g.ClusterConfig
numberOfTeams := clusterConfig.TeamCount
diff --git a/services/infrasetservice/controller.go b/services/infrasetservice/controller.go
index 6a266768..93146165 100644
--- a/services/infrasetservice/controller.go
+++ b/services/infrasetservice/controller.go
@@ -20,6 +20,7 @@ import (
"github.com/sdslabs/katana/lib/mongo"
"github.com/sdslabs/katana/lib/mysql"
utils "github.com/sdslabs/katana/lib/utils"
+ "github.com/sdslabs/katana/lib/wireguard"
"github.com/sdslabs/katana/types"
coreV1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -37,8 +38,9 @@ func InfraSet(c *fiber.Ctx) error {
log.Fatal(err)
}
+ log.Println("Creating harbor certs ...")
generateCertsforHarbor()
-
+ log.Println("Created harbor certs ...")
if err = deployment.DeployCluster(config, kubeclient); err != nil {
log.Fatal(err)
}
@@ -48,8 +50,18 @@ func InfraSet(c *fiber.Ctx) error {
log.Fatal(err)
}
+ err = wireguard.ApplyFirewall()
+ if err != nil {
+ log.Fatal(err)
+ }
+
buildKatanaServices()
+ err = wireguard.SetupWireguard()
+ if err != nil {
+ log.Fatal(err)
+ }
+
return c.SendString("Infrastructure setup completed")
}
diff --git a/services/infrasetservice/helper.go b/services/infrasetservice/helper.go
index c42bbdd0..71b344ce 100644
--- a/services/infrasetservice/helper.go
+++ b/services/infrasetservice/helper.go
@@ -19,6 +19,7 @@ func generateCertsforHarbor() {
path, _ := os.Getwd()
path = path + "/lib/harbor/certs"
+ log.Println("CHECK 1")
// Delete the directory if it already exists
if _, err := os.Stat(path); os.IsExist(err) {
errDir := os.RemoveAll(path)
@@ -26,18 +27,19 @@ func generateCertsforHarbor() {
log.Fatal(err)
}
}
-
+ log.Println("CHECK 2")
if _, err := os.Stat(path); os.IsNotExist(err) {
errDir := os.Mkdir(path, 0755)
if errDir != nil {
log.Fatal(err)
}
}
-
+ log.Println("CHECK 3")
// Generate the certificates
if err := utils.GenerateCerts("harbor.katana.local", path); err != nil {
log.Fatal(err)
}
+ log.Println("CHECK 4")
}
func createTeamCredentials(teamNumber int) (string, types.CTFTeam) {
@@ -95,6 +97,9 @@ func envVariables(gogs string, pwd string, podNamespace string) {
func buildKatanaServices() {
katanaDir, err := utils.GetKatanaRootPath()
+ if err != nil {
+ log.Fatal(err)
+ }
katanaServicesDir := katanaDir + "/katana-services"
services, err := os.ReadDir(katanaServicesDir)
@@ -103,7 +108,16 @@ func buildKatanaServices() {
}
for _, service := range services {
- if service.Name() == ".github" {
+
+ invalidServiceNames := []string{".github", ".git", ".gitignore"}
+ found := false
+ for _, invalidName := range invalidServiceNames {
+ if service.Name() == invalidName {
+ found = true
+ break
+ }
+ }
+ if found {
continue
}
if service.IsDir() {
diff --git a/types/deployment.go b/types/deployment.go
index 4237db42..3ec33920 100644
--- a/types/deployment.go
+++ b/types/deployment.go
@@ -25,6 +25,7 @@ type ManifestConfig struct {
HarborCrt string
HarborCaCrt string
HarborIP string
+ WireguardIP string
NodeAffinityValue string
}