def delete_container(task_id): """ 删除容器任务 :param task_id: 任务id """ task_info = TaskInfo.objects.filter(task_id=task_id, task_status=1).first() if not task_info: return operation_args = task_info.operation_args args = json.loads(operation_args) container_id = args["container_id"] container_vul = ContainerVul.objects.filter( container_id=container_id).first() msg = R.ok(msg="删除成功") if container_vul: # docker 连接容器ID docker_container_id = container_vul.docker_container_id try: # 连接Docker容器 docker_container = client.containers.get(docker_container_id) # 停止容器运行 docker_container.stop() # 删除容器 docker_container.remove() except Exception: pass finally: container_vul.delete() msg = R.ok(msg="删除成功") task_info.task_status = 3 task_info.task_msg = json.dumps(msg) task_info.update_date = timezone.now() task_info.save() print("删除漏洞容器成功,任务ID:%s" % (task_id, ))
def stop_container(task_id): """ 停止 docker 容器 :param task_id: task id """ task_info = TaskInfo.objects.filter(task_id=task_id, task_status=1).first() if not task_info: return operation_args = task_info.operation_args args = json.loads(operation_args) container_id = args["container_id"] container_vul = ContainerVul.objects.filter(container_id=container_id).first() msg = R.ok(msg="停止成功") if container_vul: docker_container_id = container_vul.docker_container_id try: # 连接 Docker 容器 docker_container = client.containers.get(docker_container_id) docker_container.stop() container_vul.container_status = 'stop' container_vul.save() msg = R.ok(msg="停止成功") except NotFound: container_vul.delete() msg = R.ok(msg="停止成功") except Exception: msg = R.err(msg="停止失败,服务器内部错误") # execute finish task_info.task_status = 3 task_info.task_msg = json.dumps(msg) task_info.update_date = timezone.now() task_info.save() print("停止漏洞容器成功,任务ID:%s" % (task_id, ))
def get_task(self, request, pk=None): task_info = self.get_object() task_msg = task_info.task_msg if task_info.task_status == 1: return JsonResponse( R.running(msg="执行中", data=str(task_info.task_id))) task_info.is_show = True task_info.save() if task_msg: msg = json.loads(task_msg) if msg["status"] == 200: if not msg["data"]: msg["data"] = {"_now": int(timezone.now().timestamp())} else: msg["data"]["_now"] = int(timezone.now().timestamp()) try: HTTP_HOST = request.META.get("HTTP_REFERER") # 判断前端的请求地址是IP形式或者是域名形式 if HTTP_HOST.count(":") < 2: HTTP_HOST = HTTP_HOST.replace("http://", "").replace( "https://", "") origin_host = msg["data"]["host"].split(":") if len(origin_host) >= 2 and HTTP_HOST: msg["data"][ "host"] = HTTP_HOST[: -1] + ":" + origin_host[ 1] except Exception as e: pass return JsonResponse(msg, status=200) else: return JsonResponse(msg, status=200) return JsonResponse(R.ok())
def create_run_container_task(container_vul, user_info): """ 创建运行容器任务 :param container_vul: 漏洞容器对象 :param user_info: 用户信息 """ image_info = container_vul.image_id image_name = image_info.image_name image_port = image_info.image_port user_id = user_info.id args = { "image_name": image_name, "user_id": user_id, "image_port": image_port } task_info = None if container_vul.container_status == "running": vul_port = container_vul.vul_port vul_host = container_vul.vul_host task_msg = R.ok(data={"host": vul_host, "port": vul_port, "id": str(container_vul.container_id)}) task_info = TaskInfo.objects.filter(operation_args=json.dumps(args), task_msg=json.dumps(task_msg), operation_type=2, task_name="运行容器:" + image_name, user_id=user_id).first() if not task_info: task_info = TaskInfo.objects.filter(operation_args=json.dumps(args), task_msg="", task_status=1, user_id=user_id, operation_type=2, task_name="运行容器:" + image_name).first() if not task_info: task_info = TaskInfo(task_name="运行容器:" + image_name, user_id=user_id, task_status=1, operation_type=2, operation_args=json.dumps(args), task_msg="", create_date=timezone.now(), update_date=timezone.now()) task_info.save() return str(task_info.task_id)
def get_layout(self, request, pk=None): if not pk or pk == "undefined": return JsonResponse(R.build(msg="环境不存在")) user = request.user if user.is_superuser: layout_info = Layout.objects.filter(layout_id=pk).first() else: layout_info = Layout.objects.filter(layout_id=pk, is_release=True).first() if not layout_info: return JsonResponse(R.build(msg="环境不存在或未发布")) layout_path = os.path.join(DOCKER_COMPOSE, str(layout_info.layout_id)) layout_data = LayoutData.objects.filter(layout_id=layout_info, file_path="docker-compose" + layout_path.replace(DOCKER_COMPOSE, ""), ).first() open_host_list = [] is_run = False if layout_data and layout_data.status == 'running': service_container_list = LayoutServiceContainer.objects.filter(layout_user_id=layout_data) for service_container in service_container_list: service_info = service_container.service_id container_host = service_container.container_host if service_info.is_exposed: if container_host: open_host_list.extend(container_host.split(",")) is_run = True result_data = { "layout": { "name": layout_info.layout_name, "desc": layout_info.layout_desc, }, "open": open_host_list, "is_run": is_run } return JsonResponse(R.ok(data=result_data))
def destroy(self, request, *args, **kwargs): """ 删除镜像信息 :param request: :param args: :param kwargs: :return: """ user = request.user if not user.is_superuser: return JsonResponse(R.build(msg="权限不足")) network = self.get_object() count = LayoutServiceNetwork.objects.filter(network_id=network).count() if count == 0: try: docker_network = client.networks.get( network.net_work_client_id) docker_network.remove() except Exception as e: try: network_list = client.networks.list() for network in network_list: network_configs = network.attrs['IPAM']['Config'] if len(network_configs) > 0: subnet = network_configs[0]['Subnet'] if subnet != network.net_work_subnet: continue network.remove() except Exception as e: pass network.delete() return JsonResponse(R.ok()) else: return JsonResponse( R.build(msg="网卡 %s 正在使用无法删除" % (network.net_work_subnet, )))
def get(self, request): page_no = int(request.GET.get("page", 1)) score_list = ContainerVul.objects.filter( is_check=True, time_model_id='').values('image_id').distinct().values( 'user_id').annotate(score=Sum("image_id__rank")).values( 'user_id', 'score').order_by("-score") len_score_list = [item for item in score_list if item['score'] != 0] try: pages = Paginator( [item for item in score_list if item['score'] != 0], 20) page = pages.page(page_no) except Exception as e: return JsonResponse(R.err()) result = [] for _data in list(page): user_info = UserProfile.objects.filter(id=_data["user_id"]).first() username = "" pass_container_vuls = "" user_avatar = "" if user_info: username = user_info.username user_avatar = user_info.avatar pass_container_vuls = ContainerVul.objects.filter( is_check=True, user_id=user_info.id, time_model_id='').values('image_id').distinct().count() result.append({ "rank": _data["score"], "name": username, "image_url": user_avatar, "pass_container_count": pass_container_vuls }) data = {'results': result, 'count': len(len_score_list)} return JsonResponse(R.ok(data=data))
def stop_layout(self, request, pk=None): if not pk or pk == "undefined": return JsonResponse(R.build(msg="环境不存在")) user = request.user if not user.is_superuser: return JsonResponse(R.build(msg="权限不足")) layout_info = Layout.objects.filter(layout_id=pk, is_release=True).first() if not layout_info: return JsonResponse(R.build(msg="环境不存在或未发布")) layout_id = str(layout_info.layout_id) layout_path = os.path.join(DOCKER_COMPOSE, layout_id) layout_data = LayoutData.objects.filter( layout_id=layout_info, file_path="docker-compose" + layout_path.replace(DOCKER_COMPOSE, ""), ).first() if not layout_data: return JsonResponse(R.build(msg="环境未启动,无法停止")) if not os.path.exists(layout_path): return JsonResponse(R.ok()) if layout_data.status == "stop": return JsonResponse(R.ok()) try: with transaction.atomic(): container_list = get_project(layout_path).stop() if container_list: for container in container_list: container_id = container.id LayoutServiceContainer.objects.filter(docker_container_id=container_id) \ .update(container_status="stop") LayoutServiceContainer.objects.filter( layout_user_id=layout_data).update(container_status="stop") layout_data.status = "stop" layout_data.save() except Exception as e: return JsonResponse(R.err()) request_ip = get_request_ip(request) sys_log = SysLog(user_id=user.id, operation_type="编排环境", operation_name="停止", operation_value=layout_info.layout_name, operation_args=json.dumps( LayoutSerializer(layout_info).data), ip=request_ip) sys_log.save() return JsonResponse(R.ok())
def get_layout_batch(self, request, pk=None): task_id_str = request.POST.get("task_ids", "") task_id_list = task_id_str.split(",") task_list = TaskInfo.objects.filter(task_id__in=task_id_list) result = {} for task_info in task_list: args = task_info.operation_args args_info = json.loads(args) layout_name = args_info["layout_name"] image_list = [] # 查询出该编排环境中的所有进行下载任务 progress = 0.0 status = 1 relative_task_all = TaskInfo.objects.filter( operation_type=8, user_id=request.user.id, operation_args__contains=json.dumps(layout_name), task_status=1) for single_task in relative_task_all: task_log = r.get(str(single_task.task_id)) if task_log: try: task_log_json = json.loads(task_log) current_progress = task_log_json["progress"] progress += current_progress except Exception as e: pass layout_info = Layout.objects.filter( layout_name=layout_name).first() if layout_info: yml_data = yaml.load(layout_info.yml_content, Loader=yaml.Loader) services = yml_data["services"] for service in services: image_name = services[service]["image"] image_list.append(image_name) count = len(image_list) not_download = 0 for image in image_list: try: current_image = client.images.get(image) if current_image: count -= 1 if count == 0: status = 2 except Exception as e: not_download += 1 if not_download != 0: result[str(task_info.task_id)] = { "progress": float(progress / not_download), "status": status } else: result[str(task_info.task_id)] = { "progress": 100.0, "status": 2 } return JsonResponse(R.ok(data=result))
def create_image(task_id): """ 创建镜像名称 """ task_info = TaskInfo.objects.filter(task_id=task_id, task_status=1).first() if not task_info: return operation_args = task_info.operation_args args = json.loads(operation_args) image_name = args["image_name"].strip() image_desc = args["image_desc"].strip() image_rank = args["rank"] image_vul_name = args["image_vul_name"].strip() image_info = ImageInfo.objects.filter(image_name=image_name).first() if not image_info: image_info = ImageInfo(image_name=image_name, image_desc=image_desc, rank=image_rank, image_vul_name=image_vul_name) image = None msg = {} try: image = client.images.get(image_name) except Exception as e: image_info.is_ok = False image_info.save() try: images = client.images.pull(image_name) if Image == type(images): image = images else: if len(images) > 0: image = images[0] except ImageNotFound: msg = R.build(msg="%s 不存在") except Exception: traceback.print_exc() msg = R.err(msg="%s 添加失败" % (image_name, )) if image: config = image.attrs["ContainerConfig"] port_list = [] if "ExposedPorts" in config: port_list = config["ExposedPorts"] ports = [] for port in port_list: port = port.replace("/", "").replace("tcp", "").replace("udp", "") ports.append(port) image_port = ",".join(ports) image_info.image_port = image_port image_info.is_ok = True image_info.save() msg = R.ok(msg="%s 添加成功" % (image_name, ), data=json.dumps({"image_port": image_port})) task_info.task_status = 3 else: task_info.task_status = 4 task_info.task_msg = json.dumps(msg) task_info.save()
def get_batch_task(self, request, pk=None): task_id_str = request.POST.get("task_ids", "") task_id_list = task_id_str.split(",") task_list = TaskInfo.objects.filter(task_id__in=task_id_list) result = {} for task_info in task_list: result[str(task_info.task_id)] = { "status": task_info.task_status, "data": json.loads(task_info.task_msg) } return JsonResponse(R.ok(data=result))
def del_comment(self, request, pk=None): user = request.user if not pk: return JsonResponse(R.build(msg="参数不能为空")) comment_info = Comment.objects.filter(comment_id=pk).first() if not comment_info: return JsonResponse(R.build(msg="评论不存在")) if not user.is_superuser and comment_info.user != user: return JsonResponse(R.build(msg="权限不足")) comment_info.delete() return JsonResponse(R.ok())
def update(self, request, *args, **kwargs): user = request.user if not user.is_superuser: return JsonResponse(R.build(msg="权限不足")) new_pwd = request.data.get("pwd", "") new_pwd = new_pwd.strip() if len(new_pwd) < 6: return JsonResponse(R.build(msg="密码格式不正确")) user_info = self.get_object() user_info.set_password(new_pwd) user_info.save() return JsonResponse(R.ok())
def delete_image(self, request, pk=None): user = request.user if not pk or pk == "undefined": return JsonResponse(R.build(msg="环境不存在")) if not user.is_superuser: return JsonResponse(R.build(msg="权限不足")) try: layout = Layout.objects.filter(layout_id=pk).first() if not layout: return JsonResponse(R.build(msg="环境不存在")) layout_name = layout.layout_name layout_id = str(layout.layout_id) layout_path = os.path.join(DOCKER_COMPOSE, layout_id) with transaction.atomic(): _tmp_file_path = "docker-compose" + layout_path.replace( DOCKER_COMPOSE, "") layout_data = LayoutData.objects.filter( layout_id=layout, file_path=_tmp_file_path).first() if layout_data and layout_data.status == 'running': return JsonResponse(R.build(msg="环境正在运行中,请首先停止运行")) # 删除分数 LayoutServiceContainerScore.objects.filter( layout_id=layout).delete() # 删除容器 if layout_data: LayoutServiceContainer.objects.filter( layout_user_id=layout_data) # 删除服务网卡 service_list = LayoutService.objects.filter(layout_id=layout) if len(service_list) > 0: for service in service_list: # service_id = service.service_id LayoutServiceNetwork.objects.filter( service_id=service).delete() # 删除服务 LayoutService.objects.filter(layout_id=layout).delete() # 删除内容 layout.delete() # 删除文件和文件夹 shutil.rmtree(layout_path) request_ip = get_request_ip(request) sys_log = SysLog(user_id=user.id, operation_type="编排环境", operation_name="删除", operation_value=layout_name, operation_args=json.dumps( LayoutSerializer(layout).data), ip=request_ip) sys_log.save() except Exception as e: traceback.print_exc() return JsonResponse(R.err()) return JsonResponse(R.ok())
def get_task_progress(self, request, pk=None): task_info = self.get_object() task_id = task_info.task_id task_log = r.get(str(task_id)) if task_log: task_log_json = json.loads(task_log) data = { "total": task_log_json["total"], "progress_count": task_log_json["progress_count"], "progress": task_log_json["progress"], "layer": [] } black_list = ["total", "progress_count", "progress"] layer_list = [] for key in task_log_json: if key in black_list: continue layer_list.append(task_log_json[key]) data["layer"] = layer_list return JsonResponse(R.ok(data=data)) else: return JsonResponse(R.ok())
def flag_layout(self, request, pk=None): if not pk or pk == "undefined": return JsonResponse(R.build(msg="环境不存在")) user = request.user layout_info = Layout.objects.filter(layout_id=pk, is_release=True).first() if not layout_info: return JsonResponse(R.build(msg="环境不存在或未发布")) flag = str(request.GET.get("flag", "")) if not flag: return JsonResponse(R.build(msg="Flag 不能为空")) if not flag.startswith("flag-{bmh"): return JsonResponse(R.build(msg="Flag 格式不正确")) layout_path = os.path.join(DOCKER_COMPOSE, str(layout_info.layout_id)) layout_data = LayoutData.objects.filter( layout_id=layout_info, file_path="docker-compose" + layout_path.replace(DOCKER_COMPOSE, ""), ).first() service_container = LayoutServiceContainer.objects.filter( layout_user_id=layout_data, container_flag=flag).first() if not service_container: return JsonResponse(R.build(msg="Flag 不正确")) service_container_score = LayoutServiceContainerScore.objects.filter( user_id=user.id, flag=flag, service_container_id=service_container).first() if not service_container_score: service_info = service_container.service_id image_info = service_container.image_id service_container_score = LayoutServiceContainerScore( layout_service_container_score_id=uuid.uuid4(), user_id=user.id, layout_id=layout_info, layout_data_id=layout_data, service_id=service_info, image_id=image_info, create_date=timezone.now(), service_container_id=service_container, flag=flag, update_date=timezone.now()) service_container_score.save() request_ip = get_request_ip(request) sys_log = SysLog(user_id=user.id, operation_type="编排环境", operation_name="提交Flag", operation_value=layout_info.layout_name, operation_args=json.dumps({"flag": flag}), ip=request_ip) sys_log.save() return JsonResponse(R.ok())
def get_task(self, request, pk=None): task_info = self.get_object() task_msg = task_info.task_msg if task_info.task_status == 1: return JsonResponse( R.running(msg="执行中", data=str(task_info.task_id))) task_info.is_show = True task_info.save() if task_msg: msg = json.loads(task_msg) if msg["status"] == 200: return JsonResponse(msg, status=200) else: return JsonResponse(msg, status=msg["status"]) return JsonResponse(R.ok())
def release_layout(self, request, pk=None): """ 发布环境 """ if not pk or pk == "undefined": return JsonResponse(R.build(msg="环境不存在")) user = request.user if not user.is_superuser: return JsonResponse(R.build(msg="权限不足")) layout_info = Layout.objects.filter(layout_id=pk).first() if not layout_info: return JsonResponse(R.build(msg="环境不存在")) layout_info.is_release = True layout_info.save() return JsonResponse(R.ok())
def get_task(self, request, pk=None): task_info = self.get_object() task_msg = task_info.task_msg if task_info.task_status == 1: return JsonResponse( R.running(msg="执行中", data=str(task_info.task_id))) task_info.is_show = True task_info.save() if task_msg: msg = json.loads(task_msg) if msg["status"] == 200: if not msg["data"]: msg["data"] = {"_now": int(timezone.now().timestamp())} else: msg["data"]["_now"] = int(timezone.now().timestamp()) return JsonResponse(msg, status=200) else: return JsonResponse(msg, status=msg["status"]) return JsonResponse(R.ok())
def get_batch_task(self, request, pk=None): task_id_str = request.POST.get("task_ids", "") task_id_list = task_id_str.split(",") task_list = TaskInfo.objects.filter(task_id__in=task_id_list) result = {} for task_info in task_list: progress = 0.0 task_log = r.get(str(task_info.task_id)) if task_log: try: task_log_json = json.loads(task_log) progress = task_log_json["progress"] except: pass result[str(task_info.task_id)] = { "status": task_info.task_status, "data": json.loads(task_info.task_msg), "progress": progress } return JsonResponse(R.ok(data=result))
def get_public_notice(request): notifications = Notification.objects.filter(recipient=request.user) notices = [] for single_notification in notifications: if single_notification.target_object_id: notice = Notice.objects.filter(notice_id=single_notification.target_object_id).first() if notice: notices.append(notice) notices.sort(key=lambda item: item.update_date,reverse=True) page_no = int(request.GET.get("page", "1")) pages = Paginator(notices, 20) page = pages.page(page_no) results = [] for _data in page: results.append(_data) data = { "results": NoticeInfoSerializer(results, many=True, context={'request': request}).data, "count": len(notices) } return JsonResponse(R.ok(data=data))
def get(self, request): page_no = int(request.GET.get("page", 1)) score_list = ContainerVul.objects.filter( is_check=True, time_model_id='').values('user_id').annotate( score=Sum("image_id__rank")).values('user_id', 'score').order_by("-score") try: pages = Paginator(score_list, 20) page = pages.page(page_no) except Exception as e: return JsonResponse(R.err()) result = [] for _data in list(page): user_info = UserProfile.objects.filter(id=_data["user_id"]).first() username = "" if user_info: username = user_info.username result.append({"rank": _data["score"], "name": username}) data = {'results': result, 'count': len(score_list)} return JsonResponse(R.ok(data=data))
def upload_img(request): """ 上传文件图片 """ user = request.user if not user.is_superuser: return JsonResponse(R.build(msg="权限不足")) img = request.data["img"] if not img: return JsonResponse(R.build(msg="请上传图片")) img_name = img.name img_suffix = img_name.split(".")[-1] if img_suffix not in ALLOWED_IMG_SUFFIX: return JsonResponse( R.build(msg="不支持此格式图片文件,请上传%s格式文件" % ("、".join(ALLOWED_IMG_SUFFIX), ))) image_name = str(uuid.uuid4()).replace('-', '') + "." + img_suffix with open(os.path.join(BASE_DIR, "static", image_name), "wb") as f: for chunk in img.chunks(): f.write(chunk) return JsonResponse(R.ok(data=image_name))
def get_public_notice(request): notices = [] all_notices = Notice.objects.filter(is_public=True) for single_notice in all_notices: notices.append(single_notice) notices.sort(key=lambda item: item.update_date, reverse=True) page_no = int(request.GET.get("page", "1")) pages = Paginator(notices, 20) page = pages.page(page_no) results = [] for _data in page: results.append(_data) data = { "results": NoticeInfoSerializer(results, many=True, context={ 'request': request }).data, "count": len(notices) } return JsonResponse(R.ok(data=data))
def docker_container_run(docker_container, command=""): """ docker 容器启动 :param docker_container: docker 容器对象 :param command: 执行命令,默认为空不执行命令 """ container_status = str(docker_container.status) for i in range(DOCKER_CONTAINER_TIME): docker_container.reload() container_status = str(docker_container.status) if 'running' == container_status: if command: docker_container.exec_run(command) break elif 'exited' == container_status: pass time.sleep(1) data = {"status": container_status} if "running" != container_status: return R.err(data=data, msg="漏洞容器启动失败") else: return R.ok(data)
def create(self, request, *args, **kwargs): data_dict = request.data user_id = request.user.id try: net_work_name = data_dict['net_work_name'] except Exception as e: return Response(R.build(msg="网卡名称不能为空")) try: net_work_subnet = data_dict['net_work_subnet'] except Exception as e: return Response(R.build(msg="子网不能为空")) try: net_work_gateway = data_dict['net_work_gateway'] except Exception as e: return Response(R.build(msg="网关不能为空")) try: net_work_scope = data_dict['net_work_scope'] except Exception as e: net_work_scope = 'local' try: net_work_driver = data_dict['net_work_driver'] except Exception as e: net_work_driver = 'bridge' try: enable_ipv6 = data_dict['enable_ipv6'] except Exception as e: enable_ipv6 = False try: rs = NetWorkInfo.objects.filter(net_work_name=net_work_name) if len(rs) > 0: return Response(R.build(msg="网卡名称不能重复")) rs = NetWorkInfo.objects.filter(net_work_subnet=net_work_subnet) if len(rs) > 0: return Response(R.build(msg="子网不能重复")) rs = NetWorkInfo.objects.filter(net_work_gateway=net_work_gateway) if len(rs) > 0: return Response(R.build(msg="网关不能重复")) except Exception as e: print(e) if not net_work_subnet: network_list = client.networks.list() for network in network_list: network_configs = network.attrs['IPAM']['Config'] if len(network_configs) > 0: subnet = network_configs[0]['Subnet'] net_work_gateway = network_configs[0]['Gateway'] if subnet != net_work_subnet: continue net_work_client_id = network.attrs["Id"] net_work_scope = network.attrs["Scope"] net_work_driver = network.attrs["Driver"] enable_ipv6 = network.attrs["EnableIPv6"] break else: if net_work_subnet == "192.168.10.10/24": return JsonResponse(R.err(msg="该网段已在服务器内部使用,请更换网段")) if net_work_gateway == "192.168.10.10": return JsonResponse(R.err(msg="该网关已在服务器内部使用,请更换网关")) try: ipam_pool = docker.types.IPAMPool(subnet=net_work_subnet, gateway=net_work_gateway) ipam_config = docker.types.IPAMConfig(pool_configs=[ipam_pool]) if not net_work_name: return JsonResponse(R.err(msg="网卡名称不能为空")) try: net_work = client.networks.create(net_work_name, driver=net_work_driver, ipam=ipam_config, scope=net_work_scope) except Exception as e: return JsonResponse(R.err(msg="子网或者网关设置错误")) net_work_client_id = str(net_work.id) if not net_work_gateway: net_work_gateway = net_work.attrs['IPAM']['Config'][ 'Gateway'] except Exception as e: traceback.print_exc() return JsonResponse(R.err(msg="服务器内部错误")) network_info = NetWorkInfo(net_work_id=str(uuid.uuid4()), net_work_client_id=net_work_client_id, create_user=user_id, net_work_name=net_work_name, net_work_driver=net_work_driver, net_work_subnet=net_work_subnet, net_work_gateway=net_work_gateway, net_work_scope=net_work_scope, enable_ipv6=enable_ipv6) network_info.save() data = NetWorkInfoSerializer(network_info).data return JsonResponse(R.ok(data=data))
def share_image(task_id): """ 贡献镜像 :param task_id: 任务 id :return: """ task_info = TaskInfo.objects.filter(task_id=task_id, task_status=1).first() operation_args = task_info.operation_args args = json.loads(operation_args) share_username = args["share_username"].strip() image_name = args["image_name"].strip() username = args["username"].strip() password = args["pwd"].strip() msg = R.ok(msg="分享成功") try: client.login(username, password) new_image_name = image_name.split(":")[0]+":"+share_username if new_image_name.rfind("/") > -1: r_image_info = new_image_name[:new_image_name.rfind("/")] if r_image_info.rfind("/") > -1: repo_tmp = r_image_info[:r_image_info.rfind("/")] repo_name = "/".join([repo_tmp, username, new_image_name[new_image_name.rfind("/")+1:]]) else: repo_name = "/".join([username, new_image_name[new_image_name.rfind("/")+1:]]) else: repo_name = "/".join([username, new_image_name]) new_image_name = repo_name tag_flag = api_docker_client.tag(image_name, new_image_name) if tag_flag: last_info = {} progress_info = { "total": 0, "progress_count": 0, "progress": round(0.0, 2), } black_list = ["total", "progress_count", "progress"] for line in api_docker_client.push(new_image_name, stream=True, decode=True, auth_config={"username": username, "password": password}): if "status" in line and "progressDetail" in line and "id" in line: id = line["id"] status = line["status"] if len(line["progressDetail"]) > 0: try: current = line["progressDetail"]["current"] total = line["progressDetail"]["total"] line["progress"] = round((current / total) * 100, 2) if (current / total) > 1: line["progress"] = round(0.99 * 100, 2) except: line["progress"] = round(1 * 100, 2) else: if ("Pushed" in status) or ("Verifying" in status) or \ ("Layer" in status and "already" in status and "exists" in status) or ("Mounted" in status and "from" in status): line["progress"] = round(100.00, 2) else: line["progress"] = round(0.00, 2) progress_info[id] = line progress_info["total"] = len(progress_info) - len(black_list) progress_count = 0 for key in progress_info: if key in black_list: continue if 100.00 != progress_info[key]["progress"]: continue progress_count += 1 progress_info["progress_count"] = progress_count progress_info["progress"] = round((progress_count/progress_info["total"])*100, 2) r.set(str(task_id), json.dumps(progress_info,ensure_ascii=False)) print(json.dumps(progress_info, ensure_ascii=False)) last_info = line # print("last_info") # print("==========================") # print(json.dumps(last_info, ensure_ascii=False)) if "error" in last_info and last_info["error"]: task_info.task_msg = R.build(msg="原%s构建新镜像%s失败,错误信息:%s" % (image_name, new_image_name, str(last_info["error"]),)) task_info.task_status = 4 elif "progressDetail" in last_info and "aux" in last_info and share_username in last_info["aux"]["Tag"]: image_info = ImageInfo.objects.filter(image_name=image_name).first() if image_info: image_info.is_share = True image_info.save() msg = R.ok(msg="%s 分享成功" % (image_name,)) else: msg = R.build(msg="%s 分享失败" % (image_name,)) else: task_info.task_msg = R.build(msg="原%s构建新镜像%s失败" % (image_name, new_image_name,)) task_info.task_status = 4 except docker.errors.APIError as api_error: msg = R.build(msg="Dockerhub 用户名或 Dockerhub Token 错误") task_info.task_status = 4 except Exception as e: msg = R.build(msg="%s 分享失败,错误信息:%s" % (image_name, str(e),)) task_info.task_status = 4 task_info.task_status = 3 task_info.task_msg = json.dumps(msg) task_info.save()
def create_image(task_id): """ 创建镜像名称 """ task_info = TaskInfo.objects.filter(task_id=task_id, task_status=1).first() if not task_info: return operation_args = task_info.operation_args args = json.loads(operation_args) image_name = args["image_name"].strip() image_info = ImageInfo.objects.filter(image_name=image_name).first() if not image_info: image_desc = image_name image_rank = 2.5 image_vul_name = image_desc image_info = ImageInfo(image_name=image_name, image_desc=image_desc, rank=image_rank, image_vul_name=image_vul_name) image = None msg = {} try: image = client.images.get(image_name) except Exception as e: image_info.is_ok = False image_info.save() try: last_info = {} progress_info = { "total": 0, "progress_count": 0, "progress": round(0.0, 2), } black_list = ["total", "progress_count", "progress"] for line in api_docker_client.pull(image_name, stream=True, decode=True): if "status" in line and "progressDetail" in line and "id" in line: id = line["id"] status = line["status"] if len(line["progressDetail"]) > 0: try: current = line["progressDetail"]["current"] total = line["progressDetail"]["total"] line["progress"] = round((current / total) * 100, 2) if (current / total) > 1: line["progress"] = round(0.99 * 100, 2) except: line["progress"] = round(1 * 100, 2) else: if (("Download" in status or "Pull" in status) and ("complete" in status)) or ("Verifying" in status) or \ ("Layer" in status and "already" in status and "exists" in status): line["progress"] = round(100.00, 2) else: line["progress"] = round(0.00, 2) progress_info[id] = line progress_info["total"] = len(progress_info) - len(black_list) progress_count = 0 for key in progress_info: if key in black_list: continue if 100.00 != progress_info[key]["progress"]: continue progress_count += 1 progress_info["progress_count"] = progress_count progress_info["progress"] = round((progress_count/progress_info["total"])*100, 2) r.set(str(task_id), json.dumps(progress_info,ensure_ascii=False)) print(json.dumps(progress_info, ensure_ascii=False)) last_info = line if "status" in last_info and ("Downloaded newer image for" in last_info["status"] or "Image is up to date for" in last_info["status"]): image = client.images.get(image_name) else: raise Exception except ImageNotFound: msg = R.build(msg="%s 不存在" % (image_name,)) except Exception: traceback.print_exc() msg = R.err(msg="%s 添加失败" % (image_name,)) if image: config = image.attrs["ContainerConfig"] port_list = [] if "ExposedPorts" in config: port_list = config["ExposedPorts"] ports = [] for port in port_list: port = port.replace("/", "").replace("tcp", "").replace("udp", "") ports.append(port) image_port = ",".join(ports) image_info.image_port = image_port image_info.is_ok = True image_info.save() msg = R.ok(msg="%s 添加成功" % (image_name,), data=json.dumps({"image_port": image_port})) task_info.task_status = 3 else: task_info.task_status = 4 task_info.task_msg = json.dumps(msg) task_info.save()
def create_image_task(image_info, user_info, request_ip, image_file=None): """ 创建镜像任务 """ user_id = user_info.id task_id = create_create_image_task(image_info=image_info, user_info=user_info) if user_info.is_superuser: image_name = image_info.image_name image_desc = image_info.image_desc image_vul_name = image_info.image_vul_name image_rank = image_info.rank task_info = TaskInfo.objects.filter(task_id=task_id).first() if image_file: task_msg = {} try: file_info = image_file.read() images = client.images.load(file_info) image = images[0] repo_tags = image.attrs["RepoTags"] if len(repo_tags) == 0: # 移除本地镜像 try: client.images.remove(image.id) except Exception as e: pass task_msg = R.build(msg="文件镜像 Tag 不能为空") else: config = image.attrs["ContainerConfig"] port_list = [] if "ExposedPorts" in config: port_list = config["ExposedPorts"] ports = [] for port in port_list: port = port.replace("/", "").replace("tcp", "").replace("udp", "") ports.append(port) image_name = repo_tags[0] image_port = ",".join(ports) image_info = ImageInfo.objects.filter(image_name=image_name).first() if not image_info: image_info = ImageInfo() image_info.image_name = image_name image_info.image_port = image_port # image_vul_name image_info.image_vul_name = image_name.replace("vulfocus/","") if not image_vul_name else image_vul_name # image_desc image_info.image_desc = image_name.replace("vulfocus/","") if not image_desc else image_desc # rank image_info.rank = 2.5 if image_rank > 5 or image_rank < 0.5 else image_rank image_info.is_ok = True image_info.save() task_info.task_name = "拉取镜像:"+image_name task_info.task_status = 3 task_msg = R.ok(data="%s 添加成功" % (image_name, )) except Exception as e: traceback.print_exc() task_msg = R.err() try: image_info.delete() except: pass task_info.task_status = 4 finally: task_info.task_msg = json.dumps(task_msg) task_info.update_date = timezone.now() task_info.save() elif image_name: # 创建任务 # create_image(task_id=task_id) create_image.delay(task_id) else: R.build(msg="镜像文件或镜像名称不能为空") operation_args = ImageInfoSerializer(image_info).data sys_log = SysLog(user_id=user_id, operation_type="镜像", operation_name="创建", ip=request_ip, operation_value=operation_args["image_vul_name"], operation_args=json.dumps(operation_args)) sys_log.save() else: task_info = TaskInfo.objects.filter(task_id=task_id).first() task_info.task_msg = json.dumps(R.build(msg="权限不足")) task_info.task_status = 3 task_info.update_date = timezone.now() task_info.save() return task_id
def run_container(container_id, user_id, tmp_task_id, countdown): """ 运行 docker 容器 :param container_id: 漏洞容器数据库 id :param user_id: 用户ID :param tmp_task_id: 任务ID :param countdown 定时 """ # docker container id container_vul = ContainerVul.objects.filter(container_id=container_id).first() user_info = UserProfile.objects.filter(id=user_id).first() container_id = container_vul.docker_container_id image_info = container_vul.image_id image_name = image_info.image_name image_port = image_info.image_port user_id = user_info.id docker_container = None msg = {} """ 创建启动任务 """ args = { "image_name": image_name, "user_id": user_id, "image_port": image_port } task_id = "" task_info = TaskInfo.objects.filter(task_id=tmp_task_id).first() # run container execute command command = "" vul_flag = container_vul.container_flag container_port = container_vul.container_port vul_port = {} if container_vul.vul_port: vul_port = json.loads(container_vul.vul_port) vul_host = container_vul.vul_host if container_id: # check container check_rsp = check_container(container_id) if check_rsp["flag"]: docker_container = check_rsp["container"] # set container_flag vul_flag = container_vul.container_flag # if container by delete , create a container if not docker_container: port_list = image_port.split(",") port_dict = {} random_list = [] for port in port_list: random_port = '' for i in range(20): # random port random_port = str(random.randint(8000, 65536)) if random_port in random_list or ContainerVul.objects.filter(container_port=random_port).first(): continue break if not random_port: msg = R.err(msg="端口无效") break random_list.append(random_port) port_dict['%s/tcp' % (port,)] = int(random_port) # 端口重复,无法进行创建 if len(msg) > 0 or msg: task_info.task_msg = json.dumps(msg) task_info.update_date = timezone.now() # except task_info.task_status = 4 task_info.save() return str(task_info.task_id) container_port = ",".join(random_list) """ random port """ for tmp_port in port_dict: tmp_random_port = port_dict[tmp_port] tmp_port = tmp_port.replace("/tcp", "") vul_port[tmp_port] = str(tmp_random_port) try: client.images.get(image_name) except Exception as e: msg = R.build(msg="镜像不存在") task_info.task_msg = json.dumps(msg) task_info.update_date = timezone.now() # except task_info.task_status = 4 task_info.save() image_info.is_ok = False image_info.save() return str(task_info.task_id) vul_flag = "flag-{bmh%s}" % (uuid.uuid4(),) if container_vul.container_flag: vul_flag = container_vul.container_flag try: docker_container = client.containers.run(image_name, ports=port_dict, detach=True, environment={"vul_flag": vul_flag}) except ImageNotFound: msg = R.build(msg="镜像不存在") task_info.task_msg = json.dumps(msg) task_info.update_date = timezone.now() # except task_info.task_status = 4 task_info.save() image_info.is_ok = False image_info.save() return str(task_info.task_id) command = 'touch /tmp/%s' % (vul_flag,) vul_host = get_local_ip() + ":" + container_port task_start_date = timezone.now() if countdown != 0 and countdown >= 60: task_end_date = task_start_date + datetime.timedelta(seconds=countdown) elif countdown == 0: task_end_date = None else: countdown = int(DEFAULT_CONFIG["time"]) task_end_date = task_start_date + datetime.timedelta(seconds=countdown) if "running" == docker_container.status: msg_data = R.ok(data={ "host": container_vul.vul_host, "port": container_vul.vul_port, "id": str(container_vul.container_id), "status": "running", "start_date": int(task_start_date.timestamp()), "end_date": 0 if not task_end_date else int(task_end_date.timestamp()) }) search_task = TaskInfo.objects.filter(user_id=user_id, task_msg=json.dumps(msg_data), operation_type=2, operation_args=json.dumps(args), task_end_date=task_end_date, task_name="运行容器:" + image_name).order_by("-create_date").first() if not search_task: task_info.task_status = 3 task_info.task_msg = json.dumps(msg_data) task_info.update_date = timezone.now() task_info.operation_args = json.dumps(args) task_info.save() task_id = str(task_info.task_id) else: task_info.delete() search_task.task_id = tmp_task_id search_task.task_status = 3 search_task.update_date = timezone.now() search_task.save() task_id = str(search_task.task_id) else: task_info.save() docker_container.start() msg = docker_container_run(docker_container, command=command) if msg["status"] == HTTP_ERR: try: container_vul.delete() except Exception: pass # except task_info.task_status = 4 else: container_status = msg["data"]["status"] msg["data"]["host"] = vul_host msg["data"]["port"] = vul_port msg["data"]["id"] = str(container_vul.container_id) msg["data"]["status"] = container_status msg["data"]["start_date"] = int(task_start_date.timestamp()) msg["data"]["end_date"] = 0 if not task_end_date else int(task_end_date.timestamp()) # 容器状态 container_vul.container_status = container_status # 容器 id container_vul.docker_container_id = str(docker_container.id) # 漏洞 HOST container_vul.vul_host = vul_host # 漏洞端口 container_vul.vul_port = json.dumps(vul_port) # 容器端口映射关系 container_vul.container_port = container_port # 验证 flag container_vul.container_flag = vul_flag container_vul.save() task_start_date = timezone.now() # start 时间 task_info.task_start_date = task_start_date task_info.task_end_date = task_end_date task_info.task_status = 3 task_info.task_msg = json.dumps(msg) task_info.update_date = timezone.now() task_info.save() task_id = str(task_info.task_id) print("启动漏洞容器成功,任务ID:%s" % (task_id, )) return create_stop_container_task(container_vul,user_info)