Beispiel #1
0
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})
Beispiel #2
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({})
Beispiel #3
0
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')
Beispiel #4
0
 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({})
Beispiel #5
0
    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({})
Beispiel #6
0
 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({})
Beispiel #7
0
 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({})
Beispiel #8
0
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})
Beispiel #9
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})
Beispiel #10
0
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
Beispiel #11
0
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)
Beispiel #12
0
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')
Beispiel #13
0
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()
Beispiel #14
0
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})
Beispiel #15
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})