diff --git a/apps/applications/templates/applications/remote_app_list.html b/apps/applications/templates/applications/remote_app_list.html index 3dbe4f8eb..a308bf911 100644 --- a/apps/applications/templates/applications/remote_app_list.html +++ b/apps/applications/templates/applications/remote_app_list.html @@ -1,10 +1,8 @@ {% extends '_base_list.html' %} {% load i18n static %} {% block help_message %} -
{% endblock %} {% block table_search %}{% endblock %} {% block table_container %} @@ -84,4 +82,4 @@ $(document).ready(function(){ }, 3000); }); -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/apps/assets/migrations/0043_auto_20191114_1111.py b/apps/assets/migrations/0043_auto_20191114_1111.py new file mode 100644 index 000000000..a07dee6bb --- /dev/null +++ b/apps/assets/migrations/0043_auto_20191114_1111.py @@ -0,0 +1,23 @@ +# 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'), + ), + ] diff --git a/apps/assets/models/gathered_user.py b/apps/assets/models/gathered_user.py index 282f9293a..d00021c56 100644 --- a/apps/assets/models/gathered_user.py +++ b/apps/assets/models/gathered_user.py @@ -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): diff --git a/apps/assets/serializers/gathered_user.py b/apps/assets/serializers/gathered_user.py index 956c19c6b..c055e25bd 100644 --- a/apps/assets/serializers/gathered_user.py +++ b/apps/assets/serializers/gathered_user.py @@ -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 diff --git a/apps/assets/tasks/const.py b/apps/assets/tasks/const.py index 61a9580ed..5b7db13cd 100644 --- a/apps/assets/tasks/const.py +++ b/apps/assets/tasks/const.py @@ -94,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 = [ diff --git a/apps/assets/tasks/gather_asset_users.py b/apps/assets/tasks/gather_asset_users.py index efeecc25e..7dfe0fb01 100644 --- a/apps/assets/tasks/gather_asset_users.py +++ b/apps/assets/tasks/gather_asset_users.py @@ -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, ) diff --git a/apps/assets/templates/assets/_asset_group_bulk_update_modal.html b/apps/assets/templates/assets/_asset_group_bulk_update_modal.html index 61ac04fa6..7df6c4ede 100644 --- a/apps/assets/templates/assets/_asset_group_bulk_update_modal.html +++ b/apps/assets/templates/assets/_asset_group_bulk_update_modal.html @@ -31,11 +31,11 @@