add audit policy, not completed yet.

pull/105/head
Apex Liu 2017-12-19 02:29:35 +08:00
parent 0171e54acb
commit 940bc682e9
9 changed files with 4061 additions and 27 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,683 @@
"use strict";
$app.on_init = function (cb_stack) {
$app.dom = {
btn_refresh_policy: $('#btn-refresh-policy'),
btn_create_policy: $('#btn-create-policy'),
select_all_policy: $('#table-auz-select-all'),
btn_lock: $('#btn-lock'),
btn_unlock: $('#btn-unlock'),
btn_remove: $('#btn-remove')
};
$app.drag = {
dragging: false,
drag_row_id: '0',
hover_row_id: '0',
drag_index: -1,
hover_index: -1,
insert_before: true, // 是插入到拖放目标之前还是之后
items: [],
dom: {}
};
$('#btn-rebuild').click(function () {
$app.on_rebuild();
});
$(document).mousemove(function (e) {
$app.on_dragging(e);
}).mouseup(function (e) {
$app.on_drag_end(e);
});
cb_stack
.add($app.create_controls)
.add($app.load_role_list);
cb_stack.exec();
};
$app.on_rebuild = function () {
$tp.ajax_post_json('/audit/build-auz-map', {},
function (ret) {
if (ret.code === TPE_OK) {
$tp.notify_success('重建授权映射成功!');
} else {
$tp.notify_error('重建授权映射成功失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,重建授权映射成功失败!');
}
);
};
//===================================
// 创建页面控件对象
//===================================
$app.create_controls = function (cb_stack) {
//-------------------------------
// 资产列表表格
//-------------------------------
var table_policy_options = {
dom_id: 'table-policy',
data_source: {
type: 'ajax-post',
url: '/audit/get-policies'
},
column_default: {sort: false, align: 'left'},
columns: [
{
//title: '<a href="javascript:;" data-reset-filter><i class="fa fa-rotate-left fa-fw"></i></a>',
title: '',
key: 'chkbox',
sort: false,
width: 36,
align: 'center',
render: 'make_check_box',
fields: {id: 'id'}
},
{
title: '顺序',
key: 'rank',
// sort: true,
align: 'center',
width: 60,
// header_render: 'filter_search',
render: 'rank',
fields: {rank: 'rank'}
},
{
title: '授权策略',
key: 'name',
// sort: true,
// header_render: 'filter_search',
render: 'policy_info',
fields: {id: 'id', name: 'name', desc: 'desc'}
},
{
title: "状态",
key: "state",
// sort: true,
width: 90,
align: 'center',
//header_render: 'filter_state',
render: 'state',
fields: {state: 'state'}
},
{
title: '',
key: 'action',
// sort: false,
align: 'center',
width: 80,
render: 'make_action_btn',
fields: {id: 'id', state: 'state'}
}
],
// 重载回调函数
on_header_created: $app.on_table_policy_header_created,
on_render_created: $app.on_table_policy_render_created,
on_cell_created: $app.on_table_policy_cell_created
};
$app.table_policy = $tp.create_table(table_policy_options);
cb_stack
.add($app.table_policy.load_data)
.add($app.table_policy.init);
//-------------------------------
// 用户列表相关过滤器
//-------------------------------
$tp.create_table_header_filter_search($app.table_policy, {
name: 'search',
place_holder: '搜索:授权策略名称/描述/等等...'
});
$tp.create_table_header_filter_state($app.table_policy, 'state', $app.obj_states, [TP_STATE_LOCKED]);
// 从cookie中读取用户分页限制的选择
$tp.create_table_paging($app.table_policy, 'table-auz-paging',
{
per_page: Cookies.get($app.page_id('ops_auz') + '_per_page'),
on_per_page_changed: function (per_page) {
Cookies.set($app.page_id('ops_auz') + '_per_page', per_page, {expires: 365});
}
});
$tp.create_table_pagination($app.table_policy, 'table-auz-pagination');
//-------------------------------
// 对话框
//-------------------------------
$app.dlg_edit_policy = $app.create_dlg_edit_policy();
cb_stack.add($app.dlg_edit_policy.init);
//-------------------------------
// 页面控件事件绑定
//-------------------------------
$app.dom.btn_create_policy.click(function () {
// $app.dom.dlg_edit_user.modal();
$app.dlg_edit_policy.show_add();
});
$app.dom.btn_refresh_policy.click(function () {
$app.table_policy.load_data();
});
$app.dom.select_all_policy.click(function () {
var _objects = $('#' + $app.table_policy.dom_id + ' tbody').find('[data-check-box]');
if ($(this).is(':checked')) {
$.each(_objects, function (i, _obj) {
$(_obj).prop('checked', true);
});
} else {
$.each(_objects, function (i, _obj) {
$(_obj).prop('checked', false);
});
}
});
$app.dom.btn_lock.click($app.on_btn_lock_click);
$app.dom.btn_unlock.click($app.on_btn_unlock_click);
$app.dom.btn_remove.click($app.on_btn_remove_click);
cb_stack.exec();
};
$app.on_table_policy_cell_created = function (tbl, row_id, col_key, cell_obj) {
if (col_key === 'chkbox') {
cell_obj.find('[data-check-box]').click(function () {
$app.check_host_all_selected();
});
} else if (col_key === 'rank') {
cell_obj.find('.reorder').mousedown(function (e) {
$app.on_drag_begin(e, row_id);
});
} else if (col_key === 'action') {
// 绑定系统选择框事件
cell_obj.find('[data-action]').click(function () {
var action = $(this).attr('data-action');
if (action === 'edit') {
$app.dlg_edit_policy.show_edit(row_id);
// } else if (action === 'account') {
// $app.dlg_accounts.show(row_id);
}
});
} else if (col_key === 'name') {
cell_obj.find('[data-action="edit-policy"]').click(function () {
$app.dlg_accounts.show(row_id);
});
}
};
$app.on_drag_begin = function (e, row_id) {
$(document).bind('selectstart', function () {
return false;
});
$app.drag = {
dragging: false,
drag_row_id: '0',
hover_row_id: '0',
drag_index: -1,
hover_index: -1,
items: [],
dom: {}
};
$app.drag.drag_row_id = row_id;
var body = $('body');
// create a drag-div
var policy = $app.table_policy.get_row(row_id);
body.after($('<div id="tp-drag-move-box" style="display:none;position:absolute;font-size:13px;cursor:move;opacity:0.7;padding:5px;background:#999;border:1px solid #666;"><i class="fa fa-reorder fa-fw"></i> ' + policy.rank + ' ' + policy.name + '</div>'));
$app.drag.dom.move_box = $('#tp-drag-move-box');
$app.drag.move_box_height = $app.drag.dom.move_box.height();
$app.drag.dom.move_box.css({left: e.pageX - 5, top: e.pageY - $app.drag.move_box_height / 2}).show();
// create a location-pointer
body.after($('<div id="tp-drag-insert" style="display:none;position:absolute;color:#97d262"><i class="fa fa-chevron-right fa-fw"></i></div>'));
$app.drag.dom.loc_insert = $('#tp-drag-insert');
var tr_item = $('tr[data-row-id]');
for (var i = 0; i < tr_item.length; ++i) {
var item = $(tr_item[i]);
var _row_id = item.attr('data-row-id');
if (_row_id === row_id)
$app.drag.drag_index = i;
$app.drag.items.push([item.offset().top, item.offset().top + item.height(), _row_id]);
}
$app.drag.dragging = true;
};
$app.on_dragging = function (e) {
if (!$app.drag.dragging)
return;
$app.drag.dom.move_box.css({left: e.pageX - 5, top: e.pageY - $app.drag.move_box_height / 2});
// check which <tr> we are moving on.
$app.drag.hover_row_id = null;
for (var i = 0; i < $app.drag.items.length; ++i) {
if (e.pageY < $app.drag.items[i][0])
continue;
if (e.pageY > $app.drag.items[i][1])
continue;
if ($app.drag_row_id === $app.drag.items[i][2])
continue;
if ($app.drag.drag_row_id === $app.drag.items[i][2])
break;
var idx = -1;
if (e.pageY <= $app.drag.items[i][0] + ($app.drag.items[i][1] - $app.drag.items[i][0]) / 2) {
$app.drag.insert_before = true;
idx = i - 1;
}
else {
$app.drag.insert_before = false;
idx = i + 1;
}
if (idx === $app.drag.drag_index)
break;
$app.drag.hover_row_id = $app.drag.items[i][2];
break;
}
if ($app.drag.hover_row_id === null) {
$app.drag.dom.loc_insert.hide();
return;
} else {
$app.drag.dom.loc_insert.show();
}
var hover_obj = $('tr[data-row-id="' + $app.drag.hover_row_id + '"]');
var x = hover_obj.offset().left - $app.drag.dom.loc_insert.width();
var y = 0;
if ($app.drag.insert_before)
y = hover_obj.offset().top - $app.drag.dom.loc_insert.height() / 2;
else
y = hover_obj.offset().top + hover_obj.height() - $app.drag.dom.loc_insert.height() / 2;
$app.drag.dom.loc_insert.css({left: x, top: y});
};
$app.on_drag_end = function (e) {
if (!$app.drag.dragging)
return;
$app.drag.dom.move_box.remove();
$app.drag.dom.loc_insert.remove();
$(document).unbind('selectstart');
$app.drag.dragging = false;
if ($app.drag.hover_row_id === null)
return;
var policy_drag = $app.table_policy.get_row($app.drag.drag_row_id);
var policy_target = $app.table_policy.get_row($app.drag.hover_row_id);
var direct = -1; // 移动方向,-1=向前移动1=向后移动
var start_rank = 0, end_rank = 0; // 导致rank变化的范围 start_rank <= rank <= end_rank
var new_rank = 0;//policy_target.rank; // 被移动的条目的新rank
if (policy_drag.rank > policy_target.rank) {
// 这是向前移动
direct = 1;
end_rank = policy_drag.rank - 1;
if ($app.drag.insert_before) {
new_rank = policy_target.rank;
start_rank = policy_target.rank;
}
else {
new_rank = policy_target.rank + 1;
start_rank = policy_target.rank + 1;
}
} else {
// 这是向后移动
direct = -1;
start_rank = policy_drag.rank + 1;
if ($app.drag.insert_before) {
new_rank = policy_target.rank - 1;
end_rank = policy_target.rank - 1;
}
else {
new_rank = policy_target.rank;
end_rank = policy_target.rank;
}
}
$tp.ajax_post_json('/audit/policy/rank-reorder', {
pid: policy_drag.id,
new_rank: new_rank,
start_rank: start_rank,
end_rank: end_rank,
direct: direct
},
function (ret) {
if (ret.code === TPE_OK) {
$tp.notify_success('授权策略顺序调整成功!');
$app.table_policy.load_data();
} else {
$tp.notify_error('授权策略顺序调整失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,授权策略顺序调整失败!');
}
);
};
$app.check_host_all_selected = function (cb_stack) {
var _all_checked = true;
var _objs = $('#' + $app.table_policy.dom_id + ' tbody').find('[data-check-box]');
if (_objs.length === 0) {
_all_checked = false;
} else {
$.each(_objs, function (i, _obj) {
if (!$(_obj).is(':checked')) {
_all_checked = false;
return false;
}
});
}
if (_all_checked) {
$app.dom.select_all_policy.prop('checked', true);
} else {
$app.dom.select_all_policy.prop('checked', false);
}
if (cb_stack)
cb_stack.exec();
};
$app.on_table_policy_render_created = function (render) {
// render.filter_search = function (header, title, col) {
// var _ret = ['<div class="tp-table-filter tp-table-filter-input">'];
// _ret.push('<div class="tp-table-filter-inner">');
// _ret.push('<div class="search-title">' + title + '</div>');
//
// // 表格内嵌过滤器的DOM实体在这时生成
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('search');
// _ret.push(filter_ctrl.render());
//
// _ret.push('</div></div>');
//
// return _ret.join('');
// };
//
// render.filter_state = function (header, title, col) {
// var _ret = ['<div class="tp-table-filter tp-table-filter-' + col.cell_align + '">'];
// _ret.push('<div class="tp-table-filter-inner">');
// _ret.push('<div class="search-title">' + title + '</div>');
//
// // 表格内嵌过滤器的DOM实体在这时生成
// var filter_ctrl = header._table_ctrl.get_filter_ctrl('state');
// _ret.push(filter_ctrl.render());
//
// _ret.push('</div></div>');
//
// return _ret.join('');
// };
render.rank = function (row_id, fields) {
return '<span class="reorder"><i class="fa fa-reorder fa-fw"></i> ' + fields.rank + '</span>'
};
render.make_check_box = function (row_id, fields) {
return '<span><input type="checkbox" data-check-box="' + fields.id + '" data-row-id="' + row_id + '"></span>';
};
render.policy_info = function (row_id, fields) {
return '<a href="/audit/policy/detail/' + fields.id + '">' + fields.name + '</a><span class="policy-desc">' + fields.desc + '</span>'
};
render.state = function (row_id, fields) {
var _style, _state;
for (var i = 0; i < $app.obj_states.length; ++i) {
if ($app.obj_states[i].id === fields.state) {
_style = $app.obj_states[i].style;
_state = $app.obj_states[i].name;
break;
}
}
if (i === $app.obj_states.length) {
_style = 'info';
_state = '<i class="fa fa-question-circle"></i> 未知';
}
return '<span class="label label-sm label-' + _style + '">' + _state + '</span>'
};
render.make_action_btn = function (row_id, fields) {
var ret = [];
ret.push('<div class="btn-group btn-group-sm" role="group">');
ret.push('<btn class="btn btn-primary" data-action="edit"><i class="fa fa-edit"></i> 编辑</btn>');
// ret.push('<btn class="btn btn-info" data-btn-disable="' + fields.id + '"><i class="fa fa-trash-o"></i> 禁用</btn>');
// ret.push('<btn class="btn btn-danger" data-btn-remove="' + fields.id + '"><i class="fa fa-trash-o"></i> 删除</btn>');
ret.push('</div>');
return ret.join('');
};
};
$app.on_table_policy_header_created = function (header) {
// $('#' + header._table_ctrl.dom_id + ' a[data-reset-filter]').click(function () {
// CALLBACK_STACK.create()
// .add(header._table_ctrl.load_data)
// .add(header._table_ctrl.reset_filters)
// .exec();
// });
// 表格内嵌过滤器的事件绑定在这时进行(也可以延期到整个表格创建完成时进行)
// header._table_ctrl.get_filter_ctrl('search').on_created();
// header._table_ctrl.get_filter_ctrl('state').on_created();
};
$app.get_selected_policy = function (tbl) {
var users = [];
var _objs = $('#' + $app.table_policy.dom_id + ' tbody tr td input[data-check-box]');
$.each(_objs, function (i, _obj) {
if ($(_obj).is(':checked')) {
var _row_data = tbl.get_row(_obj);
// _all_checked = false;
users.push(_row_data.id);
}
});
return users;
};
$app.on_btn_lock_click = function () {
var items = $app.get_selected_policy($app.table_policy);
if (items.length === 0) {
$tp.notify_error('请选择要禁用的授权策略!');
return;
}
$tp.ajax_post_json('/audit/policies/update', {
action: 'lock',
policy_ids: items
},
function (ret) {
if (ret.code === TPE_OK) {
CALLBACK_STACK.create()
.add($app.check_host_all_selected)
.add($app.table_policy.load_data)
.exec();
$tp.notify_success('禁用授权策略操作成功!');
} else {
$tp.notify_error('禁用授权策略操作失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,禁用授权策略操作失败!');
}
);
};
$app.on_btn_unlock_click = function () {
var items = $app.get_selected_policy($app.table_policy);
if (items.length === 0) {
$tp.notify_error('请选择要解禁的授权策略!');
return;
}
$tp.ajax_post_json('/audit/policies/update', {
action: 'unlock',
policy_ids: items
},
function (ret) {
if (ret.code === TPE_OK) {
CALLBACK_STACK.create()
.add($app.check_host_all_selected)
.add($app.table_policy.load_data)
.exec();
$tp.notify_success('解禁授权策略操作成功!');
} else {
$tp.notify_error('解禁授权策略操作失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,解禁授权策略操作失败!');
}
);
};
$app.on_btn_remove_click = function () {
var items = $app.get_selected_policy($app.table_policy);
if (items.length === 0) {
$tp.notify_error('请选择要删除的授权策略!');
return;
}
var _fn_sure = function (cb_stack, cb_args) {
$tp.ajax_post_json('/audit/policies/update', {
action: 'remove',
policy_ids: items
},
function (ret) {
if (ret.code === TPE_OK) {
cb_stack.add($app.check_host_all_selected);
cb_stack.add($app.table_policy.load_data);
$tp.notify_success('删除授权策略操作成功!');
} else {
$tp.notify_error('删除授权策略操作失败:' + tp_error_msg(ret.code, ret.message));
}
cb_stack.exec();
},
function () {
$tp.notify_error('网络故障,删除授权策略操作失败!');
cb_stack.exec();
}
);
};
var cb_stack = CALLBACK_STACK.create();
$tp.dlg_confirm(cb_stack, {
msg: '<div class="alert alert-danger"><p><strong>注意:删除操作不可恢复!!</strong></p></div><p>如果您希望临时禁止指定的授权策略,可将其“禁用”!</p><p>您确定要移除选定的' + items.length + '个授权策略吗?</p>',
fn_yes: _fn_sure
});
};
$app.create_dlg_edit_policy = function () {
var dlg = {};
dlg.dom_id = 'dlg-edit-policy';
dlg.field_id = -1;
dlg.field_name = '';
dlg.field_desc = '';
dlg.dom = {
dialog: $('#' + dlg.dom_id),
dlg_title: $('#' + dlg.dom_id + ' [data-field="dlg-title"]'),
edit_name: $('#edit-name'),
edit_desc: $('#edit-desc'),
btn_save: $('#btn-edit-policy-save')
};
dlg.init = function (cb_stack) {
dlg.dom.btn_save.click(dlg.on_save);
cb_stack.exec();
};
dlg.init_fields = function (policy) {
dlg.field_id = -1;
dlg.field_os_type = -1;
if (_.isUndefined(policy)) {
dlg.dom.dlg_title.html('创建授权策略');
dlg.dom.edit_name.val('');
dlg.dom.edit_desc.val('');
} else {
dlg.field_id = policy.id;
dlg.dom.dlg_title.html('编辑授权策略:');
dlg.dom.edit_name.val(policy.name);
dlg.dom.edit_desc.val(policy.desc);
}
};
dlg.show_add = function () {
dlg.init_fields();
dlg.dom.dialog.modal({backdrop: 'static'});
};
dlg.show_edit = function (row_id) {
var host = $app.table_policy.get_row(row_id);
dlg.init_fields(host);
dlg.dom.dialog.modal({backdrop: 'static'});
};
dlg.check_input = function () {
dlg.field_name = dlg.dom.edit_name.val();
dlg.field_desc = dlg.dom.edit_desc.val();
if (dlg.field_name.length === 0) {
dlg.dom.edit_name.focus();
$tp.notify_error('请设定授权策略名称!');
return false;
}
return true;
};
dlg.on_save = function () {
if (!dlg.check_input())
return;
var action = (dlg.field_id === -1) ? '添加' : '更新';
// 如果id为-1表示创建否则表示更新
$tp.ajax_post_json('/audit/policy/update', {
id: dlg.field_id,
name: dlg.field_name,
desc: dlg.field_desc
},
function (ret) {
if (ret.code === TPE_OK) {
$tp.notify_success('授权策略' + action + '成功!');
$app.table_policy.load_data();
dlg.dom.dialog.modal('hide');
} else {
$tp.notify_error('授权策略' + action + '失败:' + tp_error_msg(ret.code, ret.message));
}
},
function () {
$tp.notify_error('网络故障,授权策略' + action + '失败!');
}
);
};
return dlg;
};

View File

@ -0,0 +1,369 @@
<%!
page_icon_class_ = 'fa fa-server fa-fw'
page_title_ = ['审计', '审计授权']
page_id_ = ['audit', 'auz']
%>
<%inherit file="../page_base.mako"/>
<%block name="extend_js_file">
<script type="text/javascript" src="${ static_url('js/audit/auz-info.js') }"></script>
</%block>
<%block name="breadcrumb">
<ol class="breadcrumb">
%for i in range(len(self.attr.page_title_)):
%if i == 0:
<li><i class="${self.attr.page_icon_class_}"></i> ${self.attr.page_title_[i]}</li>
%else:
<li>${self.attr.page_title_[i]}</li>
%endif
%endfor
<li><strong id="group-name-breadcrumb"></strong><span data-field="policy-name"></span></li>
</ol>
</%block>
<%block name="embed_js">
<script type="text/javascript">
$app.add_options(${page_param});
if ($app.options.policy_id !== 0) {
$('[data-field="policy-name"]').text($app.options.policy_name);
$('[data-field="policy-desc"]').text($app.options.policy_desc);
} else {
## $tp.notify_error('授权策略不存在!');
$tp.disable_dom('#work-area', '授权策略不存在!');
}
</script>
</%block>
<%block name="embed_css">
<style type="text/css">
.nav-tabs-title {
padding: 0 0 10px 0;
font-size: 1.2rem;
}
.nav-tabs-title .title {
display: inline-block;
}
.nav-tabs-title .sub-title {
display: inline-block;
color: #878787;
padding-left: 15px;
font-size: 1rem;
}
#area-auditor, #area-auditee {
border: 1px solid #d6d6d6;
}
.area-title {
padding: 5px;
background-color: #f4f4f4;
}
.area-title .name {
font-size: 110%;
}
.area-title .desc {
color: #858585;
}
.field-name {
padding-right: 20px;
}
.field-desc {
display: inline-block;
color: #878787;
}
</style>
</%block>
## Begin Main Body.
<div class="page-content-inner">
<div class="box" id="work-area">
<div class="nav-tabs-title">
<div class="title">授权策略:<span data-field="policy-name"></span></div>
<div class="sub-title" data-field="policy-desc"></div>
</div>
<div class="row">
<div class="col-md-6">
<div id="area-auditor">
<div class="area-title"><span class="name">审计操作者</span><span class="desc">(执行审计操作的用户)</span></div>
<div style="padding:5px;">
<div class="table-extend-area">
<div class="table-extend-cell">
<div class="btn-group btn-group-sm">
<btn class="btn btn-default" id="btn-refresh-auditor"><i class="fa fa-rotate-right"></i> 刷新列表</btn>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<div class="btn-group btn-group-sm">
<btn class="btn btn-success" id="btn-add-auditor-user"><i class="fa fa-plus"></i> 添加用户</btn>
<btn class="btn btn-primary" id="btn-add-auditor-user-group"><i class="fa fa-plus-circle"></i> 添加用户组</btn>
</div>
</div>
</div>
<table id="table-auditor" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input id="table-auditor-select-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
<button id="btn-remove-auditor" type="button" class="btn btn-default"><i class="fa fa-times-circle fa-fw"></i> 删除</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-auditor-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-auditor-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div id="area-auditee">
<div class="area-title"><span class="name">被审计者</span><span class="desc">(被审计的用户或主机)</span></div>
<div style="padding:5px;">
<div class="table-extend-area">
<div class="table-extend-cell">
<div class="btn-group btn-group-sm">
<btn class="btn btn-default" id="btn-refresh-auditee"><i class="fa fa-rotate-right"></i> 刷新列表</btn>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<div class="btn-group btn-group-sm">
<btn class="btn btn-success" id="btn-add-auditee-user"><i class="fa fa-plus"></i> 添加用户</btn>
<btn class="btn btn-primary" id="btn-add-auditee-user-group"><i class="fa fa-plus-circle"></i> 添加用户组</btn>
<btn class="btn btn-success" id="btn-add-auditee-host"><i class="fa fa-plus"></i> 添加主机</btn>
<btn class="btn btn-primary" id="btn-add-auditee-host-group"><i class="fa fa-plus-circle"></i> 添加主机组</btn>
</div>
</div>
</div>
<table id="table-auditee" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input id="table-auditee-select-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
<button id="btn-remove-auditee" type="button" class="btn btn-default"><i class="fa fa-times-circle fa-fw"></i> 删除</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-auditee-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-auditee-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="box">
<p>说明:</p>
<ul class="help-list">
<li>授权对象表格表示左侧“审计操作者”可以访问右侧“被审计者”相关的运维操作记录。</li>
<li>按“组”进行授权,则后续加入对应组的用户或主机均自动获得本策略的授权。</li>
</ul>
</div>
</div>
<%block name="extend_content">
<div class="modal fade" id="dlg-sel-user" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times-circle fa-fw"></i></button>
<h3 data-field="dlg-title" class="modal-title">选择用户</h3>
</div>
<div class="modal-body">
<table id="table-sel-user" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input data-action="sel-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
<button data-action="use-selected" type="button" class="btn btn-primary"><i class="fa fa-edit fa-fw"></i> 添加为授权操作者</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-sel-user-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-sel-user-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="dlg-sel-user-group" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times-circle fa-fw"></i></button>
<h3 data-field="dlg-title" class="modal-title">选择用户组</h3>
</div>
<div class="modal-body">
<table id="table-sel-user-group" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input data-action="sel-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
<button data-action="use-selected" type="button" class="btn btn-primary"><i class="fa fa-edit fa-fw"></i> 添加为授权操作者</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-sel-user-group-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-sel-user-group-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="dlg-sel-host" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times-circle fa-fw"></i></button>
<h3 data-field="dlg-title" class="modal-title">选择主机</h3>
</div>
<div class="modal-body">
<table id="table-sel-host" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input data-action="sel-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
<button data-action="use-selected" type="button" class="btn btn-primary"><i class="fa fa-edit fa-fw"></i> 添加为被授权资产</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-sel-host-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-sel-host-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="dlg-sel-host-group" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times-circle fa-fw"></i></button>
<h3 data-field="dlg-title" class="modal-title">选择主机组</h3>
</div>
<div class="modal-body">
<table id="table-sel-host-group" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input data-action="sel-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
<button data-action="use-selected" type="button" class="btn btn-primary"><i class="fa fa-edit fa-fw"></i> 添加为被授权资产</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-sel-host-group-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-sel-host-group-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 关闭</button>
</div>
</div>
</div>
</div>
</%block>

View File

@ -0,0 +1,134 @@
<%!
page_icon_class_ = 'fa fa-server fa-fw'
page_title_ = ['审计', '审计授权']
page_id_ = ['audit', 'auz']
%>
<%inherit file="../page_base.mako"/>
<%block name="extend_js_file">
<script type="text/javascript" src="${ static_url('js/audit/auz-list.js') }"></script>
</%block>
<%block name="embed_css">
<style>
.policy-desc {
margin-left: 8px;
color: #7f7f7f;
}
</style>
</%block>
## Begin Main Body.
<div class="page-content-inner">
<!-- begin box -->
<div class="box box-nav-tabs">
<!-- Nav tabs -->
<ul class="nav nav-tabs">
<li class="active"><a href="#tab-policy" data-toggle="tab">授权策略</a></li>
<li><a href="#tab-search" data-toggle="tab">快速查找</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" style="padding:15px;" id="tab-policy">
<div class="table-prefix-area">
<div class="table-extend-cell">
<span class="table-name"><i class="fa fa-list fa-fw"></i> 授权策略列表</span>
<button id="btn-refresh-policy" class="btn btn-sm btn-default"><i class="fa fa-rotate-right fa-fw"></i> 刷新列表</button>
<button id="btn-rebuild" class="btn btn-sm btn-danger"><i class="fa fa-flash fa-fw"></i> 重建授权映射</button>
</div>
<div class="table-extend-cell table-extend-cell-right group-actions">
<button id="btn-create-policy" class="btn btn-sm btn-primary"><i class="fa fa-plus-circle fa-fw"></i> 新建授权策略</button>
</div>
</div>
<table id="table-policy" class="table table-striped table-bordered table-hover table-data no-footer dtr-inline"></table>
<div class="table-extend-area">
<div class="table-extend-cell checkbox-select-all"><input id="table-auz-select-all" type="checkbox"/></div>
<div class="table-extend-cell group-actions">
<div class="btn-group" role="group">
## <button id="btn-edit-host" type="button" class="btn btn-default"><i class="fa fa-edit fa-fw"></i> 编辑</button>
<button id="btn-lock" type="button" class="btn btn-default"><i class="fa fa-lock fa-fw"></i> 禁用</button>
<button id="btn-unlock" type="button" class="btn btn-default"><i class="fa fa-unlock fa-fw"></i> 解禁</button>
<button id="btn-remove" type="button" class="btn btn-default"><i class="fa fa-times-circle fa-fw"></i> 删除</button>
</div>
</div>
<div class="table-extend-cell table-item-counter">
<ol id="table-auz-paging"></ol>
</div>
</div>
<div class="table-extend-area">
<div class="table-extend-cell">
<div style="text-align:right;">
<nav>
<ul id="table-auz-pagination" class="pagination"></ul>
</nav>
</div>
</div>
</div>
</div>
<div class="tab-pane" style="padding:15px;" id="tab-search">
<div class="alert alert-danger">快速查找功能尚未实现</div>
</div>
</div>
</div>
<!-- end of box -->
<div class="box">
<p>说明:</p>
<ul class="help-list">
<li><span class="error">编辑了授权策略或调整策略顺序之后,请点击“重建授权映射”来使之生效!</span>正式版本将会改进为自动进行重建。</li>
<li>上下拖动“顺序”栏中的 <i class="fa fa-reorder fa-fw"></i> 可以调节策略的检查顺序。</li>
<li>可以在“快速查找”中快速定位用户或主机的授权关系。</li>
</ul>
</div>
</div>
<%block name="extend_content">
<div class="modal fade" id="dlg-edit-policy" tabindex="-1">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fa fa-times-circle fa-fw"></i></button>
<h3 data-field="dlg-title" class="modal-title"></h3>
</div>
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group form-group-sm">
<label for="edit-name" class="col-sm-2 control-label require">策略名称:</label>
<div class="col-sm-10">
<input id="edit-name" type="text" class="form-control" placeholder=""/>
</div>
</div>
<div class="form-group form-group-sm">
<label for="edit-desc" class="col-sm-2 control-label">策略描述:</label>
<div class="col-sm-10">
<input id="edit-desc" type="text" class="form-control"/>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-primary" id="btn-edit-policy-save"><i class="fa fa-check fa-fw"></i> 确定</button>
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal"><i class="fa fa-close fa-fw"></i> 取消</button>
</div>
</div>
</div>
</div>
</%block>

View File

@ -295,7 +295,7 @@
<li>授权对象表格表示左侧“授权操作者”可以访问右侧“被授权资产”。</li> <li>授权对象表格表示左侧“授权操作者”可以访问右侧“被授权资产”。</li>
<li>修改授权对象和连接控制选项不会影响当前已经建立的连接。</li> <li>修改授权对象和连接控制选项不会影响当前已经建立的连接。</li>
<li>如被授权资产为主机/主机组,则允许用户以对应主机相关的任意账号进行连接。</li> <li>如被授权资产为主机/主机组,则允许用户以对应主机相关的任意账号进行连接。</li>
<li>按“组”进行授权,则后续加入对应组的用户、账号或主机均自动获得本授权策略的授权。</li> <li>按“组”进行授权,则后续加入对应组的用户、账号或主机均自动获得本策略的授权。</li>
</ul> </ul>
</div> </div>

View File

@ -561,30 +561,10 @@ class DatabaseInit:
f.append('`name` varchar(128) DEFAULT ""') f.append('`name` varchar(128) DEFAULT ""')
# desc: 策略描述 # desc: 策略描述
f.append('`desc` varchar(255) DEFAULT ""') f.append('`desc` varchar(255) DEFAULT ""')
# start_time: 策略有效期起始时间(为0则忽略)
f.append('`start_time` int(11) DEFAULT 0')
# end_time: 策略有效期结束时间(为0则忽略)
f.append('`end_time` int(11) DEFAULT 0')
# state: 状态1=正常2=禁用 # state: 状态1=正常2=禁用
f.append('`state` int(3) DEFAULT 1') f.append('`state` int(3) DEFAULT 1')
# limit_ip: 是否启用来源限制0=不限制1=白名单2=黑名单(尚未实现)
f.append('`limit_ip` int(3) DEFAULT 0')
# ip_list: 限制IP列表白名单或者黑名单
f.append('`ip_list` TEXT')
# limit_time: 是否启用限时连接0=不限制1=限制(尚未实现)
f.append('`limit_time` int(3) DEFAULT 0')
# 每一个weekX表示一天的时间段按位异或表示24个小时的每个小时是否限制连接对应位为0表示不限制允许连接
f.append('`limit_week1` int(11) DEFAULT 0')
f.append('`limit_week2` int(11) DEFAULT 0')
f.append('`limit_week3` int(11) DEFAULT 0')
f.append('`limit_week4` int(11) DEFAULT 0')
f.append('`limit_week5` int(11) DEFAULT 0')
f.append('`limit_week6` int(11) DEFAULT 0')
f.append('`limit_week7` int(11) DEFAULT 0')
# creator_id: 授权者的id0=系统默认创建 # creator_id: 授权者的id0=系统默认创建
f.append('`creator_id` int(11) DEFAULT 0') f.append('`creator_id` int(11) DEFAULT 0')
# create_time: 授权时间 # create_time: 授权时间
@ -605,7 +585,7 @@ class DatabaseInit:
# policy_id: 所属的策略 # policy_id: 所属的策略
f.append('`policy_id` int(11) DEFAULT 0') f.append('`policy_id` int(11) DEFAULT 0')
# type 指明本条记录是授权还是被授权0=授权(用户/用户组1=被授权(资产:主机/主机组) # type 指明本条记录是授权还是被授权0=授权(用户/用户组1=被授权(资产:用户/用户组/主机/主机组)
f.append('`type` int(11) DEFAULT 0') f.append('`type` int(11) DEFAULT 0')
# rtype : 外链类型 # rtype : 外链类型

View File

@ -172,6 +172,16 @@ controllers = [
(r'/audit/record', audit.RecordHandler), (r'/audit/record', audit.RecordHandler),
# - [json] 审计页面(录像列表) # - [json] 审计页面(录像列表)
(r'/audit/get-records', audit.DoGetRecordsHandler), (r'/audit/get-records', audit.DoGetRecordsHandler),
# - 某个策略的管理页面
(r'/audit/policy/detail/(.*)', audit.PolicyDetailHandler),
# - [json] 获取策略列表
(r'/audit/get-policies', audit.DoGetPoliciesHandler),
# - [json] 添加/更新策略
(r'/audit/policy/update', audit.DoUpdatePolicyHandler),
# - [json] 禁用/解禁/删除策略
(r'/audit/policies/update', audit.DoUpdatePoliciesHandler),
# - [json] 调整顺序rank
(r'/audit/policy/rank-reorder', audit.DoRankReorderHandler),
# #
# - ssh录像回放页面 # - ssh录像回放页面
(r'/audit/replay/(.*)/(.*)', audit.ReplayHandler), (r'/audit/replay/(.*)/(.*)', audit.ReplayHandler),

View File

@ -1,18 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# import ctypes
import json import json
import os import os
# import platform
import shutil import shutil
from app.const import * from app.const import *
from app.base.configs import tp_cfg from app.base.configs import tp_cfg
from app.base.logger import * from app.base.logger import *
from app.model import audit
from app.model import record from app.model import record
# from app.model import user
from app.base.controller import TPBaseHandler, TPBaseJsonHandler from app.base.controller import TPBaseHandler, TPBaseJsonHandler
# import tornado.web
import tornado.gen import tornado.gen
@ -31,7 +28,195 @@ class AuzListHandler(TPBaseHandler):
ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ) ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ)
if ret != TPE_OK: if ret != TPE_OK:
return return
self.show_error_page(TPE_NOT_IMPLEMENT) self.render('audit/auz-list.mako')
class PolicyDetailHandler(TPBaseHandler):
def get(self, pid):
ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ)
if ret != TPE_OK:
return
pid = int(pid)
err, policy = audit.get_by_id(pid)
if err == TPE_OK:
param = {
'policy_id': pid,
'policy_name': policy['name'],
'policy_desc': policy['desc']
}
else:
param = {
'policy_id': 0,
'policy_name': '',
'policy_desc': ''
}
self.render('audit/auz-info.mako', page_param=json.dumps(param))
class DoGetPoliciesHandler(TPBaseJsonHandler):
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
sql_filter = {}
sql_order = dict()
sql_order['name'] = 'rank'
sql_order['asc'] = True
sql_limit = dict()
sql_limit['page_index'] = 0
sql_limit['per_page'] = 25
try:
tmp = list()
_filter = args['filter']
for i in _filter:
if i == 'state' and _filter[i] == 0:
tmp.append(i)
continue
if i == 'search':
if len(_filter[i].strip()) == 0:
tmp.append(i)
for i in tmp:
del _filter[i]
sql_filter.update(_filter)
_limit = args['limit']
if _limit['page_index'] < 0:
_limit['page_index'] = 0
if _limit['per_page'] < 10:
_limit['per_page'] = 10
if _limit['per_page'] > 100:
_limit['per_page'] = 100
sql_limit.update(_limit)
# _order = args['order']
# if _order is not None:
# sql_order['name'] = _order['k']
# sql_order['asc'] = _order['v']
except:
return self.write_json(TPE_PARAM)
err, total, page_index, row_data = audit.get_policies(sql_filter, sql_order, sql_limit)
ret = dict()
ret['page_index'] = page_index
ret['total'] = total
ret['data'] = row_data
self.write_json(err, data=ret)
class DoUpdatePolicyHandler(TPBaseJsonHandler):
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
args['id'] = int(args['id'])
args['name'] = args['name'].strip()
args['desc'] = args['desc'].strip()
except:
log.e('\n')
return self.write_json(TPE_PARAM)
if len(args['name']) == 0:
return self.write_json(TPE_PARAM)
if args['id'] == -1:
err, info = audit.create_policy(self, args)
else:
err = audit.update_policy(self, args)
info = {}
self.write_json(err, data=info)
class DoUpdatePoliciesHandler(TPBaseJsonHandler):
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
action = args['action']
p_ids = args['policy_ids']
except:
log.e('\n')
return self.write_json(TPE_PARAM)
if action == 'lock':
err = audit.update_policies_state(self, p_ids, TP_STATE_DISABLED)
return self.write_json(err)
elif action == 'unlock':
err = audit.update_policies_state(self, p_ids, TP_STATE_NORMAL)
return self.write_json(err)
elif action == 'remove':
err = audit.remove_policies(self, p_ids)
return self.write_json(err)
else:
return self.write_json(TPE_PARAM)
class DoRankReorderHandler(TPBaseJsonHandler):
def post(self):
ret = self.check_privilege(TP_PRIVILEGE_AUDIT_AUZ)
if ret != TPE_OK:
return
args = self.get_argument('args', None)
if args is None:
return self.write_json(TPE_PARAM)
try:
args = json.loads(args)
except:
return self.write_json(TPE_JSON_FORMAT)
try:
pid = int(args['pid'])
new_rank = int(args['new_rank'])
start_rank = int(args['start_rank'])
end_rank = int(args['end_rank'])
direct = int(args['direct'])
except:
log.e('\n')
return self.write_json(TPE_PARAM)
if direct == -1:
direct = '-1'
elif direct == 1:
direct = '+1'
else:
return self.write_json(TPE_PARAM)
err = audit.rank_reorder(self, pid, new_rank, start_rank, end_rank, direct)
self.write_json(err)
class RecordHandler(TPBaseHandler): class RecordHandler(TPBaseHandler):

View File

@ -0,0 +1,775 @@
# -*- coding: utf-8 -*-
from app.const import *
from app.base.logger import log
from app.base.db import get_db, SQL
from app.model import syslog
from app.base.utils import AttrDict, tp_timestamp_utc_now
def get_by_id(pid):
s = SQL(get_db())
s.select_from('audit_policy', ['id', 'name', 'desc'], alt_name='p')
s.where('p.id={}'.format(pid))
err = s.query()
if err != TPE_OK:
return err, {}
if len(s.recorder) == 0:
return TPE_NOT_EXISTS, {}
return TPE_OK, s.recorder[0]
def get_policies(sql_filter, sql_order, sql_limit):
dbtp = get_db().table_prefix
s = SQL(get_db())
s.select_from('audit_policy', ['id', 'rank', 'name', 'desc', 'state'], alt_name='p')
str_where = ''
_where = list()
if len(sql_filter) > 0:
for k in sql_filter:
if k == 'search':
_where.append('(p.name LIKE "%{filter}%" OR p.desc LIKE "%{filter}%")'.format(filter=sql_filter[k]))
if k == 'state':
_where.append('p.state={}'.format(sql_filter[k]))
else:
log.e('unknown filter field: {}\n'.format(k))
return TPE_PARAM, s.total_count, 0, s.recorder
if len(_where) > 0:
str_where = '( {} )'.format(' AND '.join(_where))
s.where(str_where)
s.order_by('p.rank', True)
if len(sql_limit) > 0:
s.limit(sql_limit['page_index'], sql_limit['per_page'])
err = s.query()
return err, s.total_count, s.page_index, s.recorder
def create_policy(handler, args):
"""
创建一个授权策略
"""
db = get_db()
_time_now = tp_timestamp_utc_now()
# 1. 判断此账号是否已经存在了
s = SQL(db)
err = s.reset().select_from('audit_policy', ['id']).where('audit_policy.name="{}"'.format(args['name'])).query()
if err != TPE_OK:
return err, 0
if len(s.recorder) > 0:
return TPE_EXISTS, 0
# 2. get total count
sql = 'SELECT COUNT(*) FROM {}audit_policy'.format(db.table_prefix)
db_ret = db.query(sql)
if not db_ret or len(db_ret) == 0:
return TPE_DATABASE, 0
rank = db_ret[0][0] + 1
sql = 'INSERT INTO `{}audit_policy` (`rank`, `name`, `desc`, `creator_id`, `create_time`) VALUES ' \
'({rank}, "{name}", "{desc}", {creator_id}, {create_time});' \
''.format(db.table_prefix,
rank=rank, name=args['name'], desc=args['desc'],
creator_id=handler.get_current_user()['id'],
create_time=_time_now)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE, 0
_id = db.last_insert_id()
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "创建审计授权策略:{}".format(args['name']))
return TPE_OK, _id
def update_policy(handler, args):
db = get_db()
# 1. 判断此账号是否已经存在
s = SQL(db)
err = s.reset().select_from('audit_policy', ['id']).where('audit_policy.id={}'.format(args['id'])).query()
if err != TPE_OK:
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
sql = 'UPDATE `{}audit_policy` SET `name`="{name}", `desc`="{desc}" WHERE `id`={p_id};' \
''.format(db.table_prefix,
name=args['name'], desc=args['desc'], p_id=args['id']
)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE
return TPE_OK
def update_policies_state(handler, p_ids, state):
db = get_db()
p_ids = ','.join([str(i) for i in p_ids])
sql_list = []
sql = 'UPDATE `{}audit_policy` SET `state`={state} WHERE `id` IN ({p_ids});'.format(db.table_prefix, state=state, p_ids=p_ids)
sql_list.append(sql)
sql = 'UPDATE `{}audit_auz` SET `state`={state} WHERE `policy_id` IN ({p_ids});'.format(db.table_prefix, state=state, p_ids=p_ids)
sql_list.append(sql)
sql = 'UPDATE `{}audit_map` SET `p_state`={state} WHERE `p_id` IN ({p_ids});'.format(db.table_prefix, state=state, p_ids=p_ids)
sql_list.append(sql)
if db.transaction(sql_list):
return TPE_OK
else:
return TPE_DATABASE
def remove_policies(handler, p_ids):
db = get_db()
p_ids = ','.join([str(i) for i in p_ids])
sql_list = []
sql = 'DELETE FROM `{}audit_policy` WHERE `id` IN ({p_ids});'.format(db.table_prefix, p_ids=p_ids)
sql_list.append(sql)
sql = 'DELETE FROM `{}audit_auz` WHERE `policy_id` IN ({p_ids});'.format(db.table_prefix, p_ids=p_ids)
sql_list.append(sql)
sql = 'DELETE FROM `{}audit_map` WHERE `p_id` IN ({p_ids});'.format(db.table_prefix, p_ids=p_ids)
sql_list.append(sql)
if db.transaction(sql_list):
return TPE_OK
else:
return TPE_DATABASE
def add_members(handler, policy_id, policy_type, ref_type, members):
# step 1: select exists rid.
s = SQL(get_db())
s.select_from('audit_auz', ['rid'], alt_name='p')
_where = list()
_where.append('p.policy_id={}'.format(policy_id))
_where.append('p.type={}'.format(policy_type))
_where.append('p.rtype={}'.format(ref_type))
s.where('( {} )'.format(' AND '.join(_where)))
err = s.query()
if err != TPE_OK:
return err
exists_ids = [r['rid'] for r in s.recorder]
operator = handler.get_current_user()
db = get_db()
_time_now = tp_timestamp_utc_now()
sql = []
# for uid in members:
# sql.append('INSERT INTO `{}group_map` (type, gid, mid) VALUES ({}, {}, {});'.format(db.table_prefix, gtype, gid, uid))
# print(args['members'])
for m in members:
if m['id'] in exists_ids:
continue
str_sql = 'INSERT INTO `{}audit_auz` (policy_id, type, rtype, rid, `name`, creator_id, create_time) VALUES ' \
'({pid}, {t}, {rtype}, {rid}, "{name}", {creator_id}, {create_time});' \
''.format(db.table_prefix,
pid=policy_id, t=policy_type, rtype=ref_type,
rid=m['id'], name=m['name'],
creator_id=operator['id'], create_time=_time_now)
sql.append(str_sql)
if db.transaction(sql):
return TPE_OK
else:
return TPE_DATABASE
def remove_members(handler, policy_id, policy_type, ids):
s = SQL(get_db())
auz_ids = [str(i) for i in ids]
# 将用户从所在组中移除
where = 'policy_id={} AND type={} AND id IN ({})'.format(policy_id, policy_type, ','.join(auz_ids))
err = s.reset().delete_from('audit_auz').where(where).exec()
if err != TPE_OK:
return err
return TPE_OK
def get_operators(sql_filter, sql_order, sql_limit):
ss = SQL(get_db())
ss.select_from('audit_auz', ['id', 'policy_id', 'rtype', 'rid', 'name'], alt_name='p')
_where = list()
_where.append('p.type=0')
if len(sql_filter) > 0:
for k in sql_filter:
if k == 'policy_id':
# _where.append('(p.name LIKE "%{filter}%" OR p.desc LIKE "%{filter}%")'.format(filter=sql_filter[k]))
_where.append('p.policy_id={}'.format(sql_filter[k]))
elif k == 'search':
_where.append('(p.name LIKE "%{filter}%")'.format(filter=sql_filter[k]))
else:
log.e('unknown filter field: {}\n'.format(k))
return TPE_PARAM, 0, 0, {}
if len(_where) > 0:
ss.where('( {} )'.format(' AND '.join(_where)))
if sql_order is not None:
_sort = False if not sql_order['asc'] else True
if 'name' == sql_order['name']:
ss.order_by('p.name', _sort)
elif 'rtype' == sql_order['name']:
ss.order_by('p.rtype', _sort)
else:
log.e('unknown order field: {}\n'.format(sql_order['name']))
return TPE_PARAM, ss.total_count, 0, ss.recorder
if len(sql_limit) > 0:
ss.limit(sql_limit['page_index'], sql_limit['per_page'])
err = ss.query()
if err != TPE_OK:
return err, 0, 0, {}
# print(ss.recorder)
return TPE_OK, ss.total_count, ss.page_index, ss.recorder
def get_asset(sql_filter, sql_order, sql_limit):
ss = SQL(get_db())
ss.select_from('audit_auz', ['id', 'policy_id', 'rtype', 'rid', 'name'], alt_name='p')
_where = list()
_where.append('p.type=1')
if len(sql_filter) > 0:
for k in sql_filter:
if k == 'policy_id':
# _where.append('(p.name LIKE "%{filter}%" OR p.desc LIKE "%{filter}%")'.format(filter=sql_filter[k]))
_where.append('p.policy_id={}'.format(sql_filter[k]))
elif k == 'search':
_where.append('(p.name LIKE "%{filter}%")'.format(filter=sql_filter[k]))
else:
log.e('unknown filter field: {}\n'.format(k))
return TPE_PARAM, 0, 0, {}
if len(_where) > 0:
ss.where('( {} )'.format(' AND '.join(_where)))
if sql_order is not None:
_sort = False if not sql_order['asc'] else True
if 'name' == sql_order['name']:
ss.order_by('p.name', _sort)
elif 'rtype' == sql_order['name']:
ss.order_by('p.rtype', _sort)
else:
log.e('unknown order field: {}\n'.format(sql_order['name']))
return TPE_PARAM, ss.total_count, 0, ss.recorder
if len(sql_limit) > 0:
ss.limit(sql_limit['page_index'], sql_limit['per_page'])
err = ss.query()
if err != TPE_OK:
return err, 0, 0, {}
# print(ss.recorder)
return TPE_OK, ss.total_count, ss.page_index, ss.recorder
def rank_reorder(handler, pid, new_rank, start_rank, end_rank, direct):
db = get_db()
# 调节顺序:
# 由pid获取被移动的策略得到其rankp_rank
# p_rank > new_rank向前移动
# 所有 new_rank <= rank < p_rank 的条目其rank+1
# p_rank < new_rank向后移动
# 所有 new_rank >= rank > p_rank 的条目其rank-1
# 最后令pid条目的rank为new_rank
# 1. 判断此账号是否已经存在
s = SQL(db)
err = s.select_from('audit_policy', ['id', 'name', 'rank']).where('audit_policy.id={}'.format(pid)).query()
if err != TPE_OK:
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
p_name = s.recorder[0]['name']
p_rank = s.recorder[0]['rank']
sql = 'UPDATE `{dbtp}audit_policy` SET rank=rank{direct} WHERE (rank>={start_rank} AND rank<={end_rank});' \
''.format(dbtp=db.table_prefix, direct=direct, start_rank=start_rank, end_rank=end_rank)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE
sql = 'UPDATE `{dbtp}audit_policy` SET rank={new_rank} WHERE id={pid};' \
''.format(dbtp=db.table_prefix, new_rank=new_rank, pid=pid)
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE
syslog.sys_log(handler.get_current_user(), handler.request.remote_ip, TPE_OK, "调整审计授权策略顺序:{},从{}{}".format(p_name, p_rank, new_rank))
return TPE_OK
def get_auth(auth_id):
db = get_db()
s = SQL(db)
err = s.select_from('audit_map', ['id', 'h_id', 'u_id', 'a_id']).where('audit_map.uni_id="{}"'.format(auth_id)).query()
if err != TPE_OK:
return None, err
if len(s.recorder) == 0:
return None, TPE_NOT_EXISTS
if len(s.recorder) != 1:
return None, TPE_FAILED
log.v(s.recorder[0])
return s.recorder[0], TPE_OK
def get_remotes(handler, sql_filter, sql_order, sql_limit):
"""
获取当前登录用户的可以远程登录的主机及账号
步骤
1. 查询满足条件的项用户->账号按授权策略顺序排序
2. 在此基础上选出非重复的用户->账号关系项
3. 继续在上一步基础上选出非重复的主机项
4. 为每一个主机查询满足条件的账号项
"""
operator = handler.get_current_user()
db = get_db()
######################################################
# step 1.
######################################################
s1 = []
s1.append('SELECT * FROM {}ops_map'.format(db.table_prefix))
s1_where = []
s1_where.append('u_id={}'.format(operator.id))
s1_where.append('p_state={state}'.format(state=TP_STATE_NORMAL))
s1.append('WHERE ({})'.format(') AND ('.join(s1_where)))
s1.append('ORDER BY p_rank DESC')
sql_1 = ' '.join(s1)
######################################################
# step 2.
######################################################
sql_2 = 'SELECT * FROM ({}) AS s1 GROUP BY ua_id'.format(sql_1)
_f = ['id', 'p_id', 'h_id', 'h_state', 'gh_state', 'h_name', 'ip', 'router_ip', 'router_port']
######################################################
# step 3.
######################################################
sql = []
sql.append('SELECT {}'.format(','.join(_f)))
sql.append('FROM')
sql.append('({}) AS s2'.format(sql_2))
sql.append('GROUP BY h_id')
sql.append('ORDER BY ip')
sql.append('LIMIT {},{}'.format(sql_limit['page_index'] * sql_limit['per_page'], sql_limit['per_page']))
sql.append(';')
sql_counter = []
sql_counter.append('SELECT COUNT(*)')
sql_counter.append('FROM')
sql_counter.append('({}) AS s3'.format(sql_2))
sql_counter.append('GROUP BY h_id')
sql_counter.append(';')
db_ret = db.query(' '.join(sql_counter))
if db_ret is None or len(db_ret) == 0:
return TPE_OK, 0, 1, []
total = len(db_ret)
ret_recorder = [] # 用于构建最终返回的数据
h_ids = [] # 涉及到的主机的ID列表
db_ret = db.query(' '.join(sql))
if db_ret is None:
return TPE_OK, 0, 1, []
for db_item in db_ret:
item = AttrDict()
for i in range(len(_f)):
item[_f[i]] = db_item[i]
item.accounts_ = []
ret_recorder.append(item)
h_ids.append(item.h_id)
######################################################
# step 4.
######################################################
host_ids = [str(i) for i in h_ids]
s4 = []
s4.append('SELECT * FROM {}ops_map'.format(db.table_prefix))
s4_where = []
s4_where.append('u_id={}'.format(operator.id))
s4_where.append('p_state={state}'.format(state=TP_STATE_NORMAL))
s4_where.append('h_id IN ({})'.format(','.join(host_ids)))
s4.append('WHERE ({})'.format(') AND ('.join(s4_where)))
s4.append('ORDER BY p_rank DESC')
sql_4 = ' '.join(s4)
sql = []
_f = ['id', 'uni_id', 'policy_auth_type', 'p_id', 'h_id', 'a_id', 'a_state', 'ga_state', 'a_name', 'protocol_type']
sql.append('SELECT {}'.format(','.join(_f)))
sql.append('FROM')
sql.append('({}) AS s4'.format(sql_4))
sql.append('GROUP BY ua_id')
sql.append(';')
db_ret = db.query(' '.join(sql))
if db_ret is None:
return TPE_OK, 0, 1, []
p_ids = [] # 涉及到的策略的ID列表
for db_item in db_ret:
item = AttrDict()
for i in range(len(_f)):
item[_f[i]] = db_item[i]
if item.p_id not in p_ids:
p_ids.append(item.p_id)
for j in range(len(ret_recorder)):
if ret_recorder[j].h_id == item.h_id:
ret_recorder[j].accounts_.append(item)
# 查询所有相关的授权策略的详细信息
# print('p-ids:', p_ids)
policy_ids = [str(i) for i in p_ids]
_f = ['id', 'flag_rdp', 'flag_ssh']
sql = []
sql.append('SELECT {}'.format(','.join(_f)))
sql.append('FROM {}ops_policy'.format(db.table_prefix))
sql.append('WHERE id IN ({})'.format(','.join(policy_ids)))
sql.append(';')
db_ret = db.query(' '.join(sql))
# print('', db_ret)
for db_item in db_ret:
item = AttrDict()
for i in range(len(_f)):
item[_f[i]] = db_item[i]
for i in range(len(ret_recorder)):
for j in range(len(ret_recorder[i].accounts_)):
if ret_recorder[i].accounts_[j].p_id == item.id:
ret_recorder[i].accounts_[j].policy_ = item
# print(json.dumps(ret_recorder, indent=' '))
return TPE_OK, total, sql_limit['page_index'], ret_recorder
def build_auz_map():
_users = {}
_hosts = {}
_accs = {}
_gusers = {}
_ghosts = {}
_gaccs = {}
_groups = {}
_policies = {}
_p_users = {}
_p_assets = {}
_map = []
s = SQL(get_db())
# 加载所有策略
err = s.reset().select_from('ops_policy', ['id', 'rank', 'state'], alt_name='p').query()
if err != TPE_OK:
return err
if 0 == len(s.recorder):
return TPE_OK
for i in s.recorder:
_policies[i.id] = i
# 加载所有的用户
err = s.reset().select_from('user', ['id', 'username', 'surname', 'state'], alt_name='u').query()
if err != TPE_OK:
return err
if 0 == len(s.recorder):
return TPE_OK
for i in s.recorder:
_users[i.id] = i
# 加载所有的主机
err = s.reset().select_from('host', ['id', 'name', 'ip', 'router_ip', 'router_port', 'state'], alt_name='h').query()
if err != TPE_OK:
return err
if 0 == len(s.recorder):
return TPE_OK
for i in s.recorder:
_hosts[i.id] = i
# 加载所有的账号
err = s.reset().select_from('acc', ['id', 'host_id', 'username', 'protocol_type', 'protocol_port', 'auth_type', 'state'], alt_name='a').query()
if err != TPE_OK:
return err
if 0 == len(s.recorder):
return TPE_OK
for i in s.recorder:
_accs[i.id] = i
# 加载所有的组
err = s.reset().select_from('group', ['id', 'type', 'state'], alt_name='g').query()
if err != TPE_OK:
return err
for i in s.recorder:
_groups[i.id] = i
if i.type == TP_GROUP_USER:
_gusers[i.id] = []
elif i.type == TP_GROUP_HOST:
_ghosts[i.id] = []
elif i.type == TP_GROUP_ACCOUNT:
_gaccs[i.id] = []
# 加载所有的组
err = s.reset().select_from('group_map', ['id', 'type', 'gid', 'mid'], alt_name='g').query()
if err != TPE_OK:
return err
for g in s.recorder:
if g.type == TP_GROUP_USER:
# if g.gid not in _gusers:
# _gusers[g.gid] = []
_gusers[g.gid].append(_users[g.mid])
elif g.type == TP_GROUP_HOST:
# if g.gid not in _ghosts:
# _ghosts[g.gid] = []
_ghosts[g.gid].append(_hosts[g.mid])
elif g.type == TP_GROUP_ACCOUNT:
# if g.gid not in _gaccs:
# _gaccs[g.gid] = []
_gaccs[g.gid].append(_accs[g.mid])
# 加载所有策略明细
err = s.reset().select_from('ops_auz', ['id', 'policy_id', 'type', 'rtype', 'rid'], alt_name='o').query()
if err != TPE_OK:
return err
if 0 == len(s.recorder):
return TPE_OK
# 分解各个策略中操作者和被操作资产的信息
for i in s.recorder:
if i.type == TP_POLICY_OPERATOR:
if i.policy_id not in _p_users:
_p_users[i.policy_id] = []
if i.rtype == TP_USER:
u = _users[i.rid]
_p_users[i.policy_id].append({
'u_id': i.rid,
'u_state': u.state,
'gu_id': 0,
'gu_state': 0,
'u_name': u.username,
'u_surname': u.surname,
'auth_from_': 'USER'
})
elif i.rtype == TP_GROUP_USER:
for u in _gusers[i.rid]:
_p_users[i.policy_id].append({
'u_id': u.id,
'u_state': u.state,
'gu_id': i.rid,
'gu_state': _groups[i.rid].state,
'u_name': u.username,
'u_surname': u.surname,
'auth_from_': 'gUSER'
})
else:
log.e('invalid operator type.\n')
return TPE_FAILED
elif i.type == TP_POLICY_ASSET:
if i.policy_id not in _p_assets:
_p_assets[i.policy_id] = []
if i.rtype == TP_ACCOUNT:
a = _accs[i.rid]
h = _hosts[a.host_id]
_p_assets[i.policy_id].append({
'a_id': i.rid,
'a_state': a.state,
'ga_id': 0,
'ga_state': 0,
'h_id': h.id,
'h_state': h.state,
'gh_id': 0,
'gh_state': 0,
'a_name': a.username,
'protocol_type': a.protocol_type,
'protocol_port': a.protocol_port,
'h_name': h.name,
'ip': h.ip,
'router_ip': h.router_ip,
'router_port': h.router_port,
'auth_to_': 'ACC'
})
elif i.rtype == TP_GROUP_ACCOUNT:
for a in _gaccs[i.rid]:
h = _hosts[a.host_id]
_p_assets[i.policy_id].append({
'a_id': a.id,
'a_state': a.state,
'ga_id': i.rid,
'ga_state': _groups[i.rid].state,
'h_id': h.id,
'h_state': h.state,
'gh_id': 0,
'gh_state': 0,
'a_name': a.username,
'protocol_type': a.protocol_type,
'protocol_port': a.protocol_port,
'h_name': h.name,
'ip': h.ip,
'router_ip': h.router_ip,
'router_port': h.router_port,
'auth_to_': 'gACC'
})
elif i.rtype == TP_HOST:
for aid in _accs:
if _accs[aid].host_id == i.rid:
a = _accs[aid]
h = _hosts[i.rid]
_p_assets[i.policy_id].append({
'a_id': aid,
'a_state': a.state,
'ga_id': 0,
'ga_state': 0,
'h_id': h.id,
'h_state': h.state,
'gh_id': 0,
'gh_state': 0,
'a_name': a.username,
'protocol_type': a.protocol_type,
'protocol_port': a.protocol_port,
'h_name': h.name,
'ip': h.ip,
'router_ip': h.router_ip,
'router_port': h.router_port,
'auth_to_': 'HOST'
})
elif i.rtype == TP_GROUP_HOST:
for h in _ghosts[i.rid]:
for aid in _accs:
if _accs[aid].host_id == h.id:
a = _accs[aid]
_p_assets[i.policy_id].append({
'a_id': aid,
'a_state': a.state,
'ga_id': 0,
'ga_state': 0,
'h_id': h.id,
'h_state': h.state,
'gh_id': i.rid,
'gh_state': _groups[i.rid].state,
'a_name': a.username,
'protocol_type': a.protocol_type,
'protocol_port': a.protocol_port,
'h_name': h.name,
'ip': h.ip,
'router_ip': h.router_ip,
'router_port': h.router_port,
'auth_to_': 'gHOST'
})
else:
log.e('invalid asset type.\n')
return TPE_FAILED
else:
return TPE_FAILED
# 3. 建立所有一一对应的映射关系
for pid in _policies:
if pid not in _p_users:
continue
for u in _p_users[pid]:
if pid not in _p_assets:
continue
for a in _p_assets[pid]:
x = AttrDict()
x.update({
'p_id': pid,
'p_rank': _policies[pid].rank,
'p_state': _policies[pid].state
})
x.update(u)
x.update(a)
x.uni_id = '{}-{}-{}-{}-{}-{}-{}'.format(x.p_id, x.gu_id, x.u_id, x.gh_id, x.h_id, x.ga_id, x.a_id)
x.ua_id = 'u{}-a{}'.format(x.u_id, x.a_id)
x.policy_auth_type = TP_POLICY_AUTH_UNKNOWN
if u['auth_from_'] == 'USER' and a['auth_to_'] == 'ACC':
x.policy_auth_type = TP_POLICY_AUTH_USER_ACC
elif u['auth_from_'] == 'USER' and a['auth_to_'] == 'gACC':
x.policy_auth_type = TP_POLICY_AUTH_USER_gACC
elif u['auth_from_'] == 'USER' and a['auth_to_'] == 'HOST':
x.policy_auth_type = TP_POLICY_AUTH_USER_HOST
elif u['auth_from_'] == 'USER' and a['auth_to_'] == 'gHOST':
x.policy_auth_type = TP_POLICY_AUTH_USER_gHOST
elif u['auth_from_'] == 'gUSER' and a['auth_to_'] == 'ACC':
x.policy_auth_type = TP_POLICY_AUTH_gUSER_ACC
elif u['auth_from_'] == 'gUSER' and a['auth_to_'] == 'gACC':
x.policy_auth_type = TP_POLICY_AUTH_gUSER_gACC
elif u['auth_from_'] == 'gUSER' and a['auth_to_'] == 'HOST':
x.policy_auth_type = TP_POLICY_AUTH_gUSER_HOST
elif u['auth_from_'] == 'gUSER' and a['auth_to_'] == 'gHOST':
x.policy_auth_type = TP_POLICY_AUTH_gUSER_gHOST
_map.append(x)
db = get_db()
dbtp = db.table_prefix
db.exec('DELETE FROM {}ops_map'.format(dbtp))
values = []
for i in _map:
v = '("{uni_id}","{ua_id}",{p_id},{p_rank},{p_state},{policy_auth_type},{u_id},{u_state},{gu_id},{gu_state},{h_id},{h_state},{gh_id},{gh_state},{a_id},{a_state},{ga_id},{ga_state},' \
'"{u_name}","{u_surname}","{h_name}","{ip}","{router_ip}",{router_port},"{a_name}",{protocol_type},{protocol_port})' \
''.format(uni_id=i.uni_id, ua_id=i.ua_id, p_id=i.p_id, p_rank=i.p_rank, p_state=i.p_state,policy_auth_type=i.policy_auth_type,
u_id=i.u_id, u_state=i.u_state, gu_id=i.gu_id, gu_state=i.gu_state, h_id=i.h_id, h_state=i.h_state,
gh_id=i.gh_id, gh_state=i.gh_state, a_id=i.a_id, a_state=i.a_state, ga_id=i.ga_id, ga_state=i.ga_state,
u_name=i.u_name, u_surname=i.u_surname, h_name=i.h_name, ip=i.ip, router_ip=i.router_ip, router_port=i.router_port,
a_name=i.a_name, protocol_type=i.protocol_type, protocol_port=i.protocol_port)
values.append(v)
sql = 'INSERT INTO `{dbtp}ops_map` (uni_id,ua_id,p_id,p_rank,p_state,policy_auth_type,u_id,u_state,gu_id,gu_state,h_id,h_state,gh_id,gh_state,a_id,a_state,ga_id,ga_state,' \
'u_name,u_surname,h_name,ip,router_ip,router_port,a_name,protocol_type,protocol_port) VALUES \n{values};' \
''.format(dbtp=dbtp, values=',\n'.join(values))
db_ret = db.exec(sql)
if not db_ret:
return TPE_DATABASE
return TPE_OK