1
1
from __future__ import annotations
2
2
3
+ import os
3
4
import uuid
5
+ import shutil
4
6
from logging import getLogger
5
-
7
+ import jwt as jwtlib
6
8
from fastapi import APIRouter , Response
7
9
from tortoise .transactions import in_transaction
8
10
@@ -43,24 +45,29 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
43
45
if team_container :
44
46
a , b = team_container [0 ], team_container [1 :]
45
47
db_ports = await a .ports .all ().values ("port" ) # Get ports from DB
46
- ports = [db_port ["port" ]
47
- for db_port in db_ports ] # Create a list out of it
48
-
48
+ ports = [db_port ["port" ] for db_port in db_ports ] # Create a list out of it
49
+ static_url = f"{ config .staticfs_url } /{ a .token } " if ctf .static else None
49
50
for db_container in b :
50
51
try :
51
52
await db_container .delete ()
52
53
except Exception :
53
54
pass
54
-
55
- container = await containerASD .docker_client .containers .get (
56
- db_container .docker_id
57
- )
58
- await container .kill ()
59
- await container .delete ()
55
+ # containers won't exist for static ctfs
56
+ if ctf .static :
57
+ staticLocation = f"{ config .staticfs_data_dir } /{ team_id } /{ db_container .docker_id } "
58
+ if os .path .exists (staticLocation ):
59
+ shutil .rmtree (staticLocation )
60
+ else :
61
+ container = await containerASD .docker_client .containers .get (
62
+ db_container .docker_id
63
+ )
64
+ await container .kill ()
65
+ await container .delete ()
60
66
61
67
return {
62
68
"msg_code" : config .msg_codes ["container_already_running" ],
63
69
"ports" : ports ,
70
+ "static_url" : static_url ,
64
71
"ctf_id" : ctf_id ,
65
72
}
66
73
@@ -75,6 +82,53 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
75
82
container_name = f"{ team_id } _{ ctf_id } _{ uuid .uuid4 ().hex } "
76
83
container_flag = f"{ config .flag } {{{ uuid .uuid4 ().hex } }}"
77
84
85
+ if ctf .static :
86
+ container_id = uuid .uuid4 ().hex
87
+ payload = {
88
+ "id" : str (team_id ),
89
+ "containerId" : container_id ,
90
+ }
91
+ token = jwtlib .encode (payload , config .staticfs_jwt_secret , algorithm = "HS256" )
92
+ container = await containerASD .docker_client .containers .run (
93
+ name = container_name ,
94
+ config = {
95
+ "Image" : ctf .image_name ,
96
+ "AttachStdin" : False ,
97
+ "AttachStdout" : False ,
98
+ "AttachStderr" : False ,
99
+ "Tty" : False ,
100
+ "OpenStdin" : False ,
101
+ "HostConfig" : {
102
+ "AutoRemove" : True ,
103
+ "Binds" : [f"{ config .staticfs_data_dir } /{ team_id } /{ container_id } :/dist" ],
104
+ },
105
+ "Cmd" : ["/root/gen_flag" , container_flag ],
106
+ },
107
+ )
108
+ try :
109
+ async with in_transaction ():
110
+ db_container = await Container .create (
111
+ docker_id = container_id ,
112
+ team_id = team_id ,
113
+ problem_id = ctf_id ,
114
+ flag = container_flag ,
115
+ token = token ,
116
+ )
117
+ except Exception as err :
118
+ # Stop the container if failed to make a DB record
119
+ await container .kill ()
120
+ await container .delete ()
121
+ logger .exception ("Error while starting" , exc_info = err )
122
+
123
+ response .status_code = 500
124
+ return {"msg_code" : config .msg_codes ["db_error" ]}
125
+ return {
126
+ "msg_code" : config .msg_codes ["container_start" ],
127
+ "ports" : [],
128
+ "static_url" : f"{ config .staticfs_url } /{ token } " ,
129
+ "ctf_id" : ctf_id ,
130
+ }
131
+
78
132
# Run
79
133
container = await containerASD .docker_client .containers .run (
80
134
name = container_name ,
@@ -91,9 +145,9 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
91
145
},
92
146
)
93
147
94
- await (
95
- await container . exec ([ "/root/gen_flag" , container_flag ])
96
- ). start ( detach = True )
148
+ await (await container . exec ([ "/root/gen_flag" , container_flag ])). start (
149
+ detach = True
150
+ )
97
151
98
152
try :
99
153
async with in_transaction ():
@@ -126,6 +180,7 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
126
180
return {
127
181
"msg_code" : config .msg_codes ["container_start" ],
128
182
"ports" : ports ,
183
+ "static_url" : None ,
129
184
"ctf_id" : ctf_id ,
130
185
}
131
186
@@ -144,7 +199,11 @@ async def stopall_docker_container(response: Response, jwt: RequireJwt):
144
199
except Exception :
145
200
response .status_code = 500
146
201
return {"msg_code" : config .msg_codes ["db_error" ]}
147
-
202
+
203
+ team_path = f"{ config .staticfs_data_dir } /{ team_id } "
204
+ if os .path .exists (team_path ):
205
+ shutil .rmtree (team_path )
206
+
148
207
for db_container in containers :
149
208
container = await containerASD .docker_client .containers .get (
150
209
db_container ["docker_id" ]
@@ -178,6 +237,12 @@ async def stop_docker_container(ctf_id: int, response: Response, jwt: RequireJwt
178
237
response .status_code = 500
179
238
return {"msg_code" : config .msg_codes ["db_error" ]}
180
239
240
+ if ctf .static :
241
+ shutil .rmtree (
242
+ f"{ config .staticfs_data_dir } /{ team_id } /{ team_container .docker_id } "
243
+ )
244
+ return {"msg_code" : config .msg_codes ["container_stop" ]}
245
+
181
246
container = await containerASD .docker_client .containers .get (
182
247
team_container .docker_id
183
248
)
0 commit comments