forked from DownUnderCTF/ctfd-kubectf-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkube_challenge.py
106 lines (89 loc) · 3.97 KB
/
kube_challenge.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import math
from os import path
from CTFd.models import Challenges, Solves, db
from CTFd.plugins.dynamic_challenges import DynamicValueChallenge
from CTFd.utils.modes import get_model
from CTFd.plugins.dynamic_challenges.decay import DECAY_FUNCTIONS, logarithmic
from .routes import blueprint
PLUGIN_FOLDER_NAME = path.basename(path.dirname(__file__))
class KubeChallenge(Challenges):
__mapper_args__ = {"polymorphic_identity": "kubectf"}
id = db.Column(db.Integer,
db.ForeignKey("challenges.id", ondelete="CASCADE"),
primary_key=True)
template_name = db.Column(db.String(255), index=False, default="")
initial = db.Column(db.Integer, default=0)
minimum = db.Column(db.Integer, default=0)
decay = db.Column(db.Integer, default=0)
function = db.Column(db.String(32), default="logarithmic_custom")
def __init__(self, *args, **kwargs):
super(KubeChallenge, self).__init__(**kwargs)
self.template_name = kwargs["template_name"]
self.value = kwargs["initial"]
class KubeChallengeType(DynamicValueChallenge):
id = "kubectf" # Unique identifier used to register challenges
name = "kubectf" # Name of a challenge type
templates = { # Templates used for each aspect of challenge editing & viewing
"create": f"/plugins/{PLUGIN_FOLDER_NAME}/templates/create.html",
"update": f"/plugins/{PLUGIN_FOLDER_NAME}/templates/update.html",
"view": f"/plugins/{PLUGIN_FOLDER_NAME}/assets/view.html",
}
scripts = { # Scripts that are loaded when a template is loaded
"create": f"/plugins/{PLUGIN_FOLDER_NAME}/assets/create.js",
"update": f"/plugins/{PLUGIN_FOLDER_NAME}/assets/update.js",
"view": f"/plugins/{PLUGIN_FOLDER_NAME}/assets/view.js",
}
# Route at which files are accessible. This must be registered using register_plugin_assets_directory()
route = f"/plugins/{PLUGIN_FOLDER_NAME}/assets/"
# Blueprint used to access the static_folder directory.
blueprint = blueprint
challenge_model = KubeChallenge
@classmethod
def read(cls, challenge):
"""
This method is in used to access the data of a challenge in a format processable by the front end.
:param challenge:
:return: Challenge object, data dictionary to be returned to the user
"""
challenge = KubeChallenge.query.filter_by(id=challenge.id).first()
data = {
"id": challenge.id,
"name": challenge.name,
"value": challenge.value,
"initial": challenge.initial,
"decay": challenge.decay,
"minimum": challenge.minimum,
"template_name": challenge.template_name,
"description": challenge.description,
"category": challenge.category,
"state": challenge.state,
"max_attempts": challenge.max_attempts,
"type": challenge.type,
"type_data": {
"id": cls.id,
"name": cls.name,
"templates": cls.templates,
"scripts": cls.scripts,
},
}
return data
@classmethod
def update(cls, challenge, request):
"""
This method is used to update the information associated with a challenge. This should be kept strictly to the
Challenges table and any child tables.
:param challenge:
:param request:
:return:
"""
data = request.form or request.get_json()
for attr, value in data.items():
# We need to set these to floats so that the next operations don't operate on strings
if attr in ("initial", "minimum", "decay"):
value = float(value)
setattr(challenge, attr, value)
return KubeChallengeType.calculate_value(challenge)
@classmethod
def solve(cls, user, team, challenge, request):
super().solve(user, team, challenge, request)
KubeChallengeType.calculate_value(challenge)