def question_destroy(question): """ 销毁容器 :param question: :return: """ if not g.user: return make_response(jsonify({"msg": "请先登陆"}), 403) instance = db.query(Question).get(question) if not instance.active_flag: return make_response(jsonify({"msg": "静态题库无需动态生成"})) containers = db.query(ContainerResource, ImageResource).join(ImageResource, ImageResource.id == ContainerResource.image_resource_id). \ filter(ImageResource.question_id == instance.id, ContainerResource.user_id == g.user.id) for (container, image_resource) in containers: try: client = docker.DockerClient("http://{}".format( image_resource.host.addr), timeout=3) docker_container = client.containers.get(container.container_id) docker_container.kill() docker_container.remove() except docker_error.DockerException: pass db.session.delete(container) db.session.commit() return jsonify({"status": 0})
def put(self): data = request.get_json() pk = data.get("id") name = data.get("name").strip() instance = db.query(Role).filter(Role.id == pk).first() if not instance: raise exceptions.InstanceNotFount("资源不存在") if instance.name == name: return jsonify({}) if db.query(Role).filter(Role.name == name).count(): raise exceptions.ConstraintFailure("角色已存在") instance.name = name db.session.commit() return jsonify({})
def register(): """ 用户注册 """ if request.method == 'POST': username = request.form.get("username") password = request.form.get("password") password2 = request.form.get("password2") if not all([username, password, password2]): return render_template('login.html', error="用户名或密码不允许为空") user = db.query(User).filter(User.username == username).one_or_none() if user: return render_template('register.html', error="该用户名已注册") if password2 != password: return render_template('register.html', error="两次输入的密码不匹配") token = create_token() user = User(username=username, password=generate_password_hash(password), active=True, token=token) db.session.add(user) db.session.commit() response = make_response(redirect('/')) response.set_cookie("token", token) return response return render_template('register.html')
def delete(self, role_id): instance = db.query(Role).filter(Role.id == role_id).first() if not instance: raise exceptions.InstanceNotFount("资源不存在") db.session.delete(instance) db.session.commit() return jsonify({})
def delete(self, pk): """ 删除题库 判断是否是动态题库 动态题库删除容器 实体容器 镜像 :param : question 题目ID """ instance = db.session.query(Question).get(pk) if instance.active_flag: containers = db.query(ContainerResource).join(ImageResource, ImageResource.id == ContainerResource.image_resource_id). \ filter(ImageResource.question_id == instance.id) # kill for container in containers: db.session.delete(container) client = docker.DockerClient("http://{}".format( container.image.host.addr)) docker_container = client.containers.get( container.container_id) docker_container.stop() container.status = 2 # 删除镜像 db.session.delete(instance) db.session.commit() return jsonify({})
def put(self, pk): data = request.get_json() username = data.get('username') user = db.query(User).get(pk) if username: user.username = username db.session.commit() return jsonify({})
def post(self): data = request.get_json() name = data.get("name") if db.query(Role).filter(Role.name == name).count(): raise exceptions.ConstraintFailure("角色已存在") instance = Role(name=name) db.session.add(instance) db.session.commit() return jsonify({})
def submit_flag(question): """ 提交flag :param question: 题目ID :data flag: 提交的flag """ ip = request.remote_addr instance = db.query(Question).get(question) flag = request.get_json().get('flag') if not flag: return make_response(jsonify({"msg": "flag不允许为空"}), 400) if not g.user: return make_response(jsonify({"msg": "请登录"}), 403) answer = Answer(question_id=instance.id, user_id=g.user.id, flag=flag, ip=ip) if instance.active_flag: # 获取镜像资源 container = db.session.query(ContainerResource).join(ImageResource, ImageResource.id == ContainerResource.image_resource_id) \ .filter(ImageResource.question_id == instance.id, ContainerResource.user_id == g.user.id) \ .order_by(ContainerResource.id.desc()).first() # 获取用户容器 if container: try: client = docker.DockerClient("http://{}".format( container.image_resource.host.addr)) docker_container = client.containers.get( container.container_id) except docker_error.DockerException: return make_response(jsonify({"msg": "容器不在线"}), 502) if container.flag == flag: answer.correct = True # 销毁容器 docker_container.kill() docker_container.remove() db.session.delete(container) db.session.add(answer) db.session.commit() else: answer.correct = False db.session.add(answer) db.session.commit() return make_response(jsonify({"msg": "Flag错误"}), 400) else: return make_response({"msg": "容器损坏,请联系管理员或重启生成!"}) elif instance.flag == flag: answer.correct = True db.session.add(answer) db.session.commit() else: answer.correct = False db.session.add(answer) db.session.commit() return jsonify({"status": 400}) return jsonify({"status": 0})
def get(self): page = int(request.args.get('page', 1)) page_size = int(request.args.get("page_size", 10)) query = db.query(Role) page_query = query.paginate(page=page, per_page=page_size) data = [] for item in page_query.items: _item = dict() _item["id"] = item.id _item["name"] = item.name data.append(_item) return jsonify({"data": data, "total": page_query.total})
def index(): """ :return :首页 后端渲染 """ subject = request.args.get('subject') subjects = ("Web", "Crypto", "Pwn", "Iot", "Misc") query = db.session.query(Question) if subject: query = query.filter(Question.type == subject.lower()).order_by( Question.id.desc()) solved_qid = [] if g.user: # 我已解决的题目 solved_question = db.query(Answer.question_id).filter( Answer.user_id == g.user.id, Answer.correct == True).all() solved_qid = [i[0] for i in solved_question] data = [] links = {} if g.user: # 获取镜像资源 containers = db.session.query(ContainerResource,ImageResource.question_id) \ .join(ImageResource, ImageResource.id == ContainerResource.image_resource_id ) \ .join(User, User.id == ContainerResource.user_id).order_by(ContainerResource.id.desc()).all() # 获取用户容器 for c in containers: container, question_id = c links[question_id] = [ "%s:%s" % (container.addr, container.container_port) ] for item in query: data.append({ "active_flag": item.active_flag, "id": item.id, "links": links.get(item.id, []), "type": item.type, "desc": item.desc, "name": item.name, "integral": item.integral, "solved": 100, "date_created": item.date_created.strftime("%y-%m-%d"), "has_solved": True if item.id in solved_qid else False }) response = make_response( render_template('index.html', user=g.user, challenges=data, subjects=subjects, subject=subject)) if not g.user: response.delete_cookie('token') return response
def challenge_detail(question): """ 题目详情 包括已解决的用户情况 点赞情况 :param question: :return: """ instance = db.query(Question).get(question) if g.user and instance.active_flag: # 获取镜像资源 container = db.session.query(ContainerResource) \ .join(ImageResource, ImageResource.id == ContainerResource.image_resource_id ) \ .join(User, User.id == ContainerResource.user_id).filter(ImageResource.question_id == instance.id, \ User.id == g.user.id) \ .order_by(ContainerResource.id.desc()).first() # 获取用户容器 if container: links = ["%s:%s" % (container.addr, container.container_port)] else: links = [] else: links = [] # 附件 question_file = db.session.query(QuestionFile).filter( QuestionFile.question_id == instance.id).all() data = { "links": links, "id": instance.id, "name": instance.name, "question_file": question_file, "desc": instance.desc, "active_flag": instance.active_flag, "type": instance.type, "solved": db.session.query(Answer).filter( Answer.question_id == instance.id, Answer.status == Answer.status_ok).count(), "date_created": instance.date_created.strftime("%y-%m-%d") } return render_template('challengeDetail.html', item=data)
def login(): """ 用户登录 """ if request.method == 'POST': username = request.form.get("username") password = request.form.get("password") if not all([username, password]): return render_template('login.html', error="用户名或密码不允许为空") user = db.query(User).filter(User.username == username).one_or_none() if user and check_password_hash(user.password, password): token = create_token() user.token = token db.session.commit() response = make_response(redirect('/')) response.set_cookie("token", token) return response else: return render_template('login.html', error="用户名或密码不允许为空") return render_template('login.html')
def build_delay(task: int, host, build_type, tag, admin, pt=None, dockerfile=None): """ 编译镜像 """ with flask_app.app_context(): task = db.query(TaskList).get(task) instance = db.session.query(Host).filter(Host.id == host).one_or_none() cli = APIClient(base_url='tcp://{}'.format(instance.addr)) if build_type == 'tar': f = open(pt, 'rb') for line in cli.build(fileobj=f, rm=True, tag=tag, custom_context=True): print(line) task_add_log(task.id, line) task.status = task.STATUS_DONE elif build_type == 'pull': for line in cli.pull(tag, stream=True, decode=True): task_add_log(task.id, line) task.status = task.STATUS_DONE else: try: f = BytesIO(dockerfile.encode('utf-8')) for line in cli.build(fileobj=f, rm=True, tag=tag): task_add_log(task.id, line) task.status = task.STATUS_DONE except docker_error.DockerException as e: task.status = task.STATUS_ERROR task.remark = str(e) db.session.commit()
def submit_flag(question): """ 提交flag :param question: 题目ID :data flag: 提交的flag """ ip = get_ip() instance = db.query(Question).get(question) flag = request.get_json().get('flag') if not flag: return make_response(jsonify({"msg": "flag不允许为空"}), 400) if not g.user: return make_response(jsonify({"msg": "请登录"}), 403) answer = Answer(question_id=instance.id, user_id=g.user.id, flag=flag, ip=ip) # 判断是否有正确的提交记录 is_answer = db.session.query(Answer).filter( Answer.question_id == instance.id, Answer.user_id == g.user.id, Answer.status == Answer.status_ok).count() if instance.active_flag: # 获取镜像资源 container = db.session.query(ContainerResource).join(ImageResource, ImageResource.id == ContainerResource.image_resource_id) \ .filter(ImageResource.question_id == instance.id, ContainerResource.user_id == g.user.id) \ .order_by(ContainerResource.id.desc()).first() if not container: answer.status = answer.status_error db.session.commit() return make_response(jsonify({"msg": "题库无效,请联系管理员或重新生成!"}), 400) # 判断是否是作弊 ok_container = db.session.query(ContainerResource) \ .join(ImageResource, ContainerResource.image_resource_id == ImageResource.id) \ .filter(ContainerResource.flag == flag, ImageResource.question_id == instance.id).first() if ok_container and ok_container != container: # 作弊 answer.status = answer.status_cheat db.session.add(answer) db.session.commit() return make_response(jsonify({"msg": "请勿作弊"}), 400) try: client = docker.DockerClient("http://{}".format( container.image_resource.host.addr)) docker_container = client.containers.get(container.container_id) except docker_error.DockerException: return make_response(jsonify({"msg": "容器不在线"}), 400) if container.flag == flag: answer.score = instance.integral # 判断是否作弊 answer.status = answer.status_repeat if is_answer else answer.status_ok # 销毁容器 docker_container.kill() docker_container.remove() db.session.delete(container) db.session.add(answer) db.session.commit() else: answer.status = answer.status_error db.session.add(answer) db.session.commit() return make_response(jsonify({"msg": "Flag错误!"}), 400) elif instance.flag == flag: answer.score = instance.integral answer.status = answer.status_repeat if is_answer else answer.status_ok db.session.add(answer) db.session.commit() else: answer.status = answer.status_error db.session.add(answer) db.session.commit() return make_response(jsonify({"msg": "flag错误!"}), 400) return jsonify({"status": 0})
def question_start(question): """ 创建一个题目容器 :param question: :return: """ if not g.user: return make_response(jsonify({"msg": "请先登陆"}), 403) user = g.user instance = db.query(Question).get(question) if not instance.active_flag: return make_response(jsonify({"msg": "静态题库无需动态生成"})) image_resource = db.query(ImageResource).filter( ImageResource.question_id == instance.id).one_or_none() if not image_resource: return make_response(jsonify({"msg": "服务器没有资源"}), 400) connect_url = "http://" + image_resource.host.addr client = docker.DockerClient(connect_url) image = client.images.get(image_resource.image_id) # 解析镜像端口 image_config = image.attrs["ContainerConfig"] random_port = "" if "ExposedPorts" in image_config: port_dict = image.attrs["ContainerConfig"]["ExposedPorts"] for docker_port, host_port in port_dict.items(): # docker_port_int = docker_port.replace("/", "").replace("tcp", "").replace("udp", "") random_port = str(random.randint(10000, 65536)) port_dict[docker_port] = random_port else: port_dict = {} image_name = image.attrs["RepoTags"][0].replace(":", ".") container_name = f"{image_name}_{user.id}" # 检查docker 是否已存在 try: c = client.containers.get(container_name) c.stop() c.remove() except docker.errors.NotFound: pass docker_container_response = client.containers.run(image=image.id, name=container_name, ports=port_dict, detach=True) # 获取创建的容器 docker_container = client.containers.get(container_name) flag = generate_flag() command = "/bin/bash /start.sh '{}'".format(flag) command_response = docker_container.exec_run(cmd=command, detach=True) # 创建容器记录 container = ContainerResource(image_resource_id=image_resource.id, flag=flag) container.addr = image_resource.host.ip container.container_id = docker_container_response.attrs["Id"] container.image_id = image.attrs["Id"] container.container_name = container_name container.container_status = docker_container_response.attrs["State"][ "Status"] container.container_port = random_port container.user_id = user.id # 创建容器 db.session.add(container) db.session.commit() return jsonify({"status": 0})