478 lines
18 KiB
Diff
478 lines
18 KiB
Diff
From 6a26eeb0692833c657d92206dc06533a73200011 Mon Sep 17 00:00:00 2001
|
|
From: smjiao <smjiao@isoftstone.com>
|
|
Date: Tue, 7 Nov 2023 17:24:13 +0800
|
|
Subject: [PATCH] add pam.d directory file analytic function
|
|
|
|
---
|
|
src/api/management.js | 12 +-
|
|
src/vendor/ant-design-pro/utils/request.js | 2 +-
|
|
.../TranscationDomainConfigurations.vue | 54 +++---
|
|
.../components/AddConfigurationDrawer.vue | 171 ++++++++++++++----
|
|
4 files changed, 176 insertions(+), 63 deletions(-)
|
|
|
|
diff --git a/src/api/management.js b/src/api/management.js
|
|
index 09f9b4a..15f9ea1 100644
|
|
--- a/src/api/management.js
|
|
+++ b/src/api/management.js
|
|
@@ -5,7 +5,8 @@ const api = {
|
|
getManagementConf: '/management/getManagementConf', // 读取业务域配置信息
|
|
queryManageConfChange: '/management/queryManageConfChange', // 读取业务域配置日志信息
|
|
deleteManagementConf: '/management/deleteManagementConf', // 删除业务域配置
|
|
- querySupportedConfs: '/confs/querySupportedConfs' // 查询可供选择的配置文件列表
|
|
+ querySupportedConfs: '/confs/querySupportedConfs', // 查询可供选择的配置文件列表
|
|
+ uploadManagementConf: '/management/uploadManagementConf' // 从本地导入文件 新增/更新配置
|
|
};
|
|
|
|
export default api;
|
|
@@ -59,3 +60,12 @@ export function querySupportedConfs(parameter) {
|
|
}
|
|
});
|
|
}
|
|
+
|
|
+export function uploadManagementConf(file) {
|
|
+ return request({
|
|
+ url: api.uploadManagementConf,
|
|
+ method: 'post',
|
|
+ data: file,
|
|
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
+ });
|
|
+}
|
|
diff --git a/src/vendor/ant-design-pro/utils/request.js b/src/vendor/ant-design-pro/utils/request.js
|
|
index c3307ce..c8015c1 100644
|
|
--- a/src/vendor/ant-design-pro/utils/request.js
|
|
+++ b/src/vendor/ant-design-pro/utils/request.js
|
|
@@ -83,7 +83,7 @@ request.interceptors.request.use(config => {
|
|
const userName = localStorage.getItem('user_name')
|
|
userName && localStorage.setItem('user_name', userName);
|
|
}
|
|
- if (config.url === '/vulnerability/cve/advisory/upload' || config.url === '/vulnerability/cve/unaffected/upload') {
|
|
+ if (config.url === '/vulnerability/cve/advisory/upload' || config.url === '/vulnerability/cve/unaffected/upload' || config.url === '/management/uploadManagementConf') {
|
|
config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
} else {
|
|
config.headers['Content-Type'] = 'application/json'
|
|
diff --git a/src/views/configuration/TranscationDomainConfigurations.vue b/src/views/configuration/TranscationDomainConfigurations.vue
|
|
index 7882254..d090493 100644
|
|
--- a/src/views/configuration/TranscationDomainConfigurations.vue
|
|
+++ b/src/views/configuration/TranscationDomainConfigurations.vue
|
|
@@ -12,7 +12,7 @@
|
|
<div slot="message">
|
|
<span>{{ `已选择` + selectedRowKeys.length + `项` }}</span>
|
|
<a
|
|
- v-if="selectedRowKeys.length > 0"
|
|
+ v-if="selectedRowKeys.length > 0"
|
|
@click="deleteConfigBash(selectedRowKeys, selectedRows)">
|
|
批量删除
|
|
</a>
|
|
@@ -33,9 +33,9 @@
|
|
</a-col>
|
|
</a-row>
|
|
<a-table
|
|
- rowKey="filePath"
|
|
- :columns="columns"
|
|
- :data-source="tableData"
|
|
+ rowKey="filePath"
|
|
+ :columns="columns"
|
|
+ :data-source="tableData"
|
|
:pagination="pagination"
|
|
:row-selection="rowSelection"
|
|
@change="handleTableChange"
|
|
@@ -48,12 +48,12 @@
|
|
<a-divider type="vertical" />
|
|
<a @click="showConfigChange(record)">配置变更日志</a>
|
|
<a-divider type="vertical" />
|
|
- <a @click="showEditDrawer(record)">编辑配置  </a>
|
|
+ <a @click="showEditDrawer(record)">编辑配置</a>
|
|
<a-divider type="vertical" />
|
|
<a-popconfirm
|
|
- title="你确定删除这行配置吗?"
|
|
- ok-text="确认"
|
|
- cancel-text="取消"
|
|
+ title="你确定删除这行配置吗?"
|
|
+ ok-text="确认"
|
|
+ cancel-text="取消"
|
|
@confirm="deleteConfig(record)">
|
|
<a-icon slot="icon" type="close-circle" style="color: red" />
|
|
<a>删除</a>
|
|
@@ -61,10 +61,10 @@
|
|
</span>
|
|
</a-table>
|
|
<a-drawer
|
|
- title="配置文件内容"
|
|
- :width="720"
|
|
- placement="right"
|
|
- :visible="configContentVisible"
|
|
+ title="配置文件内容"
|
|
+ :width="720"
|
|
+ placement="right"
|
|
+ :visible="configContentVisible"
|
|
:body-style="{paddingBottom: '80px'}"
|
|
@close="closeConfigContent">
|
|
<a-descriptions :column="1" layout="horizontal">
|
|
@@ -81,10 +81,10 @@
|
|
</a-descriptions>
|
|
</a-drawer>
|
|
<a-drawer
|
|
- title="配置日志"
|
|
- :width="1080"
|
|
- placement="right"
|
|
- :visible="configChangeVisible"
|
|
+ title="配置日志"
|
|
+ :width="1080"
|
|
+ placement="right"
|
|
+ :visible="configChangeVisible"
|
|
:body-style="{paddingBottom: '80px'}"
|
|
@close="closeConfigChange">
|
|
<a-spin :spinning="logIsLoading">
|
|
@@ -103,8 +103,8 @@
|
|
</div>
|
|
<p class="pLog">变更历史:</p>
|
|
<a-table
|
|
- rowKey="changeId"
|
|
- :columns="confChangeColumns"
|
|
+ rowKey="changeId"
|
|
+ :columns="confChangeColumns"
|
|
:data-source="manageConfChange[0].changeLog"
|
|
:expandIconAsCell="false"
|
|
:expandIconColumnIndex="4"
|
|
@@ -125,11 +125,11 @@
|
|
</div>
|
|
</a-card>
|
|
<domain-selection-modal
|
|
- :showDomainSelection="choiceDomainNameModalVisible"
|
|
+ :showDomainSelection="choiceDomainNameModalVisible"
|
|
@cancel="handleDomainSelectCancel" />
|
|
<add-configuration-drawer
|
|
- :isEdit="true"
|
|
- :visibleControl="editConfVisible"
|
|
+ :isEdit="true"
|
|
+ :visibleControl="editConfVisible"
|
|
:domainName="domainName"
|
|
:editFilePath="editFilePath"
|
|
@ok="onEditConfsOk"
|
|
@@ -225,18 +225,24 @@ export default {
|
|
{
|
|
dataIndex: 'filePath',
|
|
key: 'filePath',
|
|
- title: '配置文件'
|
|
+ title: '配置文件',
|
|
+ width: '20%'
|
|
},
|
|
{
|
|
key: 'contents',
|
|
title: '配置详情',
|
|
- scopedSlots: {customRender: 'contents'}
|
|
+ scopedSlots: {customRender: 'contents'},
|
|
+ width: '50%',
|
|
+ ellipsis: true,
|
|
+ customRender: (text, record) => <a-tooltip placement="topLeft"
|
|
+ title={record.contents}>{record.contents}</a-tooltip>
|
|
},
|
|
{
|
|
key: 'operation',
|
|
title: '操作',
|
|
scopedSlots: {customRender: 'action'},
|
|
- width: 240
|
|
+ width: '30%',
|
|
+ align: 'center'
|
|
}
|
|
];
|
|
},
|
|
diff --git a/src/views/configuration/components/AddConfigurationDrawer.vue b/src/views/configuration/components/AddConfigurationDrawer.vue
|
|
index d6880de..a6aee2f 100644
|
|
--- a/src/views/configuration/components/AddConfigurationDrawer.vue
|
|
+++ b/src/views/configuration/components/AddConfigurationDrawer.vue
|
|
@@ -7,8 +7,8 @@
|
|
</slot>
|
|
</div>
|
|
<a-drawer :title="isEdit ? '编辑配置' : '新增配置'" :width="720"
|
|
- :visible="isEdit ? visibleControl : visible" :body-style="{paddingBottom: '80px'}"
|
|
- @close="handleCancel">
|
|
+ :visible="isEdit ? visibleControl : visible" :body-style="{paddingBottom: '80px'}"
|
|
+ @close="handleCancel">
|
|
<a-form :form="form" :label-col="{span: 5}" :wrapper-col="{span: 18}">
|
|
<a-form-item label="所属业务域">
|
|
<a-input disabled v-decorator="['domainName', {initialValue: domainName}]" />
|
|
@@ -16,13 +16,15 @@
|
|
<div class="conf-form-item" v-for="(key, index) in formList" :key="key">
|
|
<span v-if="!isEdit">
|
|
<a-icon class="dynamic-delete-button" type="minus-circle-o"
|
|
- @click="removeConfForm(index)" v-if="formList.length > 1" />
|
|
+ @click="removeConfForm(index)" v-if="formList.length > 1" />
|
|
新增配置{{ index + 1 }}
|
|
</span>
|
|
<a-form-item label="配置路径">
|
|
<a-select
|
|
v-decorator="[`confFiles[${key}].filePath`, {rules: [{required: true, message: '请输入配置路径'}]}]"
|
|
- placeholder="请选择配置路径" :disabled="isEdit" show-search>
|
|
+ placeholder="请选择配置路径" :disabled="isEdit" show-search @change="value => {
|
|
+ pathSelectionChange(key,value)
|
|
+ }">
|
|
<a-select-option v-for="item in supportedConfList" :value="item" :key="item">
|
|
{{ item }}
|
|
</a-select-option>
|
|
@@ -30,7 +32,8 @@
|
|
</a-form-item>
|
|
<a-form-item>
|
|
<span slot="label">
|
|
- <a-tooltip title="配置来源二选一,推荐使用手动输入">
|
|
+ <a-tooltip title="配置来源三选一,推荐使用手动输入"
|
|
+ v-if="editFilePath!== '/etc/pam.d' && tempPath[key] !== '/etc/pam.d'">
|
|
<a-icon type="question-circle-o" />
|
|
</a-tooltip>
|
|
配置来源
|
|
@@ -40,26 +43,47 @@
|
|
formSelectionChange(key, value);
|
|
}
|
|
">
|
|
- <a-select-option value="manuel">手动输入</a-select-option>
|
|
+ <a-select-option value="manuel" v-if="editFilePath!== '/etc/pam.d' && tempPath[key] !== '/etc/pam.d'">
|
|
+ 手动输入
|
|
+ </a-select-option>
|
|
<a-select-option value="auto">从主机导入</a-select-option>
|
|
+ <a-select-option value="file" v-if="editFilePath!== '/etc/pam.d' && tempPath[key] !== '/etc/pam.d'">
|
|
+ 从本地导入
|
|
+ </a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item label="配置内容" v-if="formSelections[key] === 'manuel'">
|
|
<a-textarea placeholder="请输入配置内容" :rows="8"
|
|
- v-decorator="[`confFiles[${key}].contents`, {rules: [{required: true, message: '请输入内容'}]}]" />
|
|
+ v-decorator="[`confFiles[${key}].contents`, {rules: [{required: true, message: '请输入内容'}]}]" />
|
|
</a-form-item>
|
|
<a-form-item label="选择主机" v-else-if="formSelections[key] === 'auto'">
|
|
<a-select placeholder="请选择文件所在主机"
|
|
- v-decorator="[`confFiles[${key}].hostId`, {rules: [{required: true, message: '请选择主机'}]}]">
|
|
+ v-decorator="[`confFiles[${key}].hostId`, {rules: [{required: true, message: '请选择主机'}]}]">
|
|
<a-spin v-if="hostListLoading" slot="notFoundContent" size="small" />
|
|
<a-select-option v-for="host in hostList" :value="host.hostId" :key="host.hostId">
|
|
{{ host.ip }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
+ <a-form-item label="选择文件" html-for={null} v-else-if="formSelections[key] === 'file'">
|
|
+ <a-upload :file-list="fileDataList" :remove="removeFile" :before-upload="preUpload"
|
|
+ v-decorator="['file',{rules: [{required: true, message: '请选择文件'}]}]">
|
|
+ <div style="display:flex;">
|
|
+ <div style="flex">
|
|
+ <a-button>
|
|
+ <a-icon type="upload"/>
|
|
+ 选择文件
|
|
+ </a-button>
|
|
+ </div>
|
|
+ </div>
|
|
+ </a-upload>
|
|
+ <div class="upload-tip">
|
|
+ <p>文件大小不超过1MB</p>
|
|
+ </div>
|
|
+ </a-form-item>
|
|
</div>
|
|
</a-form>
|
|
- <a-button type="dashed" style="width: 100%" @click="addConfForm()" v-if="!isEdit">
|
|
+ <a-button type="dashed" style="width: 100%" @click="addConfForm()" v-if="formSelections[0] !== 'file' && !isEdit">
|
|
<a-icon type="plus" /> 新增配置
|
|
</a-button>
|
|
<div class="areaButton">
|
|
@@ -71,7 +95,7 @@
|
|
</template>
|
|
|
|
<script>
|
|
-import {addManagementConf, querySupportedConfs} from '@/api/management';
|
|
+import {addManagementConf, querySupportedConfs, uploadManagementConf} from '@/api/management';
|
|
import {domainHostList} from '@/api/configuration';
|
|
// 弹窗添加主机组
|
|
export default {
|
|
@@ -114,8 +138,10 @@ export default {
|
|
formList: [0],
|
|
formSelections: {0: 'manuel'},
|
|
submitIsLoading: false,
|
|
- supportedConfList: []
|
|
- };
|
|
+ supportedConfList: [],
|
|
+ fileDataList: [],
|
|
+ tempPath: {0: ''} // 配置路径值
|
|
+ }
|
|
},
|
|
watch: {
|
|
visibleControl: function () {
|
|
@@ -123,6 +149,9 @@ export default {
|
|
if (this.isEdit && this.visibleControl === true) {
|
|
this.getHostList();
|
|
this.resetData();
|
|
+ if (this.editFilePath === '/etc/pam.d') {
|
|
+ this.formSelections = {0: 'auto'}
|
|
+ }
|
|
setTimeout(function () {
|
|
_this.form.setFieldsValue({confFiles: [{filePath: _this.editFilePath}]});
|
|
}, 100);
|
|
@@ -143,6 +172,7 @@ export default {
|
|
this.formKey += 1;
|
|
this.formList.push(this.formKey);
|
|
this.formSelections[this.formKey] = 'manuel';
|
|
+ this.tempPath[this.formKey] = '';
|
|
},
|
|
removeConfForm(idx) {
|
|
const listTemp = this.formList;
|
|
@@ -154,11 +184,21 @@ export default {
|
|
temp[key] = value;
|
|
this.formSelections = Object.assign({}, temp);
|
|
},
|
|
+ pathSelectionChange(key, value) {
|
|
+ const temp = this.tempPath;
|
|
+ temp[key] = value;
|
|
+ this.tempPath = Object.assign({}, temp);
|
|
+ if (this.tempPath[key] === '/etc/pam.d') {
|
|
+ this.formSelections[key] = 'auto'
|
|
+ }
|
|
+ },
|
|
resetData() {
|
|
this.form.resetFields();
|
|
this.formKey = 0;
|
|
this.formList = [0];
|
|
this.formSelections = {0: 'manuel'};
|
|
+ this.fileDataList = []
|
|
+ this.tempPath = {0: ''};
|
|
},
|
|
showModal() {
|
|
this.resetData();
|
|
@@ -170,33 +210,62 @@ export default {
|
|
this.visible = false;
|
|
this.$emit('cancel');
|
|
},
|
|
+ // 上传文件 添加配置
|
|
+ uploadManagementConf(formData) {
|
|
+ const _this = this
|
|
+ uploadManagementConf(formData).then((res) => {
|
|
+ if (res.code === 200) {
|
|
+ _this.$message.success(res.msg)
|
|
+ } else if (res.code === 206) {
|
|
+ _this.$message.warning(res.msg)
|
|
+ }
|
|
+ _this.visible = false
|
|
+ _this.$emit('ok')
|
|
+ }).catch(function (err) {
|
|
+ _this.$message.error(err.response.message || err.response.data.detail || err.response.data.msg);
|
|
+ }).finally(function () {
|
|
+ _this.submitIsLoading = false
|
|
+ })
|
|
+ },
|
|
+ // 添加配置
|
|
+ addManagementConf(params) {
|
|
+ const _this = this
|
|
+ addManagementConf(params).then(function (res) {
|
|
+ if (res.code === 200) {
|
|
+ _this.$message.success(res.msg)
|
|
+ } else if (res.code === 206) {
|
|
+ _this.$message.warning(res.msg)
|
|
+ }
|
|
+ _this.visible = false
|
|
+ _this.$emit('ok')
|
|
+ }).catch(function (err) {
|
|
+ _this.$message.error(err.response.message || err.response.data.detail || err.response.data.msg);
|
|
+ }).finally(function () {
|
|
+ _this.submitIsLoading = false
|
|
+ })
|
|
+ },
|
|
handleOk() {
|
|
- const _this = this;
|
|
this.form.validateFields((err, values) => {
|
|
if (!err) {
|
|
- const params = {
|
|
- domainName: _this.domainName,
|
|
- confFiles: values.confFiles.filter((conf) => conf)
|
|
- };
|
|
- this.submitIsLoading = true;
|
|
- addManagementConf(params)
|
|
- .then(function (res) {
|
|
- if (res.code === 200) {
|
|
- _this.$message.success(res.msg);
|
|
- } else if (res.code === 206) {
|
|
- _this.$message.warning(res.msg);
|
|
- }
|
|
- _this.visible = false;
|
|
- _this.$emit('ok');
|
|
- })
|
|
- .catch(function (err) {
|
|
- _this.$message.error(err.response.message || err.response.data.detail || err.response.data.msg);
|
|
+ if (this.formSelections[0] === 'file') {
|
|
+ const formData = new FormData()
|
|
+ formData.append('filePath', values.confFiles[0].filePath)
|
|
+ formData.append('domainName', this.domainName)
|
|
+ this.fileDataList.forEach((file) => {
|
|
+ formData.append('file', file);
|
|
})
|
|
- .finally(function () {
|
|
- _this.submitIsLoading = false;
|
|
- });
|
|
+ this.submitIsLoading = true
|
|
+ this.uploadManagementConf(formData)
|
|
+ } else {
|
|
+ const params = {
|
|
+ domainName: this.domainName,
|
|
+ confFiles: values.confFiles.filter((conf) => conf)
|
|
+ }
|
|
+ this.submitIsLoading = true
|
|
+ this.addManagementConf(params)
|
|
+ }
|
|
}
|
|
- });
|
|
+ })
|
|
},
|
|
getHostList() {
|
|
const _this = this;
|
|
@@ -206,21 +275,49 @@ export default {
|
|
_this.hostList = res;
|
|
})
|
|
.catch(function (err) {
|
|
- if (err.response.code !== '400') {
|
|
- _this.$message.error(err.response.message || err.response.data.detail);
|
|
- } else {
|
|
+ _this.$message.error(err.response.data.msg || err.response.data.detail);
|
|
+ if (err.response.data.code === 400) {
|
|
_this.hostList = [];
|
|
}
|
|
})
|
|
.finally(function () {
|
|
_this.hostListLoading = false;
|
|
});
|
|
+ },
|
|
+ removeFile(file) {
|
|
+ const index = this.fileDataList.indexOf(file);
|
|
+ const newFileDataList = this.fileDataList.slice();
|
|
+ newFileDataList.splice(index, 1);
|
|
+ this.fileDataList = newFileDataList;
|
|
+ },
|
|
+ preUpload(file) {
|
|
+ this.fileDataList = [file];
|
|
+ // 读取文件大小
|
|
+ const fileSize = file.size;
|
|
+ if (fileSize / 1024 / 1024 > 1) {
|
|
+ this.$message.error('文件大于1M!');
|
|
+ this.removeFile(file);
|
|
+ return false;
|
|
+ }
|
|
+ return false;
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
+.upload-tip {
|
|
+ left: 150px;
|
|
+ top: 0px;
|
|
+ position: absolute;
|
|
+ font-size: 15px;
|
|
+ line-height: 18px;
|
|
+ width: 170px;
|
|
+
|
|
+ p {
|
|
+ margin-bottom: 5px;
|
|
+ }
|
|
+}
|
|
.areaButton {
|
|
position: absolute;
|
|
right: 0;
|
|
--
|
|
2.38.1.windows.1
|
|
|