Commit 2ef487a9 authored by ibuler's avatar ibuler

[Update] 修改收集用户

parent 05e7311b
# Generated by Django 2.2.5 on 2019-11-14 03:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0042_favoriteasset'),
]
operations = [
migrations.AddField(
model_name='gathereduser',
name='date_last_login',
field=models.DateTimeField(null=True, verbose_name='Date last login'),
),
migrations.AddField(
model_name='gathereduser',
name='ip_last_login',
field=models.CharField(default='', max_length=39, verbose_name='IP last login'),
),
]
......@@ -12,13 +12,12 @@ __all__ = ['GatheredUser']
class GatheredUser(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, verbose_name=_("Asset"))
username = models.CharField(max_length=32, blank=True, db_index=True,
verbose_name=_('Username'))
username = models.CharField(max_length=32, blank=True, db_index=True, verbose_name=_('Username'))
present = models.BooleanField(default=True, verbose_name=_("Present"))
date_created = models.DateTimeField(auto_now_add=True,
verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True,
verbose_name=_("Date updated"))
date_last_login = models.DateTimeField(null=True, verbose_name=_("Date last login"))
ip_last_login = models.CharField(max_length=39, default='', verbose_name=_("IP last login"))
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created"))
date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated"))
@property
def hostname(self):
......
......@@ -12,6 +12,7 @@ class GatheredUserSerializer(OrgResourceModelSerializerMixin):
model = GatheredUser
fields = [
'id', 'asset', 'hostname', 'ip', 'username',
'date_last_login', 'ip_last_login',
'present', 'date_created', 'date_updated'
]
read_only_fields = fields
......
......@@ -7,10 +7,7 @@ from django.utils.translation import ugettext_lazy as _
ENV_PERIOD_TASK = os.environ.get("PERIOD_TASK", "on") == 'on'
ENV_PERIOD_TASK_ENABLED = os.environ.get("PERIOD_TASK_ENABLED", "on") == "on"
PERIOD_TASK_ENABLED = settings.CONFIG.PERIOD_TASK_ENABLE \
and ENV_PERIOD_TASK \
and ENV_PERIOD_TASK_ENABLED
PERIOD_TASK_ENABLED = settings.PERIOD_TASK_ENABLED and ENV_PERIOD_TASK
UPDATE_ASSETS_HARDWARE_TASKS = [
{
......@@ -97,6 +94,13 @@ GATHER_ASSET_USERS_TASKS = [
"args": "database=passwd"
},
},
{
"name": "get last login",
"action": {
"module": "shell",
"args": "users=$(getent passwd | grep -v 'nologin' | grep -v 'shudown' | awk -F: '{ print $1 }');for i in $users;do last -F $i -1 | head -1 | grep -v '^$' | awk '{ print $1\"@\"$3\"@\"$5,$6,$7,$8 }';done"
}
}
]
GATHER_ASSET_USERS_TASKS_WINDOWS = [
......
......@@ -2,9 +2,10 @@
import re
from collections import defaultdict
from celery import shared_task
from celery import shared_task
from django.utils.translation import ugettext as _
from django.utils import timezone
from orgs.utils import tmp_to_org
from common.utils import get_logger
......@@ -19,19 +20,25 @@ ignore_login_shell = re.compile(r'nologin$|sync$|shutdown$|halt$')
def parse_linux_result_to_users(result):
task_result = {}
for task_name, raw in result.items():
res = raw.get('ansible_facts', {}).get('getent_passwd')
if res:
task_result = res
break
if not task_result or not isinstance(task_result, dict):
return []
users = []
for username, attr in task_result.items():
users = defaultdict(dict)
users_result = result.get('gather host users', {})\
.get('ansible_facts', {})\
.get('getent_passwd')
if not isinstance(users_result, dict):
users_result = {}
for username, attr in users_result.items():
if ignore_login_shell.search(attr[-1]):
continue
users.append(username)
users[username] = {}
last_login_result = result.get('get last login', {}).get('stdout_lines', [])
for line in last_login_result:
data = line.split('@')
if len(data) != 3:
continue
username, ip, dt = data
dt += ' +0800'
date = timezone.datetime.strptime(dt, '%b %d %H:%M:%S %Y %z')
users[username] = {"ip": ip, "date": date}
return users
......@@ -45,7 +52,7 @@ def parse_windows_result_to_users(result):
if not task_result:
return []
users = []
users = {}
for i in range(4):
task_result.pop(0)
......@@ -55,7 +62,7 @@ def parse_windows_result_to_users(result):
for line in task_result:
user = space.split(line)
if user[0]:
users.append(user[0])
users[user[0]] = {}
return users
......@@ -82,8 +89,12 @@ def add_asset_users(assets, results):
with tmp_to_org(asset.org_id):
GatheredUser.objects.filter(asset=asset, present=True)\
.update(present=False)
for username in users:
for username, data in users.items():
defaults = {'asset': asset, 'username': username, 'present': True}
if data.get("ip"):
defaults["ip_last_login"] = data["ip"]
if data.get("date"):
defaults["date_last_login"] = data["date"]
GatheredUser.objects.update_or_create(
defaults=defaults, asset=asset, username=username,
)
......
......@@ -303,9 +303,24 @@ function defaultCallback(action) {
return logging
}
function toggle() {
if (show === 0) {
$("#split-left").hide(500, function () {
$("#split-right").attr("class", "col-lg-12");
$("#toggle-icon").attr("class", "fa fa-angle-right fa-x");
show = 1;
});
} else {
$("#split-right").attr("class", "col-lg-9");
$("#toggle-icon").attr("class", "fa fa-angle-left fa-x");
$("#split-left").show(500);
show = 0;
}
}
$(document).ready(function () {
$('.treebox').css('height', window.innerHeight - 180);
$('.treebox').css('height', window.innerHeight - 60);
})
.on('click', '.btn-show-current-asset', function(){
hideRMenu();
......@@ -320,6 +335,9 @@ $(document).ready(function () {
$('#show_current_asset').css('display', 'inline-block');
setCookie('show_current_asset', '');
location.reload();
}).on('click', '.tree-toggle-btn', function (e) {
e.preventDefault();
toggle();
})
</script>
......@@ -48,12 +48,12 @@
{% block content %}
<div class="wrapper wrapper-content">
<div class="row">
<div class="col-lg-3" id="split-left" style="padding-left: 3px">
<div class="col-lg-3" id="split-left" style="padding-left: 3px;padding-right: 0">
{% include 'assets/_node_tree.html' %}
</div>
<div class="col-lg-9 animated fadeInRight" id="split-right">
<div class="tree-toggle">
<div class="btn btn-sm btn-primary tree-toggle-btn" onclick="toggle()">
<div class="tree-toggle" style="z-index: 9999">
<div class="btn btn-sm btn-primary tree-toggle-btn">
<i class="fa fa-angle-left fa-x" id="toggle-icon"></i>
</div>
</div>
......
This diff is collapsed.
......@@ -246,30 +246,35 @@ class AdHoc(models.Model):
time_start = time.time()
date_start = timezone.now()
is_success = False
summary = {}
raw = ''
try:
date_start_s = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Start task: {}").format(date_start_s, self.task.name))
raw, summary = self._run_only()
is_success = summary.get('success', False)
return raw, summary
except Exception as e:
logger.error(e, exc_info=True)
summary = {}
raw = {"dark": {"all": str(e)}, "contacted": []}
return raw, summary
finally:
date_end = timezone.now()
date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Task finish").format(date_end_s))
print('.\n\n.')
try:
summary_text = json.dumps(summary)
except json.JSONDecodeError:
summary_text = '{}'
AdHocRunHistory.objects.filter(id=history.id).update(
date_start=date_start,
is_finished=True,
is_success=is_success,
date_finished=timezone.now(),
timedelta=time.time() - time_start
timedelta=time.time() - time_start,
_summary=summary_text
)
return raw, summary
def _run_only(self):
Task.objects.filter(id=self.task.id).update(date_updated=timezone.now())
......@@ -321,10 +326,9 @@ class AdHoc(models.Model):
except AdHocRunHistory.DoesNotExist:
return None
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
super().save(force_insert=force_insert, force_update=force_update,
using=using, update_fields=update_fields)
def save(self, **kwargs):
instance = super().save(**kwargs)
return instance
def __str__(self):
return "{} of {}".format(self.task.name, self.short_id)
......@@ -393,7 +397,10 @@ class AdHocRunHistory(models.Model):
@summary.setter
def summary(self, item):
self._summary = json.dumps(item)
try:
self._summary = json.dumps(item)
except json.JSONDecodeError:
self._summary = json.dumps({})
@property
def success_hosts(self):
......
......@@ -23,12 +23,12 @@
{% block content %}
<div class="wrapper wrapper-content">
<div class="row">
<div class="col-lg-3" id="split-left" style="padding-left: 3px">
<div class="col-lg-3" id="split-left" style="padding-left: 3px;padding-right: 0">
{% include 'assets/_node_tree.html' %}
</div>
<div class="col-lg-9 animated fadeInRight" id="split-right">
<div class="tree-toggle">
<div class="btn btn-sm btn-primary tree-toggle-btn" onclick="toggle()">
<div class="btn btn-sm btn-primary tree-toggle-btn">
<i class="fa fa-angle-left fa-x" id="toggle-icon"></i>
</div>
</div>
......@@ -209,20 +209,6 @@ function initTree() {
})
}
function toggle() {
if (show === 0) {
$("#split-left").hide(500, function () {
$("#split-right").attr("class", "col-lg-12");
$("#toggle-icon").attr("class", "fa fa-angle-right fa-x");
show = 1;
});
} else {
$("#split-right").attr("class", "col-lg-9");
$("#toggle-icon").attr("class", "fa fa-angle-left fa-x");
$("#split-left").show(500);
show = 0;
}
}
$(document).ready(function(){
initTable();
......
# Generated by Django 2.2.5 on 2019-11-14 03:05
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tickets', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='comment',
name='ticket',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='tickets.Ticket'),
),
migrations.AlterField(
model_name='ticket',
name='type',
field=models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm')], default='general', max_length=16, verbose_name='Type'),
),
]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment