1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# ~*~ coding: utf-8 ~*~
import re
from collections import defaultdict
from celery import shared_task
from django.utils.translation import ugettext as _
from orgs.utils import tmp_to_org
from common.utils import get_logger
from ..models import GatheredUser, Node
from .utils import clean_hosts
from . import const
__all__ = ['gather_asset_users', 'gather_nodes_asset_users']
logger = get_logger(__name__)
space = re.compile('\s+')
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():
if ignore_login_shell.search(attr[-1]):
continue
users.append(username)
return users
def parse_windows_result_to_users(result):
task_result = []
for task_name, raw in result.items():
res = raw.get('stdout_lines', {})
if res:
task_result = res
break
if not task_result:
return []
users = []
for i in range(4):
task_result.pop(0)
for i in range(2):
task_result.pop()
for line in task_result:
user = space.split(line)
if user[0]:
users.append(user[0])
return users
def add_asset_users(assets, results):
assets_map = {a.hostname: a for a in assets}
parser_map = {
'linux': parse_linux_result_to_users,
'windows': parse_windows_result_to_users
}
assets_users_map = {}
for platform, platform_results in results.items():
for hostname, res in platform_results.items():
parse = parser_map.get(platform)
users = parse(res)
logger.debug('Gathered host users: {} {}'.format(hostname, users))
asset = assets_map.get(hostname)
if not asset:
continue
assets_users_map[asset] = users
for asset, users in assets_users_map.items():
with tmp_to_org(asset.org_id):
GatheredUser.objects.filter(asset=asset, present=True)\
.update(present=False)
for username in users:
defaults = {'asset': asset, 'username': username, 'present': True}
GatheredUser.objects.update_or_create(
defaults=defaults, asset=asset, username=username,
)
@shared_task(queue="ansible")
def gather_asset_users(assets, task_name=None):
from ops.utils import update_or_create_ansible_task
if task_name is None:
task_name = _("Gather assets users")
assets = clean_hosts(assets)
if not assets:
return
hosts_category = {
'linux': {
'hosts': [],
'tasks': const.GATHER_ASSET_USERS_TASKS
},
'windows': {
'hosts': [],
'tasks': const.GATHER_ASSET_USERS_TASKS_WINDOWS
}
}
for asset in assets:
hosts_list = hosts_category['windows']['hosts'] if asset.is_windows() \
else hosts_category['linux']['hosts']
hosts_list.append(asset)
results = {'linux': defaultdict(dict), 'windows': defaultdict(dict)}
for k, value in hosts_category.items():
if not value['hosts']:
continue
_task_name = '{}: {}'.format(task_name, k)
task, created = update_or_create_ansible_task(
task_name=_task_name, hosts=value['hosts'], tasks=value['tasks'],
pattern='all', options=const.TASK_OPTIONS,
run_as_admin=True, created_by=value['hosts'][0].org_id,
)
raw, summary = task.run()
results[k].update(raw['ok'])
add_asset_users(assets, results)
@shared_task(queue="ansible")
def gather_nodes_asset_users(nodes_key):
assets = Node.get_nodes_all_assets(nodes_key)
assets_groups_by_100 = [assets[i:i+100] for i in range(0, len(assets), 100)]
for _assets in assets_groups_by_100:
gather_asset_users(_assets)