mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-07-17 16:31:28 +00:00
perf: windows ad gather account
This commit is contained in:
parent
d6b1a577fc
commit
1254d28463
@ -13,6 +13,7 @@ def parse_date(date_str, default=None):
|
|||||||
formats = [
|
formats = [
|
||||||
'%Y/%m/%d %H:%M:%S',
|
'%Y/%m/%d %H:%M:%S',
|
||||||
'%Y-%m-%dT%H:%M:%S',
|
'%Y-%m-%dT%H:%M:%S',
|
||||||
|
'%Y-%m-%d %H:%M:%S',
|
||||||
'%d-%m-%Y %H:%M:%S',
|
'%d-%m-%Y %H:%M:%S',
|
||||||
'%Y/%m/%d',
|
'%Y/%m/%d',
|
||||||
'%d-%m-%Y',
|
'%d-%m-%Y',
|
||||||
@ -26,7 +27,6 @@ def parse_date(date_str, default=None):
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
# TODO 后期会挪到 playbook 中
|
|
||||||
class GatherAccountsFilter:
|
class GatherAccountsFilter:
|
||||||
def __init__(self, tp):
|
def __init__(self, tp):
|
||||||
self.tp = tp
|
self.tp = tp
|
||||||
@ -208,14 +208,35 @@ class GatherAccountsFilter:
|
|||||||
key, value = parts
|
key, value = parts
|
||||||
user_info[key.strip()] = value.strip()
|
user_info[key.strip()] = value.strip()
|
||||||
detail = {'groups': user_info.get('Global Group memberships', ''), }
|
detail = {'groups': user_info.get('Global Group memberships', ''), }
|
||||||
user = {
|
|
||||||
'username': user_info.get('User name', ''),
|
username = user_info.get('User name')
|
||||||
'date_password_change': parse_date(user_info.get('Password last set', '')),
|
if not username:
|
||||||
'date_password_expired': parse_date(user_info.get('Password expires', '')),
|
continue
|
||||||
'date_last_login': parse_date(user_info.get('Last logon', '')),
|
|
||||||
|
result[username] = {
|
||||||
|
'username': username,
|
||||||
|
'date_password_change': parse_date(user_info.get('Password last set')),
|
||||||
|
'date_password_expired': parse_date(user_info.get('Password expires')),
|
||||||
|
'date_last_login': parse_date(user_info.get('Last logon')),
|
||||||
|
'groups': detail,
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def windows_ad_filter(info):
|
||||||
|
result = {}
|
||||||
|
for user_info in info['user_details']:
|
||||||
|
detail = {'groups': user_info.get('GlobalGroupMemberships', ''), }
|
||||||
|
username = user_info.get('SamAccountName')
|
||||||
|
if not username:
|
||||||
|
continue
|
||||||
|
result[username] = {
|
||||||
|
'username': username,
|
||||||
|
'date_password_change': parse_date(user_info.get('PasswordLastSet')),
|
||||||
|
'date_password_expired': parse_date(user_info.get('PasswordExpires')),
|
||||||
|
'date_last_login': parse_date(user_info.get('LastLogonDate')),
|
||||||
'groups': detail,
|
'groups': detail,
|
||||||
}
|
}
|
||||||
result[user['username']] = user
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -4,10 +4,10 @@ version: 1
|
|||||||
method: gather_accounts
|
method: gather_accounts
|
||||||
category:
|
category:
|
||||||
- host
|
- host
|
||||||
- ds
|
|
||||||
type:
|
type:
|
||||||
- windows
|
- windows
|
||||||
- windows_ad
|
|
||||||
|
|
||||||
i18n:
|
i18n:
|
||||||
Windows account gather:
|
Windows account gather:
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
- hosts: demo
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- name: Import ActiveDirectory module
|
||||||
|
win_shell: Import-Module ActiveDirectory
|
||||||
|
args:
|
||||||
|
warn: false
|
||||||
|
|
||||||
|
- name: Get the SamAccountName list of all AD users
|
||||||
|
win_shell: |
|
||||||
|
Import-Module ActiveDirectory
|
||||||
|
Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName
|
||||||
|
register: ad_user_list
|
||||||
|
|
||||||
|
- name: Set the all_users variable
|
||||||
|
set_fact:
|
||||||
|
all_users: "{{ ad_user_list.stdout_lines }}"
|
||||||
|
|
||||||
|
- name: Get detailed information for each user
|
||||||
|
win_shell: |
|
||||||
|
Import-Module ActiveDirectory
|
||||||
|
|
||||||
|
$user = Get-ADUser -Identity {{ item }} -Properties Name, SamAccountName, Enabled, LastLogonDate, PasswordLastSet, msDS-UserPasswordExpiryTimeComputed, MemberOf
|
||||||
|
|
||||||
|
$globalGroups = @()
|
||||||
|
if ($user.MemberOf) {
|
||||||
|
$globalGroups = $user.MemberOf | ForEach-Object {
|
||||||
|
try {
|
||||||
|
$group = Get-ADGroup $_ -ErrorAction Stop
|
||||||
|
if ($group.GroupScope -eq 'Global') { $group.Name }
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$passwordExpiry = $null
|
||||||
|
$expiryRaw = $user.'msDS-UserPasswordExpiryTimeComputed'
|
||||||
|
if ($expiryRaw) {
|
||||||
|
try {
|
||||||
|
$passwordExpiry = [datetime]::FromFileTime($expiryRaw)
|
||||||
|
} catch {
|
||||||
|
$passwordExpiry = $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = [PSCustomObject]@{
|
||||||
|
Name = $user.Name
|
||||||
|
SamAccountName = $user.SamAccountName
|
||||||
|
Enabled = $user.Enabled
|
||||||
|
LastLogonDate = if ($user.LastLogonDate) { $user.LastLogonDate.ToString("yyyy-MM-dd HH:mm:ss") } else { $null }
|
||||||
|
PasswordLastSet = if ($user.PasswordLastSet) { $user.PasswordLastSet.ToString("yyyy-MM-dd HH:mm:ss") } else { $null }
|
||||||
|
PasswordExpires = if ($passwordExpiry) { $passwordExpiry.ToString("yyyy-MM-dd HH:mm:ss") } else { $null }
|
||||||
|
GlobalGroupMemberships = $globalGroups
|
||||||
|
}
|
||||||
|
|
||||||
|
$output | ConvertTo-Json -Depth 3
|
||||||
|
loop: "{{ all_users }}"
|
||||||
|
register: ad_user_details
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
info:
|
||||||
|
user_details: >-
|
||||||
|
{{
|
||||||
|
ad_user_details.results
|
||||||
|
| selectattr('rc', 'equalto', 0)
|
||||||
|
| map(attribute='stdout')
|
||||||
|
| select('truthy')
|
||||||
|
| map('from_json')
|
||||||
|
}}
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: info
|
@ -0,0 +1,15 @@
|
|||||||
|
id: gather_accounts_windows_ad
|
||||||
|
name: "{{ 'Windows account gather' | trans }}"
|
||||||
|
version: 1
|
||||||
|
method: gather_accounts
|
||||||
|
category:
|
||||||
|
- ds
|
||||||
|
|
||||||
|
type:
|
||||||
|
- windows_ad
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
Windows account gather:
|
||||||
|
zh: 使用命令 Get-ADUser 收集 Windows 账号
|
||||||
|
ja: コマンド Get-ADUser を使用して Windows アカウントを収集する
|
||||||
|
en: Using command Get-ADUser to gather accounts
|
@ -1,6 +1,6 @@
|
|||||||
|
import time
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import time
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from accounts.const import AutomationTypes
|
from accounts.const import AutomationTypes
|
||||||
@ -222,6 +222,7 @@ class GatherAccountsManager(AccountBasePlaybookManager):
|
|||||||
def _collect_asset_account_info(self, asset, info):
|
def _collect_asset_account_info(self, asset, info):
|
||||||
result = self._filter_success_result(asset.type, info)
|
result = self._filter_success_result(asset.type, info)
|
||||||
accounts = []
|
accounts = []
|
||||||
|
|
||||||
for username, info in result.items():
|
for username, info in result.items():
|
||||||
self.asset_usernames_mapper[str(asset.id)].add(username)
|
self.asset_usernames_mapper[str(asset.id)].add(username)
|
||||||
|
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
# Generated by Django 4.1.13 on 2025-03-31 02:49
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
import django
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
from assets.const.types import AllTypes
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
dependencies = [
|
|
||||||
("assets", "0015_automationexecution_type"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RunPython(add_ad_host_type),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="DS",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"asset_ptr",
|
|
||||||
models.OneToOneField(
|
|
||||||
auto_created=True,
|
|
||||||
on_delete=django.db.models.deletion.CASCADE,
|
|
||||||
parent_link=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
to="assets.asset",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"domain_name",
|
|
||||||
models.CharField(
|
|
||||||
blank=True,
|
|
||||||
default="",
|
|
||||||
max_length=128,
|
|
||||||
verbose_name="Domain name",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Active Directory",
|
|
||||||
},
|
|
||||||
bases=("assets.asset",),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="platform",
|
|
||||||
name="ds",
|
|
||||||
field=models.ForeignKey(
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
on_delete=django.db.models.deletion.SET_NULL,
|
|
||||||
related_name="ad_platforms",
|
|
||||||
to="assets.ds",
|
|
||||||
verbose_name="Active Directory",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="platform",
|
|
||||||
name="ds_enabled",
|
|
||||||
field=models.BooleanField(default=False, verbose_name="DS enabled"),
|
|
||||||
),
|
|
||||||
]
|
|
@ -48,7 +48,7 @@ def add_ds_platforms(apps, schema_editor):
|
|||||||
|
|
||||||
},
|
},
|
||||||
"gather_accounts_enabled": true,
|
"gather_accounts_enabled": true,
|
||||||
"gather_accounts_method": "gather_accounts_windows",
|
"gather_accounts_method": "gather_accounts_windows_ad",
|
||||||
"gather_accounts_params": {
|
"gather_accounts_params": {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@ -194,6 +195,7 @@ class JMSInventory:
|
|||||||
secret_info = {k: v for k, v in asset.secret_info.items() if v}
|
secret_info = {k: v for k, v in asset.secret_info.items() if v}
|
||||||
host = {
|
host = {
|
||||||
'name': name,
|
'name': name,
|
||||||
|
'local_python_interpreter': sys.executable,
|
||||||
'jms_asset': {
|
'jms_asset': {
|
||||||
'id': str(asset.id), 'name': asset.name, 'address': asset.address,
|
'id': str(asset.id), 'name': asset.name, 'address': asset.address,
|
||||||
'type': tp, 'category': category,
|
'type': tp, 'category': category,
|
||||||
|
Loading…
Reference in New Issue
Block a user