forked from glzjin/CTFd-Whale
-
Notifications
You must be signed in to change notification settings - Fork 29
/
__init__.py
124 lines (107 loc) · 4.25 KB
/
__init__.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import fcntl
import warnings
import requests
from flask import Blueprint, render_template, session, current_app, request
from flask_apscheduler import APScheduler
from CTFd.api import CTFd_API_v1
from CTFd.plugins import (
register_plugin_assets_directory,
register_admin_plugin_menu_bar,
)
from CTFd.plugins.challenges import CHALLENGE_CLASSES
from CTFd.utils import get_config, set_config
from CTFd.utils.decorators import admins_only
from .api import user_namespace, admin_namespace, AdminContainers
from .challenge_type import DynamicValueDockerChallenge
from .utils.checks import WhaleChecks
from .utils.control import ControlUtil
from .utils.db import DBContainer
from .utils.docker import DockerUtils
from .utils.exceptions import WhaleWarning
from .utils.setup import setup_default_configs
from .utils.routers import Router
def load(app):
app.config['RESTX_ERROR_404_HELP'] = False
# upgrade()
plugin_name = __name__.split('.')[-1]
set_config('whale:plugin_name', plugin_name)
app.db.create_all()
if not get_config("whale:setup"):
setup_default_configs()
register_plugin_assets_directory(
app, base_path=f"/plugins/{plugin_name}/assets",
endpoint='plugins.ctfd-whale.assets'
)
register_admin_plugin_menu_bar(
title='Whale',
route='/plugins/ctfd-whale/admin/settings'
)
DynamicValueDockerChallenge.templates = {
"create": f"/plugins/{plugin_name}/assets/create.html",
"update": f"/plugins/{plugin_name}/assets/update.html",
"view": f"/plugins/{plugin_name}/assets/view.html",
}
DynamicValueDockerChallenge.scripts = {
"create": "/plugins/ctfd-whale/assets/create.js",
"update": "/plugins/ctfd-whale/assets/update.js",
"view": "/plugins/ctfd-whale/assets/view.js",
}
CHALLENGE_CLASSES["dynamic_docker"] = DynamicValueDockerChallenge
page_blueprint = Blueprint(
"ctfd-whale",
__name__,
template_folder="templates",
static_folder="assets",
url_prefix="/plugins/ctfd-whale"
)
CTFd_API_v1.add_namespace(admin_namespace, path="/plugins/ctfd-whale/admin")
CTFd_API_v1.add_namespace(user_namespace, path="/plugins/ctfd-whale")
worker_config_commit = None
@page_blueprint.route('/admin/settings')
@admins_only
def admin_list_configs():
nonlocal worker_config_commit
errors = WhaleChecks.perform()
if not errors and get_config("whale:refresh") != worker_config_commit:
worker_config_commit = get_config("whale:refresh")
DockerUtils.init()
Router.reset()
set_config("whale:refresh", "false")
return render_template('whale_config.html', errors=errors)
@page_blueprint.route("/admin/containers")
@admins_only
def admin_list_containers():
result = AdminContainers.get()
view_mode = request.args.get('mode', session.get('view_mode', 'list'))
session['view_mode'] = view_mode
return render_template("whale_containers.html",
plugin_name=plugin_name,
containers=result['data']['containers'],
pages=result['data']['pages'],
curr_page=abs(request.args.get("page", 1, type=int)),
curr_page_start=result['data']['page_start'])
def auto_clean_container():
with app.app_context():
results = DBContainer.get_all_expired_container()
for r in results:
ControlUtil.try_remove_container(r.user_id)
app.register_blueprint(page_blueprint)
try:
Router.check_availability()
DockerUtils.init()
except Exception:
warnings.warn("Initialization Failed. Please check your configs.", WhaleWarning)
try:
lock_file = open("/tmp/ctfd_whale.lock", "w")
lock_fd = lock_file.fileno()
fcntl.lockf(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
scheduler.add_job(
id='whale-auto-clean', func=auto_clean_container,
trigger="interval", seconds=10
)
print("[CTFd Whale] Started successfully")
except IOError:
pass