Skip to content

Commit

Permalink
scan&login execution
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbieHan committed Jan 11, 2019
1 parent 371b1eb commit 9c20493
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 10 deletions.
1 change: 1 addition & 0 deletions apps/cmdb/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
default_app_config = 'cmdb.apps.CmdbConfig'
5 changes: 4 additions & 1 deletion apps/cmdb/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@


class CmdbConfig(AppConfig):
name = 'cmdb'
name = 'cmdb'

def ready(self):
from .signals import auto_delete_file
20 changes: 12 additions & 8 deletions apps/cmdb/models.py
Original file line number Diff line number Diff line change
@@ -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()

Expand Down Expand Up @@ -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 changes: 13 additions & 0 deletions apps/cmdb/signals.py
Original file line number Diff line number Diff line change
@@ -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)
135 changes: 135 additions & 0 deletions apps/utils/sandbox_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import yaml
import logging
import nmap
import paramiko

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sandboxMP.settings')
error_logger = logging.getLogger('sandbox_error')
Expand Down Expand Up @@ -72,3 +74,136 @@ def get_net_address(self):
"""
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)
2 changes: 1 addition & 1 deletion requirements/pro.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions sandboxMP/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'simple_history',
'system',
'cmdb',
]
Expand All @@ -53,6 +54,7 @@
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'apps.system.middleware.MenuCollection',
'apps.system.middleware.RbacMiddleware',
'simple_history.middleware.HistoryRequestMiddleware',
]

ROOT_URLCONF = 'sandboxMP.urls'
Expand Down

0 comments on commit 9c20493

Please sign in to comment.