scan&login execution

This commit is contained in:
RobbieHan
2019-01-11 17:53:32 +08:00
parent 371b1ebbe3
commit 9c204933e8
7 changed files with 168 additions and 10 deletions

View File

@@ -0,0 +1 @@
default_app_config = 'cmdb.apps.CmdbConfig'

View File

@@ -2,4 +2,7 @@ from django.apps import AppConfig
class CmdbConfig(AppConfig):
name = 'cmdb'
name = 'cmdb'
def ready(self):
from .signals import auto_delete_file

View File

@@ -1,9 +1,9 @@
import os
from datetime import datetime
from django.db import models
from django.contrib.auth import get_user_model
from django.dispatch import receiver
from simple_history.models import HistoricalRecords
User = get_user_model()
@@ -99,20 +99,24 @@ class DeviceInfo(AbstractMode, DeviceAbstract, TimeAbstract):
buyDate = models.DateField(default=datetime.now, verbose_name="购买日期")
warrantyDate = models.DateField(default=datetime.now, verbose_name="到保日期")
desc = models.TextField(blank=True, default='', verbose_name='备注信息')
changed_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
history = HistoricalRecords(excluded_fields=['add_time', 'modify_time'])
class Meta:
verbose_name = '设备信息'
verbose_name_plural = verbose_name
@property
def _history_user(self):
return self.changed_by
@_history_user.setter
def _history_user(self, value):
self.changed_by = value
class DeviceFile(TimeAbstract):
device = models.ForeignKey('DeviceInfo', blank=True, null=True, on_delete=models.SET_NULL, verbose_name='设备')
file_content = models.FileField(upload_to="asset_file/%Y/%m", null=True, blank=True, verbose_name="资产文件")
upload_user = models.CharField(max_length=20, verbose_name="上传人")
@receiver(models.signals.post_delete, sender=DeviceFile)
def auto_delete_file(sender, instance, **kwargs):
if instance.file_content:
if os.path.isfile(instance.file_content.path):
os.remove(instance.file_content.path)

13
apps/cmdb/signals.py Normal file
View File

@@ -0,0 +1,13 @@
import os
from django.dispatch import receiver
from django.db.models.signals import post_delete
from .models import DeviceFile
@receiver(post_delete, sender=DeviceFile)
def auto_delete_file(sender, instance, **kwargs):
if instance.file_content:
if os.path.isfile(instance.file_content.path):
os.remove(instance.file_content.path)

View File

@@ -8,6 +8,8 @@ from django.conf import settings
import yaml
import logging
import nmap
import paramiko
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sandboxMP.settings')
error_logger = logging.getLogger('sandbox_error')
@@ -72,3 +74,136 @@ class ConfigFileMixin:
"""
key = ['hosts', 'net_address']
return self.get_conf_content(*key)
class SandboxScan(ConfigFileMixin):
def basic_scan(self):
"""
Use ICMP discovery online hosts and return online hosts.
"""
hosts = self.get_net_address()
nm = nmap.PortScanner()
nm.scan(hosts=hosts, arguments='-n -sP -PE')
online_hosts = nm.all_hosts()
return online_hosts
def os_scan(self):
"""
Get the system type by nmap scan and return hosts list with os type.
"""
hosts = self.get_net_address()
nm = nmap.PortScanner()
nm.scan(hosts=hosts, arguments='-n sS -O')
online_hosts = []
for host in nm.all_hosts():
try:
os_type = nm[host]['osmatch'][0]['osclass'][0]['osfamily']
except Exception:
os_type = 'unknown'
host_dict = {'host': host, 'os': os_type}
online_hosts.append(host_dict)
return online_hosts
def get_net_address(self):
"""
Return the hosts that will be used to scan.
Subclasses can override this to return any hosts.`
"""
hosts_list = super().get_net_address()
hosts = ' '.join(str(i) for i in hosts_list)
return hosts
class LoginExecution(ConfigFileMixin):
def login_execution(self, auth_type='password', **kwargs):
"""
Support two authentication modes: password or private_key, and auth_type default is password.
"""
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
if auth_type == 'password':
ssh.connect(
kwargs['hostname'],
kwargs['port'],
kwargs['username'],
kwargs['password'],
timeout=3,
)
kwargs['auth_type'] = 'password'
elif auth_type == 'private_key':
kwargs['auth_type'] = 'private_key'
private_key = paramiko.RSAKey.from_private_key_file(kwargs['private_key'])
ssh.connect(
kwargs['hostname'],
kwargs['port'],
kwargs['username'],
private_key,
timeout=3,
)
kwargs['status'] = 'succeed'
kwargs['error_message'] = ''
commands = self.get_commands()
for key, value in commands.items():
stdin, stdout, stderr = ssh.exec_command(value, timeout=5)
result = str(stdout.read()).strip('b').strip("'").strip('\\n')
kwargs[key] = result
except Exception as e:
msg = '%(exc)s hostname %(hostname)s' % {
'exc': e,
'hostname': kwargs['hostname']
}
error_logger.error(msg)
kwargs['status'] = 'failed'
kwargs['error_message'] = str(e)
return kwargs
def password_login_execution(self, **kwargs):
"""
Login to the remote system with a password.
Kwargs is a dict containing hostname, port, username and password.
Example: kwargs = {'hostname': '172.16.3.101', 'port': 22, 'username': 'root', 'password': 'paw123'}
"""
return self.login_execution(**kwargs)
def private_key_login_execution(self, **kwargs):
"""
Login to the remote system with a private_key.
Kwargs is a dict containing hostname, port, username and private key.
Example:kwargs = {'hostname': '172.16.3.101', 'port': 22, 'username': 'root', 'private_key': '/root/.ssh/id_rsa'}
"""
return self.login_execution(auth_type='private_key', **kwargs)
def get_auth_type(self):
key = ['hosts', 'auth_type']
return self.get_conf_content(*key)
def get_ssh_username(self):
key = ['hosts', 'ssh_username']
return self.get_conf_content(*key)
def get_ssh_port(self):
key = ['hosts', 'ssh_port']
return self.get_conf_content(*key)
def get_ssh_password(self):
key = ['hosts', 'ssh_password']
return self.get_conf_content(*key)
def get_ssh_private_key(self):
key = ['hosts', 'ssh_private_key']
return self.get_conf_content(*key)
def get_email(self):
key = ['hosts', 'email']
return self.get_conf_content(*key)
def get_send_email(self):
key = ['hosts', 'send_email']
return self.get_conf_content(*key)
def get_scan_type(self):
key = ['hosts', 'scan_type']
return self.get_conf_content(*key)

View File

@@ -8,7 +8,7 @@ python-nmap==0.6.1
redis==3.0.1
pymongo==3.7.1
paramiko==2.4.2
pycrypto==2.6.1
django-simple-history==2.6.0
celery==4.2.1
celery-once==2.0.0
flower==0.9.2

View File

@@ -39,6 +39,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'simple_history',
'system',
'cmdb',
]
@@ -53,6 +54,7 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'apps.system.middleware.MenuCollection',
'apps.system.middleware.RbacMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
]
ROOT_URLCONF = 'sandboxMP.urls'