mirror of https://github.com/jumpserver/jumpserver
perf: add delete account action
parent
f72fc19ba6
commit
d89164db63
|
@ -30,7 +30,6 @@ __all__ = [
|
||||||
]
|
]
|
||||||
|
|
||||||
from ...filters import NodeFilterBackend
|
from ...filters import NodeFilterBackend
|
||||||
|
|
||||||
from ...risk_handlers import RiskHandler
|
from ...risk_handlers import RiskHandler
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -155,6 +155,19 @@ class AnalyseAccountRisk:
|
||||||
def _update_risk(self, account):
|
def _update_risk(self, account):
|
||||||
return account
|
return account
|
||||||
|
|
||||||
|
def lost_accounts(self, asset, lost_users):
|
||||||
|
if not self.check_risk:
|
||||||
|
return
|
||||||
|
for user in lost_users:
|
||||||
|
self._create_risk(
|
||||||
|
dict(
|
||||||
|
asset_id=str(asset.id),
|
||||||
|
username=user,
|
||||||
|
risk=RiskChoice.account_deleted,
|
||||||
|
details=[{"datetime": self.now.isoformat()}],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def analyse_risk(self, asset, ga, d, sys_found):
|
def analyse_risk(self, asset, ga, d, sys_found):
|
||||||
if not self.check_risk:
|
if not self.check_risk:
|
||||||
return
|
return
|
||||||
|
@ -289,6 +302,8 @@ class GatherAccountsManager(AccountBasePlaybookManager):
|
||||||
"username": username,
|
"username": username,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
risk_analyser = AnalyseAccountRisk(self.check_risk)
|
||||||
|
risk_analyser.lost_accounts(asset, lost_users)
|
||||||
|
|
||||||
# 收集的账号 比 账号列表多的, 有可能是账号中删掉了, 但这时候状态已经是 confirm 了
|
# 收集的账号 比 账号列表多的, 有可能是账号中删掉了, 但这时候状态已经是 confirm 了
|
||||||
# 标识状态为 待处理, 让管理员去确认
|
# 标识状态为 待处理, 让管理员去确认
|
||||||
|
|
|
@ -139,6 +139,7 @@ class Migration(migrations.Migration):
|
||||||
choices=[
|
choices=[
|
||||||
("long_time_no_login", "Long time no login"),
|
("long_time_no_login", "Long time no login"),
|
||||||
("new_found", "New found"),
|
("new_found", "New found"),
|
||||||
|
("account_deleted", "Account deleted"),
|
||||||
("groups_changed", "Groups change"),
|
("groups_changed", "Groups change"),
|
||||||
("sudoers_changed", "Sudo changed"),
|
("sudoers_changed", "Sudo changed"),
|
||||||
("authorized_keys_changed", "Authorized keys changed"),
|
("authorized_keys_changed", "Authorized keys changed"),
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
from itertools import islice
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import TextChoices
|
from django.db.models import TextChoices
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from itertools import islice
|
|
||||||
|
|
||||||
from common.const import ConfirmOrIgnore
|
from common.const import ConfirmOrIgnore
|
||||||
from common.db.models import JMSBaseModel
|
from common.db.models import JMSBaseModel
|
||||||
|
@ -41,6 +42,7 @@ class RiskChoice(TextChoices):
|
||||||
# 依赖自动发现的
|
# 依赖自动发现的
|
||||||
long_time_no_login = 'long_time_no_login', _('Long time no login') # 好久没登录的账号, 禁用、删除
|
long_time_no_login = 'long_time_no_login', _('Long time no login') # 好久没登录的账号, 禁用、删除
|
||||||
new_found = 'new_found', _('New found') # 未被纳管的账号, 纳管, 删除, 禁用
|
new_found = 'new_found', _('New found') # 未被纳管的账号, 纳管, 删除, 禁用
|
||||||
|
account_deleted = 'account_deleted', _('Account deleted') # 账号被删除, 纳管, 删除, 禁用
|
||||||
group_changed = 'groups_changed', _('Groups change') # 组变更, 确认
|
group_changed = 'groups_changed', _('Groups change') # 组变更, 确认
|
||||||
sudo_changed = 'sudoers_changed', _('Sudo changed') # sudo 变更, 确认
|
sudo_changed = 'sudoers_changed', _('Sudo changed') # sudo 变更, 确认
|
||||||
authorized_keys_changed = 'authorized_keys_changed', _('Authorized keys changed') # authorized_keys 变更, 确认
|
authorized_keys_changed = 'authorized_keys_changed', _('Authorized keys changed') # authorized_keys 变更, 确认
|
||||||
|
|
|
@ -8,7 +8,7 @@ from accounts.models import (
|
||||||
AccountRisk,
|
AccountRisk,
|
||||||
SecretType,
|
SecretType,
|
||||||
AutomationExecution,
|
AutomationExecution,
|
||||||
RiskChoice
|
RiskChoice, Account
|
||||||
)
|
)
|
||||||
from common.const import ConfirmOrIgnore
|
from common.const import ConfirmOrIgnore
|
||||||
from common.utils import random_string
|
from common.utils import random_string
|
||||||
|
@ -19,10 +19,11 @@ TYPE_CHOICES = [
|
||||||
("close", _("Close")),
|
("close", _("Close")),
|
||||||
("disable_remote", _("Disable remote")),
|
("disable_remote", _("Disable remote")),
|
||||||
("delete_remote", _("Delete remote")),
|
("delete_remote", _("Delete remote")),
|
||||||
|
("delete_account", _("Delete account")),
|
||||||
("delete_both", _("Delete remote")),
|
("delete_both", _("Delete remote")),
|
||||||
("add_account", _("Add account")),
|
("add_account", _("Add account")),
|
||||||
("change_password_add", _("Change password and Add")),
|
("change_password_add", _("Change password and Add")),
|
||||||
("change_password", _("Change password"))
|
("change_password", _("Change password")),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,6 +74,9 @@ class RiskHandler:
|
||||||
def handle_reopen(self):
|
def handle_reopen(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def handle_delete_account(self):
|
||||||
|
Account.objects.filter(asset=self.asset, username=self.username).delete()
|
||||||
|
|
||||||
def handle_close(self):
|
def handle_close(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -102,7 +106,7 @@ class RiskHandler:
|
||||||
present=True, status=ConfirmOrIgnore.confirmed
|
present=True, status=ConfirmOrIgnore.confirmed
|
||||||
)
|
)
|
||||||
self.risk = RiskChoice.new_found
|
self.risk = RiskChoice.new_found
|
||||||
|
|
||||||
risk = self.get_risk()
|
risk = self.get_risk()
|
||||||
risk.account = account
|
risk.account = account
|
||||||
risk.save()
|
risk.save()
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
{% include '_head_css_js.html' %}
|
{% include '_head_css_js.html' %}
|
||||||
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
|
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
|
||||||
<script src="{% static "js/jumpserver.js" %}?_=9"></script>
|
<script src="{% static "js/jumpserver.js" %}?_=9"></script>
|
||||||
|
<style>
|
||||||
|
.btn-sm i {
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -20,19 +25,18 @@
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<div>
|
<div>
|
||||||
<img src="{{ INTERFACE.logo_logout }}" style="margin: auto" width="82" height="82">
|
<img src="{{ INTERFACE.logo_logout }}" style="margin: auto" width="62" height="62" alt="logo">
|
||||||
<h2 style="display: inline">
|
<h2 style="display: inline">
|
||||||
{{ INTERFACE.login_title }}
|
{{ INTERFACE.login_title }}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<p></p>
|
<div class="alert alert-success info-messages">
|
||||||
<div class="alert alert-success info-messages" >
|
|
||||||
{{ msg|safe }}
|
{{ msg|safe }}
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-danger error-messages" style="display: none">
|
<div class="alert alert-danger error-messages" style="display: none"></div>
|
||||||
</div>
|
|
||||||
<div class="progress progress-bar-default progress-striped active">
|
<div class="progress progress-bar-default progress-striped active">
|
||||||
<div aria-valuemax="3600" aria-valuemin="0" aria-valuenow="43" role="progressbar" class="progress-bar">
|
<div aria-valuemax="3600" aria-valuemin="0" aria-valuenow="43" role="progressbar"
|
||||||
|
class="progress-bar">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -66,107 +70,111 @@
|
||||||
{% include '_foot_js.html' %}
|
{% include '_foot_js.html' %}
|
||||||
<script src="{% static "js/plugins/clipboard/clipboard.min.js" %}"></script>
|
<script src="{% static "js/plugins/clipboard/clipboard.min.js" %}"></script>
|
||||||
<script>
|
<script>
|
||||||
var errorMsgShow = false;
|
var errorMsgShow = false;
|
||||||
var errorMsgRef = $(".error-messages");
|
var errorMsgRef = $(".error-messages");
|
||||||
var infoMsgRef = $(".info-messages");
|
var infoMsgRef = $(".info-messages");
|
||||||
var timestamp = '{{ timestamp }}';
|
var timestamp = '{{ timestamp }}';
|
||||||
var progressBarRef = $(".progress-bar");
|
var progressBarRef = $(".progress-bar");
|
||||||
var interval, checkInterval;
|
var interval, checkInterval;
|
||||||
var url = "{% url 'api-auth:login-confirm-ticket-status' %}";
|
var url = "{% url 'api-auth:login-confirm-ticket-status' %}";
|
||||||
var successUrl = "{% url 'authentication:login-guard' %}";
|
var successUrl = "{% url 'authentication:login-guard' %}";
|
||||||
|
|
||||||
function doRequestAuth() {
|
function doRequestAuth() {
|
||||||
requestApi({
|
requestApi({
|
||||||
url: url,
|
url: url,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"X-JMS-LOGIN-TYPE": "W"
|
"X-JMS-LOGIN-TYPE": "W"
|
||||||
},
|
},
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (!data.error && data.msg === 'ok') {
|
if (!data.error && data.msg === 'ok') {
|
||||||
window.onbeforeunload = function(){};
|
window.onbeforeunload = function () {
|
||||||
window.location = "{% url 'authentication:login-guard' %}"
|
};
|
||||||
} else if (data.error !== "login_confirm_wait") {
|
window.location = "{% url 'authentication:login-guard' %}"
|
||||||
if (!errorMsgShow) {
|
} else if (data.error !== "login_confirm_wait") {
|
||||||
infoMsgRef.hide();
|
if (!errorMsgShow) {
|
||||||
errorMsgRef.show();
|
infoMsgRef.hide();
|
||||||
progressBarRef.addClass('progress-bar-danger');
|
errorMsgRef.show();
|
||||||
errorMsgShow = true;
|
progressBarRef.addClass('progress-bar-danger');
|
||||||
|
errorMsgShow = true;
|
||||||
|
}
|
||||||
|
clearInterval(interval);
|
||||||
|
clearInterval(checkInterval);
|
||||||
|
cancelTicket();
|
||||||
|
$(".copy-btn").attr('disabled', 'disabled');
|
||||||
|
errorMsgRef.html(data.msg)
|
||||||
}
|
}
|
||||||
clearInterval(interval);
|
},
|
||||||
clearInterval(checkInterval);
|
error: function (text, data) {
|
||||||
cancelTicket();
|
},
|
||||||
$(".copy-btn").attr('disabled', 'disabled');
|
flash_message: false, // 是否显示flash消息
|
||||||
errorMsgRef.html(data.msg)
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function initClipboard() {
|
||||||
|
var clipboard = new Clipboard('.btn-copy', {
|
||||||
|
text: function (trigger) {
|
||||||
|
var origin = window.location.origin;
|
||||||
|
var link = origin + $(".btn-copy").data('link');
|
||||||
|
return link
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
error: function (text, data) {
|
clipboard.on("success", function (e) {
|
||||||
},
|
toastr.success("{% trans "Copy success" %}")
|
||||||
flash_message: false, // 是否显示flash消息
|
})
|
||||||
})
|
}
|
||||||
}
|
|
||||||
function initClipboard() {
|
function handleProgressBar() {
|
||||||
var clipboard = new Clipboard('.btn-copy', {
|
var now = new Date().getTime() / 1000;
|
||||||
text: function (trigger) {
|
var offset = now - timestamp;
|
||||||
var origin = window.location.origin;
|
var percent = offset / 3600 * 100;
|
||||||
var link = origin + $(".btn-copy").data('link');
|
if (percent > 100) {
|
||||||
return link
|
percent = 100
|
||||||
}
|
}
|
||||||
});
|
progressBarRef.css("width", percent + '%');
|
||||||
clipboard.on("success", function (e) {
|
progressBarRef.attr('aria-valuenow', offset);
|
||||||
toastr.success("{% trans "Copy success" %}")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleProgressBar() {
|
|
||||||
var now = new Date().getTime() / 1000;
|
|
||||||
var offset = now - timestamp;
|
|
||||||
var percent = offset / 3600 * 100;
|
|
||||||
if (percent > 100) {
|
|
||||||
percent = 100
|
|
||||||
}
|
}
|
||||||
progressBarRef.css("width", percent + '%');
|
|
||||||
progressBarRef.attr('aria-valuenow', offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelTicket() {
|
function cancelTicket() {
|
||||||
requestApi({
|
requestApi({
|
||||||
url: url,
|
url: url,
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
flash_message: false
|
flash_message: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelCloseConfirm() {
|
function cancelCloseConfirm() {
|
||||||
window.onbeforeunload = function() {};
|
window.onbeforeunload = function () {
|
||||||
window.onunload = function(){};
|
};
|
||||||
}
|
window.onunload = function () {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function setCloseConfirm() {
|
function setCloseConfirm() {
|
||||||
window.onbeforeunload = function (e) {
|
window.onbeforeunload = function (e) {
|
||||||
return 'Confirm';
|
return 'Confirm';
|
||||||
};
|
};
|
||||||
window.onunload = function (e) {
|
window.onunload = function (e) {
|
||||||
|
cancelTicket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
interval = setInterval(handleProgressBar, 1000);
|
||||||
|
checkInterval = setInterval(doRequestAuth, 5000);
|
||||||
|
doRequestAuth();
|
||||||
|
initClipboard();
|
||||||
|
setCloseConfirm();
|
||||||
|
}).on('click', '.btn-refresh', function () {
|
||||||
|
cancelCloseConfirm();
|
||||||
|
window.location.reload();
|
||||||
|
}).on('click', '.btn-return', function () {
|
||||||
cancelTicket();
|
cancelTicket();
|
||||||
}
|
cancelCloseConfirm();
|
||||||
}
|
clearInterval(interval);
|
||||||
|
clearInterval(checkInterval);
|
||||||
$(document).ready(function () {
|
window.location = "{% url 'authentication:logout' %}"
|
||||||
interval = setInterval(handleProgressBar, 1000);
|
})
|
||||||
checkInterval = setInterval(doRequestAuth, 5000);
|
|
||||||
doRequestAuth();
|
|
||||||
initClipboard();
|
|
||||||
setCloseConfirm();
|
|
||||||
}).on('click', '.btn-refresh', function () {
|
|
||||||
cancelCloseConfirm();
|
|
||||||
window.location.reload();
|
|
||||||
}).on('click', '.btn-return', function () {
|
|
||||||
cancelTicket();
|
|
||||||
cancelCloseConfirm();
|
|
||||||
clearInterval(interval);
|
|
||||||
clearInterval(checkInterval);
|
|
||||||
window.location = "{% url 'authentication:logout' %}"
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue