jumpserver/apps/accounts/automations/check_account/manager.py

152 lines
4.6 KiB
Python
Raw Normal View History

2024-11-14 11:00:29 +00:00
import re
from collections import defaultdict
2024-11-11 03:12:10 +00:00
from django.utils import timezone
2024-11-14 11:00:29 +00:00
from accounts.models import Account, AccountRisk
2024-11-18 11:06:04 +00:00
from assets.automations.base.manager import BaseManager
from common.decorators import bulk_create_decorator, bulk_update_decorator
2024-11-18 03:22:46 +00:00
from common.utils.strings import color_fmt
2024-11-14 11:00:29 +00:00
def is_weak_password(password):
# 判断密码长度
if len(password) < 8:
return True
# 判断是否只有一种字符类型
if password.isdigit() or password.isalpha():
return True
# 判断是否只包含数字或字母
if password.islower() or password.isupper():
return True
# 判断是否包含常见弱密码
common_passwords = ["123456", "password", "12345678", "qwerty", "abc123"]
if password.lower() in common_passwords:
return True
# 正则表达式判断字符多样性(数字、字母、特殊字符)
if (
not re.search(r"[A-Za-z]", password)
or not re.search(r"[0-9]", password)
or not re.search(r"[\W_]", password)
):
2024-11-14 11:00:29 +00:00
return True
return False
@bulk_create_decorator(AccountRisk)
2024-11-20 11:12:28 +00:00
def create_risk(data):
return AccountRisk(**data)
@bulk_update_decorator(AccountRisk, update_fields=["details"])
def update_risk(risk):
return risk
2024-11-14 11:00:29 +00:00
def check_account_secrets(accounts, assets):
now = timezone.now().isoformat()
risks = []
tmpl = "Check account %s: %s"
summary = defaultdict(int)
2024-11-18 03:22:46 +00:00
result = defaultdict(list)
summary["accounts"] = len(accounts)
summary["assets"] = len(assets)
2024-11-18 03:22:46 +00:00
2024-11-14 11:00:29 +00:00
for account in accounts:
2024-11-18 03:22:46 +00:00
result_item = {
"asset": str(account.asset),
"username": account.username,
2024-11-18 03:22:46 +00:00
}
2024-11-14 11:00:29 +00:00
if not account.secret:
print(tmpl % (account, "no secret"))
summary["no_secret"] += 1
result["no_secret"].append(result_item)
2024-11-14 11:00:29 +00:00
continue
if is_weak_password(account.secret):
2024-11-18 03:22:46 +00:00
print(tmpl % (account, color_fmt("weak", "red")))
summary["weak_password"] += 1
result["weak_password"].append(result_item)
risks.append(
{
"account": account,
"risk": "weak_password",
}
)
2022-10-27 10:53:10 +00:00
else:
summary["ok"] += 1
result["ok"].append(result_item)
2024-11-18 03:22:46 +00:00
print(tmpl % (account, color_fmt("ok", "green")))
2024-11-12 08:00:41 +00:00
2024-11-14 11:00:29 +00:00
origin_risks = AccountRisk.objects.filter(asset__in=assets)
origin_risks_dict = {f"{r.asset_id}_{r.username}_{r.risk}": r for r in origin_risks}
2024-11-13 08:09:07 +00:00
2024-11-14 11:00:29 +00:00
for d in risks:
key = f'{d["account"].asset_id}_{d["account"].username}_{d["risk"]}'
origin_risk = origin_risks_dict.get(key)
2024-11-12 08:00:41 +00:00
2024-11-14 11:00:29 +00:00
if origin_risk:
2024-12-03 09:49:04 +00:00
origin_risk.details.append({"datetime": now, 'type': 'refind'})
update_risk(origin_risk)
2024-11-11 03:12:10 +00:00
else:
create_risk({
"asset": d["account"].asset,
"username": d["account"].username,
"risk": d["risk"],
2024-12-03 09:49:04 +00:00
"details": [{"datetime": now, 'type': 'init'}],
})
2024-11-18 03:22:46 +00:00
return summary, result
2024-11-14 11:00:29 +00:00
2024-11-18 11:06:04 +00:00
class CheckAccountManager(BaseManager):
2024-11-19 10:05:59 +00:00
batch_size = 100
2024-11-18 11:06:04 +00:00
2024-11-14 11:00:29 +00:00
def __init__(self, execution):
2024-11-18 11:06:04 +00:00
super().__init__(execution)
self.accounts = []
2024-11-14 11:00:29 +00:00
self.assets = []
def pre_run(self):
self.assets = self.execution.get_all_assets()
2024-11-18 03:22:46 +00:00
self.execution.date_start = timezone.now()
self.execution.save(update_fields=["date_start"])
2024-11-14 11:00:29 +00:00
2024-11-18 11:06:04 +00:00
def do_run(self, *args, **kwargs):
for engine in self.execution.snapshot.get("engines", []):
if engine == "check_account_secret":
2024-11-14 11:00:29 +00:00
handle = check_account_secrets
else:
continue
2024-11-18 11:06:04 +00:00
for i in range(0, len(self.assets), self.batch_size):
_assets = self.assets[i : i + self.batch_size]
2024-11-14 11:00:29 +00:00
accounts = Account.objects.filter(asset__in=_assets)
2024-11-18 03:22:46 +00:00
summary, result = handle(accounts, _assets)
2024-11-14 11:00:29 +00:00
2024-11-18 03:22:46 +00:00
for k, v in summary.items():
self.summary[k] = self.summary.get(k, 0) + v
for k, v in result.items():
self.result[k].extend(v)
2024-11-19 10:05:59 +00:00
def get_report_subject(self):
return "Check account report of %s" % self.execution.id
def get_report_template(self):
return "accounts/check_account_report.html"
2024-11-19 10:05:59 +00:00
2024-11-18 11:06:04 +00:00
def print_summary(self):
tmpl = (
"\n---\nSummary: \nok: %s, weak password: %s, no secret: %s, using time: %ss"
% (
self.summary["ok"],
self.summary["weak_password"],
self.summary["no_secret"],
int(self.duration),
)
2024-11-14 11:00:29 +00:00
)
print(tmpl)