11from __future__ import annotations
22
3+ import os
34import uuid
5+ import shutil
46from logging import getLogger
5-
7+ import jwt as jwtlib
68from fastapi import APIRouter , Response
79from tortoise .transactions import in_transaction
810
@@ -43,24 +45,29 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
4345 if team_container :
4446 a , b = team_container [0 ], team_container [1 :]
4547 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
4950 for db_container in b :
5051 try :
5152 await db_container .delete ()
5253 except Exception :
5354 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 ()
6066
6167 return {
6268 "msg_code" : config .msg_codes ["container_already_running" ],
6369 "ports" : ports ,
70+ "static_url" : static_url ,
6471 "ctf_id" : ctf_id ,
6572 }
6673
@@ -75,6 +82,53 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
7582 container_name = f"{ team_id } _{ ctf_id } _{ uuid .uuid4 ().hex } "
7683 container_flag = f"{ config .flag } {{{ uuid .uuid4 ().hex } }}"
7784
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+
78132 # Run
79133 container = await containerASD .docker_client .containers .run (
80134 name = container_name ,
@@ -91,9 +145,9 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
91145 },
92146 )
93147
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+ )
97151
98152 try :
99153 async with in_transaction ():
@@ -126,6 +180,7 @@ async def start_docker_container(ctf_id: int, response: Response, jwt: RequireJw
126180 return {
127181 "msg_code" : config .msg_codes ["container_start" ],
128182 "ports" : ports ,
183+ "static_url" : None ,
129184 "ctf_id" : ctf_id ,
130185 }
131186
@@ -144,7 +199,11 @@ async def stopall_docker_container(response: Response, jwt: RequireJwt):
144199 except Exception :
145200 response .status_code = 500
146201 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+
148207 for db_container in containers :
149208 container = await containerASD .docker_client .containers .get (
150209 db_container ["docker_id" ]
@@ -178,6 +237,12 @@ async def stop_docker_container(ctf_id: int, response: Response, jwt: RequireJwt
178237 response .status_code = 500
179238 return {"msg_code" : config .msg_codes ["db_error" ]}
180239
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+
181246 container = await containerASD .docker_client .containers .get (
182247 team_container .docker_id
183248 )
0 commit comments