mirror of
https://github.com/RobbieHan/sandboxMP.git
synced 2026-02-03 02:43:14 +08:00
scan config
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from .views import CmdbView
|
from .views import CmdbView
|
||||||
from . import views_code
|
from . import views_code, views_scan
|
||||||
|
|
||||||
app_name = 'cmdb'
|
app_name = 'cmdb'
|
||||||
|
|
||||||
@@ -12,4 +12,6 @@ urlpatterns = [
|
|||||||
path('portal/code/list/', views_code.CodeListView.as_view(), name='portal-code-list'),
|
path('portal/code/list/', views_code.CodeListView.as_view(), name='portal-code-list'),
|
||||||
path('portal/code/update/', views_code.CodeUpdateView.as_view(), name='portal-code-update'),
|
path('portal/code/update/', views_code.CodeUpdateView.as_view(), name='portal-code-update'),
|
||||||
path('portal/code/delete/', views_code.CodeDeleteView.as_view(), name='portal-code-delete'),
|
path('portal/code/delete/', views_code.CodeDeleteView.as_view(), name='portal-code-delete'),
|
||||||
|
|
||||||
|
path('portal/scan_config/', views_scan.ScanConfigView.as_view(), name='portal-scan_config'),
|
||||||
]
|
]
|
||||||
|
|||||||
54
apps/cmdb/views_scan.py
Normal file
54
apps/cmdb/views_scan.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# @Time : 2018/12/29 19:25
|
||||||
|
# @Author : RobbieHan
|
||||||
|
# @File : views_scan.py
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import logging
|
||||||
|
from ruamel import yaml
|
||||||
|
|
||||||
|
from django.views.generic import View
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
|
||||||
|
from system.mixin import LoginRequiredMixin
|
||||||
|
from custom import BreadcrumbMixin
|
||||||
|
from utils.sandbox_utils import ConfigFileMixin
|
||||||
|
from system.models import Menu
|
||||||
|
|
||||||
|
error_logger = logging.getLogger('sandbox_error')
|
||||||
|
|
||||||
|
|
||||||
|
class ScanConfigView(LoginRequiredMixin, BreadcrumbMixin, ConfigFileMixin, View):
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
menu = Menu.get_menu_by_request_url(request.path_info)
|
||||||
|
template_name = 'cmdb/scan_config.html'
|
||||||
|
context = self.get_conf_content()
|
||||||
|
context.update(menu)
|
||||||
|
return render(request, template_name, context)
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
ret = dict(result=False)
|
||||||
|
config = dict()
|
||||||
|
hosts = request.POST
|
||||||
|
try:
|
||||||
|
config['net_address'] = ast.literal_eval(hosts['net_address'])
|
||||||
|
config['ssh_username'] = hosts['ssh_username']
|
||||||
|
config['ssh_port'] = hosts['ssh_port']
|
||||||
|
config['ssh_password'] = hosts['ssh_password']
|
||||||
|
config['ssh_private_key'] = hosts['ssh_private_key']
|
||||||
|
config['commands'] = ast.literal_eval(hosts['commands'])
|
||||||
|
config['auth_type'] = hosts['auth_type']
|
||||||
|
config['scan_type'] = hosts['scan_type']
|
||||||
|
config['email'] = hosts['email']
|
||||||
|
config['send_email'] = hosts['send_email']
|
||||||
|
data = dict(hosts=config)
|
||||||
|
config_file = self.get_config_file()
|
||||||
|
with open(config_file, 'w', encoding='utf-8') as f:
|
||||||
|
yaml.dump(data, f, Dumper=yaml.RoundTripDumper, indent=4)
|
||||||
|
ret['result'] = True
|
||||||
|
except Exception as e:
|
||||||
|
error_logger.error(e)
|
||||||
|
|
||||||
|
return JsonResponse(ret)
|
||||||
3
apps/utils/__init__.py
Normal file
3
apps/utils/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# @Time : 2018/12/29 16:26
|
||||||
|
# @Author : RobbieHan
|
||||||
|
# @File : __init__.py.py
|
||||||
74
apps/utils/sandbox_utils.py
Normal file
74
apps/utils/sandbox_utils.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# @Time : 2018/12/29 19:22
|
||||||
|
# @Author : RobbieHan
|
||||||
|
# @File : sandbox_utils.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
import logging
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sandboxMP.settings')
|
||||||
|
error_logger = logging.getLogger('sandbox_error')
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFileMixin:
|
||||||
|
config_file = None
|
||||||
|
|
||||||
|
def get_config_file(self):
|
||||||
|
"""
|
||||||
|
Return 'config_file' that will be used to look up the scan hosts IP,
|
||||||
|
network, range of IP, or other config settings.
|
||||||
|
This method is called by the default implementation of get_hosts(),
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.config_file is None:
|
||||||
|
config_file = os.path.join(os.path.join(settings.BASE_DIR, 'config'), 'scanhosts.yml')
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
return config_file
|
||||||
|
else:
|
||||||
|
msg = ' %(cls)s is missing a config file. Define %(cls)s.config_file, ' \
|
||||||
|
'or override %(cls)s.get_config_file().' % {'cls': self.__class__.__name__}
|
||||||
|
error_logger.error(msg)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
return self.config_file
|
||||||
|
|
||||||
|
def get_conf_content(self, *key):
|
||||||
|
"""
|
||||||
|
Get the configuration content from config file .
|
||||||
|
Example ssh_password, commands, email which is in the config file.
|
||||||
|
"""
|
||||||
|
_config = self.get_config_file()
|
||||||
|
with open(_config) as f:
|
||||||
|
content = yaml.load(f)
|
||||||
|
if key is not None:
|
||||||
|
try:
|
||||||
|
num = 0
|
||||||
|
while num < len(key):
|
||||||
|
content = content[key[num]]
|
||||||
|
num += 1
|
||||||
|
except Exception as e:
|
||||||
|
msg = '%(exc)s is not in %(config)s.' % {
|
||||||
|
'exc': e,
|
||||||
|
'config': _config
|
||||||
|
}
|
||||||
|
error_logger.error(msg)
|
||||||
|
raise ValueError(msg)
|
||||||
|
return content
|
||||||
|
|
||||||
|
def get_commands(self):
|
||||||
|
"""
|
||||||
|
Get the commands from config file.
|
||||||
|
"""
|
||||||
|
key = ['hosts', 'commands']
|
||||||
|
return self.get_conf_content(*key)
|
||||||
|
|
||||||
|
def get_net_address(self):
|
||||||
|
"""
|
||||||
|
Return the hosts that will be used to scan.
|
||||||
|
Subclasses can override this to return any hosts.
|
||||||
|
"""
|
||||||
|
key = ['hosts', 'net_address']
|
||||||
|
return self.get_conf_content(*key)
|
||||||
18
config/scanhosts.yml
Normal file
18
config/scanhosts.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
hosts:
|
||||||
|
net_address:
|
||||||
|
- '172.16.3.0/24'
|
||||||
|
- '172.16.2.100-105'
|
||||||
|
ssh_username: 'root'
|
||||||
|
ssh_port: '22'
|
||||||
|
ssh_password: '1234@abcd.com'
|
||||||
|
ssh_private_key: '/root/.ssh/id_rsa'
|
||||||
|
commands:
|
||||||
|
sys_hostname: 'hostname'
|
||||||
|
mac_address: 'cat /sys/class/net/[^tsbvl]*/address'
|
||||||
|
sn_number: 'dmidecode -s system-serial-number'
|
||||||
|
os_type: 'cat /etc/redhat-release'
|
||||||
|
device_type: 'echo `dmidecode -s system-manufacturer && dmidecode -s system-product-name`'
|
||||||
|
email: 'robbie_han@outlook.com'
|
||||||
|
send_email: 'false'
|
||||||
|
scan_type: 'basic_scan'
|
||||||
|
auth_type: 'private_key'
|
||||||
176
templates/cmdb/scan_config.html
Normal file
176
templates/cmdb/scan_config.html
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
{% extends "base-left.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
<link rel="stylesheet" href="{% static 'js/plugins/layer/skin/layer.css' %}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<section class="content">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<!-- Horizontal Form -->
|
||||||
|
<div class="box box-default">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">扫面参数配置</h3>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-header -->
|
||||||
|
<!-- form start -->
|
||||||
|
<form class="form-horizontal" id="addForm" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">扫描网段</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="net_address" name="net_address" value="{{ hosts.net_address }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">登陆用户</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="ssh_username" name="ssh_username" value="{{ hosts.ssh_username }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">SSH端口</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="ssh_port" name="ssh_port" value="{{ hosts.ssh_port }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">登陆密码</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" type="password" id="ssh_password" name="ssh_password" value="{{ hosts.ssh_password }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">密钥路径</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="ssh_private_key" name="ssh_private_key" value="{{ hosts.ssh_private_key }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">运行命令</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea class="form-control" rows="5" id="commands" name="commands" readonly>{{ hosts.commands }}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">认证方式</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<select class="form-control" name="auth_type">
|
||||||
|
<option value="password" {% ifequal hosts.auth_type 'password' %}selected="selected"{% endifequal %}>密码认证</option>
|
||||||
|
<option value="private_key" {% ifequal hosts.auth_type 'private_key' %}selected="selected"{% endifequal %}>私钥认证</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<label class="col-sm-2 control-label">扫描方式</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<select class="form-control" name="scan_type">
|
||||||
|
<option value="basic_scan" {% ifequal hosts.scan_type 'basic_scan' %}selected="selected"{% endifequal %}>基础扫描</option>
|
||||||
|
<option value="enhanced_scan" {% ifequal hosts.scan_type 'enhanced_scan' %}selected="selected"{% endifequal %}>加强扫描</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label">收件邮箱</label>
|
||||||
|
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input class="form-control" id="email" name="email" value="{{ hosts.email }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-group has-feedback">
|
||||||
|
<label class="col-sm-2 control-label">发送邮件</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<label class="control-label">
|
||||||
|
<input type="radio" class="minimal" name="send_email" value="true" {% ifequal hosts.send_email 'true' %}checked{% endifequal %}>是
|
||||||
|
</label>
|
||||||
|
<label class="control-label">
|
||||||
|
<input type="radio" class="minimal" name="send_email" value="false" {% ifequal hosts.send_email 'false' %}checked{% endifequal %}>否
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-body -->
|
||||||
|
<div class="box-footer">
|
||||||
|
<span class="pull-right">
|
||||||
|
<button type="button" id="btnCancel" class="btn btn-default">取消</button>
|
||||||
|
<button type="button" id="btnSave" class="btn btn-info">保存</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- /.box-footer -->
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="box box-default">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">参数配置说明</h3>
|
||||||
|
</div><!-- /.box-header -->
|
||||||
|
<div class="box-body">
|
||||||
|
<a class="product-title"><strong>扫描网段</strong><span class="label label-danger pull-right">必填参数</span></a>
|
||||||
|
<p><small>网络扫描地址列表,列表中可以包含一个或多个网段,也可以是一个或多个地址区间,例如['192.168.100.0/24', '192.168.100.10-20']</small></p>
|
||||||
|
<a class="product-title"><strong>登陆用户</strong><span class="label label-danger pull-right">必填参数</span></a>
|
||||||
|
<p><small>系统登陆测试使用的用户名,默认root。</small></p>
|
||||||
|
<a class="product-title"><strong>登陆密码</strong><span class="label label-danger pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统登陆测试使用的密码,如过认证方式为密码认证,必须填写密码信息。</small></p>
|
||||||
|
<a class="product-title"><strong>密钥路径</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统登陆测试使用的密钥存放路径,如过认证方式为私钥认证,必须填写密钥路径。</small></p>
|
||||||
|
<a class="product-title"><strong>运行命令</strong><span class="label label-default pull-right">预定义参数</span></a>
|
||||||
|
<p><small>登陆系统后运行的基本命令,用来获取系统基本信息,当扫描方式为加强扫描时,才会执行运行命令,运行命令为预定义,禁止修改。</small></p>
|
||||||
|
<a class="product-title"><strong>认证方式</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统登陆认证方式,包括密码认证和私钥认证两种方式,当扫描方式为加强扫描时,需要设定认证方式。</small></p>
|
||||||
|
<a class="product-title"><strong>扫描方式</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>系统扫描方式,包括基本扫描和加强扫描,当设置为加强扫描时会登陆系统执行运行命令获取系统信息。</small></p>
|
||||||
|
<a class="product-title"><strong>收件邮箱</strong><span class="label label-primary pull-right">可选参数</span></a>
|
||||||
|
<p><small>用于接收扫描结果邮件,可以通过发送邮件选项设置是否发送通知邮件。</small></p>
|
||||||
|
</div><!-- /.box-body -->
|
||||||
|
</div><!-- /.box -->
|
||||||
|
</div>
|
||||||
|
<!-- /.box -->
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- /.content -->
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
<script src="{% static 'js/plugins/layer/layer.js' %}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// 菜单选中高亮
|
||||||
|
$(function () {
|
||||||
|
$('#CMDB-PORTAL').addClass('active');
|
||||||
|
$('#CMDB-PORTAL-SCAN_CONFIG').addClass('active');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#btnSave").click(function () {
|
||||||
|
var hosts = $("#addForm").serialize();
|
||||||
|
$.ajax({
|
||||||
|
type: $("#addForm").attr('method'),
|
||||||
|
url: "{% url 'cmdb:portal-scan_config' %}",
|
||||||
|
cache: false,
|
||||||
|
data: hosts,
|
||||||
|
success: function (msg) {
|
||||||
|
if (msg.result) {
|
||||||
|
layer.alert('数据保存成功!', {icon: 1});
|
||||||
|
} else {
|
||||||
|
layer.alert('数据保存失败', {icon: 5});
|
||||||
|
//$('errorMessage').html(msg.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*点取消刷新新页面*/
|
||||||
|
$("#btnCancel").click(function () {
|
||||||
|
window.location.reload();
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user