CN-318 feat: detection服务质量界面

This commit is contained in:
chenjinsong
2022-02-25 13:33:54 +08:00
parent 2889c3cb19
commit 6158a6a4f4
19 changed files with 1197 additions and 683 deletions

View File

@@ -99,6 +99,8 @@
.basic-info__item { .basic-info__item {
padding-right: 40px; padding-right: 40px;
display: flex;
align-items: center;
i { i {
padding-right: 6px; padding-right: 6px;
color: #8FA1BE; color: #8FA1BE;

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "cn-icon"; /* Project id 2614877 */ font-family: "cn-icon"; /* Project id 2614877 */
src: url('iconfont.woff2?t=1644832156673') format('woff2'), src: url('iconfont.woff2?t=1645687921203') format('woff2'),
url('iconfont.woff?t=1644832156673') format('woff'), url('iconfont.woff?t=1645687921203') format('woff'),
url('iconfont.ttf?t=1644832156673') format('truetype'); url('iconfont.ttf?t=1645687921203') format('truetype');
} }
.cn-icon { .cn-icon {
@@ -13,7 +13,11 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.cn-icon-shaixuan:before { .cn-icon-detection:before {
content: "\e766";
}
.cn-icon-filter:before {
content: "\e764"; content: "\e764";
} }

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -60,7 +60,7 @@
</template> </template>
<template v-else-if="from === 'domain'"> <template v-else-if="from === 'domain'">
<div class="body__row"> <div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-category"></i>{{$t('entities.Group')}}</span> <span class="body__row-label"><i class="cn-icon cn-icon-category"></i>{{$t('entities.group')}}</span>
<div class="body__row-value" :title="d.categoryGroup">{{d.categoryGroup || '-'}}</div> <div class="body__row-value" :title="d.categoryGroup">{{d.categoryGroup || '-'}}</div>
</div> </div>
<div class="body__row"> <div class="body__row">

View File

@@ -39,7 +39,7 @@ const routes = [
component: () => import('@/views/entityExplorer/EntityExplorer') component: () => import('@/views/entityExplorer/EntityExplorer')
}, },
{ {
path: '/detections', path: '/detection/:typeName',
component: () => import('@/views/detections/Index') component: () => import('@/views/detections/Index')
}, },
{ {

View File

@@ -74,16 +74,28 @@ export const api = {
entityIpRelatedServerDomain: '/interface/entity/detail/overview/ip/relatedDomain', entityIpRelatedServerDomain: '/interface/entity/detail/overview/ip/relatedDomain',
entityIpRelatedServerApp: '/interface/entity/detail/overview/ip/relatedApp', entityIpRelatedServerApp: '/interface/entity/detail/overview/ip/relatedApp',
// detection // detection
detectionSeverityTrend: '/interface/detection/filter/severityTrend', detection: {
detectionAttackType: '/interface/detection/filter/attackType', securityEvent: {
detectionOffenderIp: '/interface/detection/filter/offenderIp', eventSeverityTrend: '/interface/detection/filter/severityTrend',
detectionOffenderLocation: '/interface/detection/filter/offenderLocation', securityType: '/interface/detection/filter/attackType',
detectionVictimIp: '/interface/detection/filter/victimIp', offenderIp: '/interface/detection/filter/offenderIp',
detectionVictimLocation: '/interface/detection/filter/victimLocation', offenderLocation: '/interface/detection/filter/offenderLocation',
detectionSeverity: '/interface/detection/filter/severity', victimIp: '/interface/detection/filter/victimIp',
detectionListBasic: '/interface/detection/list/basic', victimLocation: '/interface/detection/filter/victimLocation',
detectionOverviewBasic: '/interface/detection/detail/overview/basic', eventSeverity: '/interface/detection/filter/severity',
detectionOverviewEvent: '/interface/detection/detail/overview/event' listBasic: '/interface/detection/list/basic',
overviewBasic: '/interface/detection/detail/overview/basic',
overviewEvent: '/interface/detection/detail/overview/event'
},
performanceEvent: {
eventSeverityTrend: '/interface/detection/filter/severityTrend',
securityType: '/interface/detection/filter/attackType',
eventSeverity: '/interface/detection/filter/severity',
activeEntity: '/interface/detection/filter/activeEntity',
listBasic: '/interface/detection/list/basic',
overviewBasic: '/interface/detection/detail/overview/basic'
}
}
} }
/* panel */ /* panel */

View File

@@ -165,6 +165,11 @@ export const securityType = {
dga: 'dga', dga: 'dga',
ddos: 'ddos' ddos: 'ddos'
} }
export const detectionPageType = {
securityEvent: 'securityEvent',
performanceEvent: 'performanceEvent'
}
export const iso36112 = { export const iso36112 = {
[storageKey.iso36112Capital]: 'data/countriesWithCapital', [storageKey.iso36112Capital]: 'data/countriesWithCapital',
[storageKey.iso36112WorldLow]: 'worldChinaLow', [storageKey.iso36112WorldLow]: 'worldChinaLow',

View File

@@ -10,6 +10,7 @@
<detection-row <detection-row
v-for="(data, index) in listData" v-for="(data, index) in listData"
:detection="data" :detection="data"
:page-type="pageType"
:timeFilter="timeFilter" :timeFilter="timeFilter"
:key="index" :key="index"
:ref="`detectionRow${index}`" :ref="`detectionRow${index}`"
@@ -33,7 +34,8 @@ export default {
from: String, from: String,
pageObj: Object, pageObj: Object,
loading: Boolean, loading: Boolean,
timeFilter: Object timeFilter: Object,
pageType: String // 安全事件、服务质量
}, },
data () { data () {
return { return {

View File

@@ -5,16 +5,18 @@
<span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span> <span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span>
</div> </div>
<div class="cn-detection__case"> <div class="cn-detection__case">
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[detection.eventSecurity]}`"> <div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[detection.eventSecurity]}`"></div>
</div>
<div class="cn-detection__row"> <div class="cn-detection__row">
<div class="cn-detection__header"> <div class="cn-detection__header" v-if="pageType === detectionPageType.securityEvent">
<i class="cn-icon cn-icon-attacker" ></i>{{detection.offenderIp}} <i class="cn-icon cn-icon-attacker" ></i>{{detection.offenderIp}}
<span class="line">-------</span> <span class="line">-------</span>
<span class="circle"></span> <span class="circle"></span>
<i class="cn-icon cn-icon-attacked" ></i>{{detection.victimIp}} <i class="cn-icon cn-icon-attacked" ></i>{{detection.victimIp}}
</div> </div>
<div class="cn-detection__header" v-else-if="pageType === detectionPageType.performanceEvent">
<div class="cn-entity__icon"><i :class="iconClass"></i></div>
<div style="padding-left: 3px;">{{detection.serverIp || detection.domain || detection.appName || 'Unknown'}}</div>
</div>
<div class="cn-detection__body"> <div class="cn-detection__body">
<div class="body__basic-info"> <div class="body__basic-info">
<div class="basic-info"> <div class="basic-info">
@@ -28,12 +30,12 @@
<span>{{$t('detection.list.securityType')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('detection.list.securityType')}}&nbsp;:&nbsp;&nbsp;</span>
<span>{{detection.securityType}}</span> <span>{{detection.securityType}}</span>
</div> </div>
<div class="basic-info__item" v-if="detection.malwareName && detection.malwareName.length > 0 "> <div class="basic-info__item" v-if="detection.malwareName">
<i class="cn-icon cn-icon-trojan"></i> <i class="cn-icon cn-icon-trojan"></i>
<span>{{$t('detection.list.malwareName')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('detection.list.malwareName')}}&nbsp;:&nbsp;&nbsp;</span>
<span>{{detection.malwareName}}</span> <span>{{detection.malwareName}}</span>
</div> </div>
<div class="basic-info__item" v-if="detection.cryptominingPool && detection.cryptominingPool.length > 0 "> <div class="basic-info__item" v-if="detection.cryptominingPool">
<i class="cn-icon cn-icon-mining-pool"></i> <i class="cn-icon cn-icon-mining-pool"></i>
<span>{{$t('detection.list.cryptominingPool')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('detection.list.cryptominingPool')}}&nbsp;:&nbsp;&nbsp;</span>
<span>{{detection.cryptominingPool}}</span> <span>{{detection.cryptominingPool}}</span>
@@ -43,6 +45,13 @@
<span>{{$t('detection.list.startTime')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('detection.list.startTime')}}&nbsp;:&nbsp;&nbsp;</span>
<span>{{dayJs.tz(getMillisecond(detection.startTime)).format('YYYY-MM-DD HH:mm:ss')}}</span> <span>{{dayJs.tz(getMillisecond(detection.startTime)).format('YYYY-MM-DD HH:mm:ss')}}</span>
</div> </div>
<div class="basic-info__item">
<i class="cn-icon cn-icon-time2"></i>
<span>{{$t('overall.duration')}}&nbsp;:&nbsp;&nbsp;</span>
<span style="display: inline-block;height: 6px;width: 6px;border-radius: 50%;margin-right: 8px;"
:style="pointColor(detection)"></span>
<span>{{unitConvert(detection.durationMs, 'time', null, null, 0).join(' ')}}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -50,10 +59,28 @@
<el-collapse-transition> <el-collapse-transition>
<div class="cn-detection__detail-overview" v-if="!isCollapse"> <div class="cn-detection__detail-overview" v-if="!isCollapse">
<el-divider></el-divider> <el-divider></el-divider>
<detection-overview <detection-security-event-overview
v-if="pageType === detectionPageType.securityEvent"
:detection="detection" :detection="detection"
:time-filter="timeFilter" :time-filter="timeFilter"
></detection-overview> ></detection-security-event-overview>
<template v-else>
<detection-performance-event-ip-overview
v-if="detection.entityType === entityType.ip.toLowerCase()"
:detection="detection"
:time-filter="timeFilter"
></detection-performance-event-ip-overview>
<detection-performance-event-domain-overview
v-else-if="detection.entityType === entityType.domain.toLowerCase()"
:detection="detection"
:time-filter="timeFilter"
></detection-performance-event-domain-overview>
<detection-performance-event-app-overview
v-else-if="detection.entityType === entityType.app.toLowerCase()"
:detection="detection"
:time-filter="timeFilter"
></detection-performance-event-app-overview>
</template>
</div> </div>
</el-collapse-transition> </el-collapse-transition>
</div> </div>
@@ -61,26 +88,70 @@
</template> </template>
<script> <script>
import { eventSeverityColor } from '@/utils/constants' import { eventSeverityColor, detectionPageType, entityType } from '@/utils/constants'
import { getMillisecond } from '@/utils/date-util' import { getMillisecond } from '@/utils/date-util'
import DetectionOverview from '@/views/detections/DetectionOverview' import unitConvert from '@/utils/unit-convert'
import DetectionSecurityEventOverview from '@/views/detections/overview/DetectionSecurityEventOverview'
import DetectionPerformanceEventIpOverview from '@/views/detections/overview/DetectionPerformanceEventIpOverview'
import DetectionPerformanceEventAppOverview from '@/views/detections/overview/DetectionPerformanceEventAppOverview'
import DetectionPerformanceEventDomainOverview from '@/views/detections/overview/DetectionPerformanceEventDomainOverview'
export default { export default {
name: 'DetectionRow', name: 'DetectionRow',
components: { components: {
DetectionOverview DetectionSecurityEventOverview,
DetectionPerformanceEventIpOverview,
DetectionPerformanceEventAppOverview,
DetectionPerformanceEventDomainOverview
}, },
props: { props: {
index: Number, index: Number,
timeFilter: Object, timeFilter: Object,
detection: Object detection: Object,
pageType: String // 安全事件、服务质量
}, },
data () { data () {
return { return {
entityType,
detectionPageType,
isCollapse: true, // 是否是折叠状态 isCollapse: true, // 是否是折叠状态
eventSeverityColor eventSeverityColor
} }
}, },
computed: {
iconClass () {
let className
switch (this.detection.entityType) {
case ('ip'): {
className = 'cn-icon cn-icon-ip'
break
}
case ('domain'): {
className = 'cn-icon cn-icon-domain'
break
}
case ('app'): {
className = 'cn-icon cn-icon-app'
break
}
default:
break
}
return className
},
pointColor () {
return function (detection) {
let color = '#8FA1BE'
if (detection.startTime && detection.endTime) {
if (getMillisecond(detection.endTime) - getMillisecond(detection.startTime) < 5 * 60 * 1000) {
color = '#D84C4C'
}
}
return { backgroundColor: color }
}
}
},
methods: { methods: {
unitConvert,
getMillisecond, getMillisecond,
/* 切换折叠状态 */ /* 切换折叠状态 */
switchCollapse () { switchCollapse () {

View File

@@ -14,10 +14,10 @@
></detection-search> ></detection-search>
<!-- 内容区 --> <!-- 内容区 -->
<div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column"> <div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column">
<div class="detection__event-severity-bar" id="detectionEventSeverityBar"></div> <div class="detection__event-severity-bar" id="eventSeverityTrendBar"></div>
<div style="display: flex;"> <div style="display: flex;">
<detection-filter <detection-filter
:filter-data="filterData" :filter-data="filterData[pageType]"
:q="q" :q="q"
:time-filter="timeFilter" :time-filter="timeFilter"
@filter="filter" @filter="filter"
@@ -29,7 +29,7 @@
<div class="chart-header"> <div class="chart-header">
<div class="chart-header__title">{{$t('detection.severity')}}</div> <div class="chart-header__title">{{$t('detection.severity')}}</div>
</div> </div>
<div class="chart-content" id="detectionSeverityPer"> <div class="chart-content" id="eventSeverityPie">
</div> </div>
</div> </div>
<div class="statistics__category"> <div class="statistics__category">
@@ -41,7 +41,7 @@
</div> </div>
<div class="statistics__active-attack"> <div class="statistics__active-attack">
<div class="chart-header"> <div class="chart-header">
<div class="chart-header__title">{{$t('detection.activeAttacker')}}</div> <div class="chart-header__title">{{pageType === detectionPageType.securityEvent ? $t('detection.activeAttacker') : $t('detections.activeEntity')}}</div>
</div> </div>
<div class="chart-content" style="" id="detectionActiveAttacker"> <div class="chart-content" style="" id="detectionActiveAttacker">
</div> </div>
@@ -51,6 +51,7 @@
:list-data="listData" :list-data="listData"
:pageObj="pageObj" :pageObj="pageObj"
:time-filter="timeFilter" :time-filter="timeFilter"
:page-type="pageType"
@pageSize="pageSize" @pageSize="pageSize"
@pageNo="pageNo" @pageNo="pageNo"
:loading="listLoading" :loading="listLoading"
@@ -80,14 +81,13 @@ import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
import DetectionFilter from '@/views/detections/DetectionFilter' import DetectionFilter from '@/views/detections/DetectionFilter'
import DetectionList from '@/views/detections/DetectionList' import DetectionList from '@/views/detections/DetectionList'
import Pagination from '@/components/common/Pagination' import Pagination from '@/components/common/Pagination'
import { defaultPageSize } from '@/utils/constants' import { defaultPageSize, detectionPageType } from '@/utils/constants'
import { getNowTime, getSecond } from '@/utils/date-util' import { getNowTime, getSecond } from '@/utils/date-util'
import { ref } from 'vue' import { ref } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor,getSeriesIndex } from '@/views/detections/options/detectionOptions' import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor,getSeriesIndex } from '@/views/detections/options/detectionOptions'
import ChartEchart from '@/views/charts/charts/ChartEchart' import { api, getData } from '@/utils/api'
import { api } from '@/utils/api' import { useRoute } from 'vue-router'
import { get } from '@/utils/http'
export default { export default {
name: 'Index', name: 'Index',
@@ -97,8 +97,7 @@ export default {
TimeRefresh, TimeRefresh,
DetectionFilter, DetectionFilter,
DetectionList, DetectionList,
Pagination, Pagination
ChartEchart
}, },
data () { data () {
return { return {
@@ -108,7 +107,9 @@ export default {
total: 0 total: 0
}, },
q: '', q: '',
filterData: [ detectionPageType,
filterData: {
securityEvent: [
{ {
title: this.$t('detections.eventSeverity'), title: this.$t('detections.eventSeverity'),
column: 'eventSeverity', column: 'eventSeverity',
@@ -154,13 +155,7 @@ export default {
value: [], value: [],
showMore: false, showMore: false,
showIndex: 9, showIndex: 9,
data: [ data: [] // 从接口动态获取
{
label: '1.2.6.8',
value: '1.2.6.8',
count: 50
}
] // 从接口动态获取
}, },
{ {
title: this.$t('detections.offenderLocation'), title: this.$t('detections.offenderLocation'),
@@ -169,18 +164,28 @@ export default {
value: [], value: [],
showMore: false, showMore: false,
showIndex: 9, showIndex: 9,
data: [ data: [] // 从接口动态获取
{
label: 'China',
value: 'china',
count: 50
}
] // 从接口动态获取
} }
], ],
performanceEvent: [
{
title: this.$t('detections.eventSeverity'),
column: 'eventSeverity',
collapse: false,
value: [], // value之间是or的关系
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
},
{
title: this.$t('detections.securityType'),
column: 'securityType',
collapse: false,
value: [],
data: [] // 从接口动态获取
}
]
},
listData: [], listData: [],
listLoading: false, listLoading: false,
eventSeverityOption: null,
eventSeverityData: [], eventSeverityData: [],
severityPerOption: null, severityPerOption: null,
severityPerData: [], severityPerData: [],
@@ -191,24 +196,10 @@ export default {
} }
}, },
methods: { methods: {
initEventSeverityTrendData () { // 初始化顶部大柱状图
const chartDom = document.getElementById('detectionEventSeverityBar') initEventSeverityTrendData (params) {
const detectionChart = echarts.init(chartDom) getData(api.detection[this.pageType].eventSeverityTrend, params).then(data => {
this.eventSeverityOption = this.$_.cloneDeep(multipleBarOption) data = [
const queryParams = {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionSeverityTrend, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'matrix',
result: [
{ {
legend: "critical", legend: "critical",
values: [[1435781430781, "5"], [1435781431781, "3"],[1435781432781, "5"], [1435781433781, "3"]] values: [[1435781430781, "5"], [1435781431781, "3"],[1435781432781, "5"], [1435781433781, "3"]]
@@ -227,40 +218,24 @@ export default {
values: [[1435781430781, "5"], [1435781431781, "7"],[1435781432781, "5"], [1435781433781, "8"]] values: [[1435781430781, "5"], [1435781431781, "7"],[1435781432781, "5"], [1435781433781, "8"]]
} }
] ]
} const chartDom = document.getElementById('eventSeverityTrendBar')
} const detectionChart = echarts.init(chartDom)
if (response.code === 200) { const eventSeverityTrendOption = this.$_.cloneDeep(multipleBarOption)
response.data.result.forEach(item => { data.forEach(item => {
this.eventSeverityOption.series[Number(getSeriesIndex(item.legend))].data = item.values.map(v => Number(v[1])) eventSeverityTrendOption.series[Number(getSeriesIndex(item.legend))].data = item.values.map(v => Number(v[1]))
}) })
eventSeverityTrendOption.xAxis.data = data[0].values.map(v => [window.$dayJs.tz(Number(v[0])).format('YYYY-MM-DD HH:mm:ss')])
this.eventSeverityOption.xAxis.data = response.data.result[0].values.map(v => [window.$dayJs.tz(Number(v[0])).format('YYYY-MM-DD HH:mm:ss')])
}
}).finally(() => {
this.$nextTick(() => { this.$nextTick(() => {
this.eventSeverityOption && detectionChart.setOption(this.eventSeverityOption) detectionChart.setOption(eventSeverityTrendOption)
}) })
}).catch(error => {
}) })
}, },
initSeverityPerData () { // 初始化左侧事件严重等级和小饼图
const chartDom = document.getElementById('detectionSeverityPer') initEventSeverityData (params) {
const detectionChart = echarts.init(chartDom) getData(api.detection[this.pageType].eventSeverity, params).then(data => {
this.severityPerOption = this.$_.cloneDeep(pieForSeverity) data = [
const queryParams = {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionEventSeverity, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
eventSeverity: 'critical', eventSeverity: 'critical',
count: 1048 count: 1048
@@ -278,39 +253,21 @@ export default {
count: 300 count: 300
} }
] ]
} this.filterData[this.pageType][0].data = data.map(r => ({ label: r.eventSeverity, value: r.eventSeverity, count: r.count }))
} const eventSeverityOption = this.$_.cloneDeep(pieForSeverity)
if (response.code === 200) { eventSeverityOption.series[0].data = data.map(d => {
this.filterData[0].data = response.data.result.map(r => ({ label: r.eventSeverity, value: r.eventSeverity, count: r.count }))
this.severityPerData = response.data.result.map(d => {
return { value: d.count, name: d.eventSeverity, itemStyle: { color: getSeverityColor(d.eventSeverity) } } return { value: d.count, name: d.eventSeverity, itemStyle: { color: getSeverityColor(d.eventSeverity) } }
}) })
} const chartDom = document.getElementById('eventSeverityPie')
}).finally(() => { const detectionChart = echarts.init(chartDom)
this.$nextTick(() => { detectionChart.setOption(eventSeverityOption)
this.severityPerOption.series[0].data = this.severityPerData }).catch(error => {
this.severityPerOption && detectionChart.setOption(this.severityPerOption)
})
}) })
}, },
initCategoryPerData () { initSecurityTypeData (params) {
const chartDom = document.getElementById('detectionCategoryPer') getData(api.detection[this.pageType].securityType, params).then(data => {
const detectionChart = echarts.init(chartDom) data = [
this.categoryPerOption = this.$_.cloneDeep(pieForSeverity)
const queryParams = {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionAttackType, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
attackType: 'command and control', attackType: 'command and control',
count: 1048 count: 1048
@@ -331,39 +288,21 @@ export default {
count: 50 count: 50
} }
] ]
} this.filterData[this.pageType][1].data = data.map(r => ({ label: r.attackType, value: r.attackType, count: r.count }))
} const chartDom = document.getElementById('detectionCategoryPer')
if (response.code === 200) { const detectionChart = echarts.init(chartDom)
this.filterData[1].data = response.data.result.map(r => ({ label: r.attackType, value: r.attackType, count: r.count })) const securityTypeOption = this.$_.cloneDeep(pieForSeverity)
this.categoryPerData = response.data.result.map(d => { securityTypeOption.series[0].data = data.map(d => {
return { value: d.count, name: d.attackType, itemStyle: { color: getAttackColor(d.attackType) } } return { value: d.count, name: d.attackType, itemStyle: { color: getAttackColor(d.attackType) } }
}) })
} detectionChart.setOption(securityTypeOption)
}).finally(() => { }).catch(error => {
this.$nextTick(() => {
this.categoryPerOption.series[0].data = this.categoryPerData
this.categoryPerOption && detectionChart.setOption(this.categoryPerOption)
})
}) })
}, },
initActiveAttackData () { initOffenderIpData (params) {
const chartDom = document.getElementById('detectionActiveAttacker') getData(api.detection[this.pageType].offenderIp, params).then(data => {
const detectionChart = echarts.init(chartDom) data = [
this.activeAttackOption = this.$_.cloneDeep(activeAttackBar)
const queryParams = {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionOffenderIp, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
offenderIp: '192.168.12.21', offenderIp: '192.168.12.21',
count: 99999 count: 99999
@@ -381,38 +320,25 @@ export default {
count: 55555 count: 55555
} }
] ]
} this.filterData[this.pageType][4].data = data.map(r => ({ label: r.offenderIp, value: r.offenderIp, count: r.count }))
} const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][4].data)
if (response.code === 200) { this.filterData[this.pageType][4].showMore = showMore
this.filterData[4].data = response.data.result.map(r => ({ label: r.offenderIp, value: r.offenderIp, count: r.count })) this.filterData[this.pageType][4].showIndex = showIndex
const { showMore, showIndex } = this.computeFilterPage(this.filterData[4].data)
this.filterData[4].showMore = showMore const chartDom = document.getElementById('detectionActiveAttacker')
this.filterData[4].showIndex = showIndex const detectionChart = echarts.init(chartDom)
this.activeAttackData = response.data.result.map(d => { const offenderIpOption = this.$_.cloneDeep(activeAttackBar)
offenderIpOption.series[0].data = data.map(d => {
return [d.count, d.offenderIp] return [d.count, d.offenderIp]
}) }).reverse()
} detectionChart.setOption(offenderIpOption)
}).finally(() => { }).catch(error => {
this.$nextTick(() => {
this.activeAttackOption.series[0].data = this.activeAttackData.reverse()
this.activeAttackOption && detectionChart.setOption(this.activeAttackOption)
})
}) })
}, },
initVictimIp () { initVictimIpData (params) {
const queryParams = { getData(api.detection[this.pageType].victimIp, params).then(data => {
startTime: getSecond(this.timeFilter.startTime), data = [
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionVictimIp, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
victimIp: '1.2.6.8', victimIp: '1.2.6.8',
count: 50 count: 50
@@ -498,72 +424,71 @@ export default {
count: 50 count: 50
} }
] ]
} this.filterData[this.pageType][2].data = data.map(r => ({ label: r.victimIp, value: r.victimIp, count: r.count }))
} const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][2].data)
if (response.data && response.data.result) { this.filterData[this.pageType][2].showMore = showMore
this.filterData[2].data = response.data.result.map(r => ({ label: r.victimIp, value: r.victimIp, count: r.count })) this.filterData[this.pageType][2].showIndex = showIndex
const { showMore, showIndex } = this.computeFilterPage(this.filterData[2].data) }).catch(error => {
this.filterData[2].showMore = showMore
this.filterData[2].showIndex = showIndex
}
}) })
}, },
initVictimLocation () { initVictimLocationData (params) {
const queryParams = { getData(api.detection[this.pageType].victimLocation, params).then(data => {
startTime: getSecond(this.timeFilter.startTime), data = [
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionVictimLocation, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
victimLocationCountry: 'china', victimLocationCountry: 'china',
count: 50 count: 50
} }
] ]
} this.filterData[this.pageType][3].data = data.map(r => ({ label: r.victimLocationCountry, value: r.victimLocationCountry, count: r.count }))
} const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][3].data)
if (response.data && response.data.result) { this.filterData[this.pageType][3].showMore = showMore
this.filterData[3].data = response.data.result.map(r => ({ label: r.victimLocationCountry, value: r.victimLocationCountry, count: r.count })) this.filterData[this.pageType][3].showIndex = showIndex
const { showMore, showIndex } = this.computeFilterPage(this.filterData[3].data) }).catch(error => {
this.filterData[3].showMore = showMore
this.filterData[3].showIndex = showIndex
}
}) })
}, },
initOffenderLocation () { initOffenderLocationData (params) {
const queryParams = { getData(api.detection[this.pageType].offenderLocation, params).then(data => {
startTime: getSecond(this.timeFilter.startTime), data = [
endTime: getSecond(this.timeFilter.endTime),
q: this.q
}
get(api.detectionOffenderLocation, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
offenderLocationCountry: 'china', offenderLocationCountry: 'china',
count: 50 count: 50
} }
] ]
this.filterData[this.pageType][5].data = data.map(r => ({ label: r.offenderLocationCountry, value: r.offenderLocationCountry, count: r.count }))
const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][5].data)
this.filterData[this.pageType][5].showMore = showMore
this.filterData[this.pageType][5].showIndex = showIndex
}).catch(error => {
})
},
initActiveEntity (params) {
getData(api.detection[this.pageType].activeEntity, params).then(data => {
data = [
{
name: 'csdn.net',
count: 250
},
{
name: 'duokan',
count: 150
},
{
name: '2.3.2.2',
count: 50
} }
} ]
if (response.data && response.data.result) { const chartDom = document.getElementById('detectionActiveAttacker')
this.filterData[5].data = response.data.result.map(r => ({ label: r.offenderLocationCountry, value: r.offenderLocationCountry, count: r.count })) const detectionChart = echarts.init(chartDom)
const { showMore, showIndex } = this.computeFilterPage(this.filterData[5].data) const option = this.$_.cloneDeep(activeAttackBar)
this.filterData[5].showMore = showMore option.series[0].data = data.map(d => {
this.filterData[5].showIndex = showIndex return [d.count, d.name]
} }).reverse()
detectionChart.setOption(option)
}).catch(error => {
}) })
}, },
computeFilterPage (data) { computeFilterPage (data) {
@@ -572,19 +497,10 @@ export default {
showIndex: 9 showIndex: 9
} }
}, },
queryList () { queryList (params) {
const queryParams = { getData(api.detection[this.pageType].listBasic, params).then(data => {
...this.timeFilter, if (this.pageType === detectionPageType.securityEvent) {
q: this.q data = [
}
get(api.detectionListBasic, queryParams).then(response => {
response = {
code: 200,
success: true,
msg: 'OK',
data: {
resultType: 'table',
result: [
{ {
eventId: 1212, eventId: 1212,
securityType: 'ddos', securityType: 'ddos',
@@ -592,7 +508,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'critical', eventSecurity: 'critical',
malwareName: 'the great wall', malwareName: 'the great wall',
cryptominingPool: 'a', durationMs: 60000,
startTime: 978456923589 startTime: 978456923589
}, },
{ {
@@ -602,6 +518,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'high', eventSecurity: 'high',
cryptominingPool: 'a', cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -611,6 +528,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'low', eventSecurity: 'low',
malwareName: 'the great wall', malwareName: 'the great wall',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -620,7 +538,17 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'medium', eventSecurity: 'medium',
malwareName: 'the great wall', malwareName: 'the great wall',
durationMs: 60000,
startTime: 1111111111
},
{
eventId: 1212,
securityType: 'ddos',
offenderIp: '1.1.1.1',
victimIp: '2.2.2.2',
eventSecurity: 'info',
cryptominingPool: 'a', cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -630,7 +558,37 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', malwareName: 'the great wall',
durationMs: 600000,
startTime: 1111111111
},
{
eventId: 1212,
securityType: 'ddos',
offenderIp: '1.1.1.1',
victimIp: '2.2.2.2',
eventSecurity: 'info',
cryptominingPool: 'a', cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111
},
{
eventId: 1212,
securityType: 'ddos',
offenderIp: '1.1.1.1',
victimIp: '2.2.2.2',
eventSecurity: 'info',
cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111
},
{
eventId: 1212,
securityType: 'ddos',
offenderIp: '1.1.1.1',
victimIp: '2.2.2.2',
eventSecurity: 'info',
cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -640,7 +598,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', malwareName: 'the great wall',
cryptominingPool: 'a', durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -650,7 +608,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', malwareName: 'the great wall',
cryptominingPool: 'a', durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -660,7 +618,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', malwareName: 'the great wall',
cryptominingPool: 'a', durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -670,7 +628,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', malwareName: 'the great wall',
cryptominingPool: 'a', durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -680,7 +638,7 @@ export default {
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', malwareName: 'the great wall',
cryptominingPool: 'a', durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -689,8 +647,8 @@ export default {
offenderIp: '1.1.1.1', offenderIp: '1.1.1.1',
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall',
cryptominingPool: 'a', cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
@@ -699,57 +657,147 @@ export default {
offenderIp: '1.1.1.1', offenderIp: '1.1.1.1',
victimIp: '2.2.2.2', victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall',
cryptominingPool: 'a', cryptominingPool: 'a',
durationMs: 60000,
startTime: 1111111111
}
]
} else if (this.pageType === detectionPageType.performanceEvent) {
data = [
{
entityType: 'ip',
eventType: 'Dns error',
serverIp: '2.2.2.2',
eventSecurity: 'critical',
durationMs: 60000,
startTime: 978456923589
},
{
entityType: 'ip',
eventType: 'ddos',
serverIp: '2.2.2.2',
eventSecurity: 'high',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
}, },
{ {
eventId: 1212, entityType: 'ip',
securityType: 'ddos', eventType: 'ddos',
offenderIp: '1.1.1.1', serverIp: '2.2.2.2',
victimIp: '2.2.2.2', eventSecurity: 'low',
eventSecurity: 'info', durationMs: 60000,
malwareName: 'the great wall',
cryptominingPool: 'a',
startTime: 1111111111 startTime: 1111111111
}, },
{ {
eventId: 1212, entityType: 'domain',
securityType: 'ddos', eventType: 'ddos',
offenderIp: '1.1.1.1', domain: 'csdn.net',
victimIp: '2.2.2.2', eventSecurity: 'medium',
eventSecurity: 'info', durationMs: 60000,
malwareName: 'the great wall',
cryptominingPool: 'a',
startTime: 1111111111 startTime: 1111111111
}, },
{ {
eventId: 1212, entityType: 'domain',
securityType: 'ddos', eventType: 'ddos',
offenderIp: '1.1.1.1', domain: 'amazon.com',
victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', durationMs: 60000,
cryptominingPool: 'a',
startTime: 1111111111 startTime: 1111111111
}, },
{ {
eventId: 1212, entityType: 'domain',
securityType: 'ddos', eventType: 'ddos',
offenderIp: '1.1.1.1', domain: 'qiniu.com',
victimIp: '2.2.2.2',
eventSecurity: 'info', eventSecurity: 'info',
malwareName: 'the great wall', durationMs: 600000,
cryptominingPool: 'a', startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111
},
{
entityType: 'app',
eventType: 'ddos',
appName: 'Samsung',
eventSecurity: 'info',
durationMs: 60000,
startTime: 1111111111 startTime: 1111111111
} }
] ]
} }
}
if (response.code === 200) { this.listData = data
this.listData = response.data.result }).catch(error => {
}
}) })
}, },
timeRefreshChange () { timeRefreshChange () {
@@ -778,20 +826,29 @@ export default {
this.queryListTotal() this.queryListTotal()
}, },
queryFilter () { queryFilter () {
this.initEventSeverityTrendData() const params = {
this.initSeverityPerData() startTime: getSecond(this.timeFilter.startTime),
this.initCategoryPerData() endTime: getSecond(this.timeFilter.endTime),
this.initActiveAttackData() q: this.q
this.initOffenderLocation() }
this.initVictimIp() this.initEventSeverityTrendData(params)
this.initVictimLocation() this.initEventSeverityData(params)
this.initSecurityTypeData(params)
if (this.pageType === detectionPageType.securityEvent) {
this.initOffenderIpData(params)
this.initOffenderLocationData(params)
this.initVictimIpData(params)
this.initVictimLocationData(params)
} else if (this.pageType === detectionPageType.performanceEvent) {
this.initActiveEntity(params)
}
}, },
queryListTotal () { queryListTotal () {
}, },
filter (filterColumn) { filter (filterColumn) {
const params = {} const params = {}
params[filterColumn] = this.filterData.find(f => { params[filterColumn] = this.filterData[this.pageType].find(f => {
return f.column === filterColumn return f.column === filterColumn
}).value }).value
this.$refs.search.changeParams(params) this.$refs.search.changeParams(params)
@@ -832,65 +889,66 @@ export default {
timeFilter (n) { timeFilter (n) {
this.search(this.metaList, this.q) this.search(this.metaList, this.q)
}, },
'filterData.0.value': { 'filterData.securityEvent.0.value': {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData[0].column, oldValue: o, newValue: n }) this.$refs.search.changeParams({ column: this.filterData.securityEvent[0].column, oldValue: o, newValue: n })
} }
}, },
'filterData.1.value': { 'filterData.securityEvent.1.value': {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData[1].column, oldValue: o, newValue: n }) this.$refs.search.changeParams({ column: this.filterData.securityEvent[1].column, oldValue: o, newValue: n })
} }
}, },
'filterData.2.value': { 'filterData.securityEvent.2.value': {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData[2].column, oldValue: o, newValue: n }) this.$refs.search.changeParams({ column: this.filterData.securityEvent[2].column, oldValue: o, newValue: n })
} }
}, },
'filterData.3.value': { 'filterData.securityEvent.3.value': {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData[3].column, oldValue: o, newValue: n }) this.$refs.search.changeParams({ column: this.filterData.securityEvent[3].column, oldValue: o, newValue: n })
} }
}, },
'filterData.4.value': { 'filterData.securityEvent.4.value': {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData[4].column, oldValue: o, newValue: n }) this.$refs.search.changeParams({ column: this.filterData.securityEvent[4].column, oldValue: o, newValue: n })
} }
}, },
'filterData.5.value': { 'filterData.securityEvent.5.value': {
deep: true, deep: true,
handler (n, o) { handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData[5].column, oldValue: o, newValue: n }) this.$refs.search.changeParams({ column: this.filterData.securityEvent[5].column, oldValue: o, newValue: n })
}
},
'filterData.performanceEvent.0.value': {
deep: true,
handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData.performanceEvent[0].column, oldValue: o, newValue: n })
}
},
'filterData.performanceEvent.1.value': {
deep: true,
handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData.performanceEvent[1].column, oldValue: o, newValue: n })
} }
} }
}, },
setup () { setup () {
const { params } = useRoute()
const pageType = params.typeName
const dateRangeValue = 60 const dateRangeValue = 60
const { startTime, endTime } = getNowTime(dateRangeValue) const { startTime, endTime } = getNowTime(dateRangeValue)
const timeFilter = ref({ startTime, endTime, dateRangeValue }) const timeFilter = ref({ startTime, endTime, dateRangeValue })
return { return {
timeFilter, timeFilter,
severityPerChart: { pageType
params: {
url: '/interface/entity/detail/ip/trafficMap?startTime={{startTime}}&endTime={{endTime}}&country={{country}}&ip={{ip}}',
unitType: 'number'
},
id: 'detectionSeverityPer',
type: 32
},
categoryPerChart: {
params: {
url: '/interface/entity/detail/ip/trafficMap?startTime={{startTime}}&endTime={{endTime}}&country={{country}}&ip={{ip}}',
unitType: 'number'
},
id: 'detectionCategoryPer',
type: 32
}
} }
} }
} }

View File

@@ -0,0 +1,117 @@
<template>
<div class="detection-detail-overview">
<div class="overview__left">
<div class="overview__title">{{$t('overall.remark')}}</div>
<div class="overview__row">
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
</div>
<div class="overview__title">Fields</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.category')}}</div>
<div class="row__content">{{basicInfo.appCategory}}</div>
</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.subcategory')}}</div>
<div class="row__content">{{basicInfo.appSubcategory || '-'}}</div>
</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.riskLevel')}}</div>
<div class="row__content">
<div class="row__tag" :style="`background-color:${eventSeverityColor[basicInfo.appRisk]}`">{{basicInfo.appRisk || '-'}}</div>
</div>
</div>
</div>
<div class="overview__right">
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
<div class="overview__row">
<div class="row__content row__content--link">{{$t('detections.viewDetailOf', {ip: detection.appName})}}</div>
</div>
<div class="overview__title">{{$t('detections.goToHunt')}}</div>
<div class="overview__row">
<div class="row__content row__content--link">{{$t('detections.viewAllRelated')}}</div>
</div>
</div>
</div>
</template>
<script>
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import { eventSeverityColor } from '@/utils/constants'
export default {
name: 'DetectionPerformanceEventAppOverview',
props: {
detection: Object
},
data () {
return {
eventSeverityColor,
basicInfo: {}
}
},
computed: {
computeLocation () {
return function (basicInfo) {
let result = ''
if (basicInfo.serverLocationCountry) {
result += basicInfo.serverLocationCountry
}
if (basicInfo.serverLocationProvince) {
if (result) {
result += ', '
}
result += basicInfo.serverLocationProvince
}
if (basicInfo.serverLocationRegion) {
if (result) {
result += ', '
}
result += basicInfo.serverLocationRegion
}
return result || '-'
}
}
},
methods: {
query () {
this.basicInfo = {
"clientLocationCountry": 1212,
"clientLocationProvince": "112.2.2.3",
"clientLocationRegion": "China",
"clientAsn": "Hebei",
"serverLocationCountry": "Xingtai",
"serverLocationProvince": "hehe",
"serverLocationRegion": "2.2.2.2",
"serverAsn": "China",
"domainCategoryName": "Hebei",
"domainCategoryGroup": "Xingtai",
"domainReputationScore": "hehe",
"domainReputationLevel": "high",
"appCategory": "vpn",
"appSubcategory": "foreign vpn",
"appRisk": "critical"
}
/*this.queryBasic().then(responses => {
})*/
},
queryBasic () {
return new Promise((resolve, reject) => {
try {
get(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.appName }).then(response => {
if (response.code === 200) {
resolve(response.data.list)
} else {
reject(response)
}
})
} catch (e) {
reject(e)
}
})
}
},
mounted () {
this.query()
}
}
</script>

View File

@@ -0,0 +1,121 @@
<template>
<div class="detection-detail-overview">
<div class="overview__left">
<div class="overview__title">{{$t('overall.remark')}}</div>
<div class="overview__row">
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
</div>
<div class="overview__title">Fields</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.category')}}</div>
<div class="row__content">{{basicInfo.domainCategoryName}}</div>
</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.group')}}</div>
<div class="row__content">{{basicInfo.domainCategoryGroup || '-'}}</div>
</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.credit')}}</div>
<div class="row__content">{{basicInfo.domainReputationScore || '-'}}</div>
</div>
<div class="overview__row">
<div class="row__label">{{$t('entities.reputationLevel')}}</div>
<div class="row__content">
<div class="row__tag" :style="`background-color:${eventSeverityColor[basicInfo.domainReputationLevel]}`">{{basicInfo.domainReputationLevel || '-'}}</div>
</div>
</div>
</div>
<div class="overview__right">
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
<div class="overview__row">
<div class="row__content row__content--link">{{$t('detections.viewDetailOf', {ip: detection.domain})}}</div>
</div>
<div class="overview__title">{{$t('detections.goToHunt')}}</div>
<div class="overview__row">
<div class="row__content row__content--link">{{$t('detections.viewAllRelated')}}</div>
</div>
</div>
</div>
</template>
<script>
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import { eventSeverityColor } from '@/utils/constants'
export default {
name: 'DetectionPerformanceEventDomainOverview',
props: {
detection: Object
},
data () {
return {
eventSeverityColor,
basicInfo: {}
}
},
computed: {
computeLocation () {
return function (basicInfo) {
let result = ''
if (basicInfo.serverLocationCountry) {
result += basicInfo.serverLocationCountry
}
if (basicInfo.serverLocationProvince) {
if (result) {
result += ', '
}
result += basicInfo.serverLocationProvince
}
if (basicInfo.serverLocationRegion) {
if (result) {
result += ', '
}
result += basicInfo.serverLocationRegion
}
return result || '-'
}
}
},
methods: {
query () {
this.basicInfo = {
"clientLocationCountry": 1212,
"clientLocationProvince": "112.2.2.3",
"clientLocationRegion": "China",
"clientAsn": "Hebei",
"serverLocationCountry": "Xingtai",
"serverLocationProvince": "hehe",
"serverLocationRegion": "2.2.2.2",
"serverAsn": "China",
"domainCategoryName": "Hebei",
"domainCategoryGroup": "Xingtai",
"domainReputationScore": "hehe",
"domainReputationLevel": "high",
"appCategory": "vpn",
"appSubcategory": "foreign vpn",
"appRisk": "critical"
}
/*this.queryBasic().then(responses => {
})*/
},
queryBasic () {
return new Promise((resolve, reject) => {
try {
get(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.appName }).then(response => {
if (response.code === 200) {
resolve(response.data.list)
} else {
reject(response)
}
})
} catch (e) {
reject(e)
}
})
}
},
mounted () {
this.query()
}
}
</script>

View File

@@ -0,0 +1,106 @@
<template>
<div class="detection-detail-overview">
<div class="overview__left">
<div class="overview__title">{{$t('overall.remark')}}</div>
<div class="overview__row">
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
</div>
<div class="overview__title">Fields</div>
<div class="overview__row">
<div class="row__label">{{$t('overall.location')}}</div>
<div class="row__content">{{computeLocation(basicInfo)}}</div>
</div>
<div class="overview__row">
<div class="row__label">ASN</div>
<div class="row__content">{{basicInfo.serverAsn || '-'}}</div>
</div>
</div>
<div class="overview__right">
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
<div class="overview__row">
<div class="row__content row__content--link">{{$t('detections.viewDetailOf', {ip: detection.serverIp})}}</div>
</div>
<div class="overview__title">{{$t('detections.goToHunt')}}</div>
<div class="overview__row">
<div class="row__content row__content--link">{{$t('detections.viewAllRelated')}}</div>
</div>
</div>
</div>
</template>
<script>
import { api, getData } from '@/utils/api'
export default {
name: 'DetectionPerformanceEventIpOverview',
props: {
detection: Object
},
data () {
return {
basicInfo: {}
}
},
computed: {
computeLocation () {
return function (basicInfo) {
let result = ''
if (basicInfo.serverLocationCountry) {
result += basicInfo.serverLocationCountry
}
if (basicInfo.serverLocationProvince) {
if (result) {
result += ', '
}
result += basicInfo.serverLocationProvince
}
if (basicInfo.serverLocationRegion) {
if (result) {
result += ', '
}
result += basicInfo.serverLocationRegion
}
return result || '-'
}
}
},
methods: {
query () {
this.basicInfo = {
"clientLocationCountry": 1212,
"clientLocationProvince": "112.2.2.3",
"clientLocationRegion": "China",
"clientAsn": "Hebei",
"serverLocationCountry": "Xingtai",
"serverLocationProvince": "hehe",
"serverLocationRegion": "2.2.2.2",
"serverAsn": "China",
"domainCategoryName": "Hebei",
"domainCategoryGroup": "Xingtai",
"domainReputationScore": "hehe",
"domainReputationLevel": "high",
"appCategory": "vpn",
"appSubcategory": "foreign vpn",
"appRisk": "critical"
}
/*this.queryBasic().then(responses => {
})*/
},
queryBasic () {
return new Promise((resolve, reject) => {
try {
getData(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.serverIp }).then(data => {
resolve(data)
}).catch(error => {
reject(error)
})
} catch (e) {
reject(e)
}
})
}
},
mounted () {
this.query()
}
}
</script>

View File

@@ -63,7 +63,7 @@
</template> </template>
<template v-else-if="entityData.entityType === 'domain'"> <template v-else-if="entityData.entityType === 'domain'">
<div class="body__row"> <div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-category"></i>{{$t('entities.Group')}}</span> <span class="body__row-label"><i class="cn-icon cn-icon-category"></i>{{$t('entities.group')}}</span>
<div class="body__row-value" :title="entityData.domainCategoryGroup">{{entityData.domainCategoryGroup || '-'}}</div> <div class="body__row-value" :title="entityData.domainCategoryGroup">{{entityData.domainCategoryGroup || '-'}}</div>
</div> </div>
<div class="body__row"> <div class="body__row">

View File

@@ -20,10 +20,7 @@
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-position"></i> <i class="cn-icon cn-icon-position"></i>
<span>{{$t('overall.region')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('overall.region')}}&nbsp;:&nbsp;&nbsp;</span>
<span v-if="entityData.ipLocationProvince !== 'null' && entityData.ipLocationCity !== 'null'">{{$_.get(entityData, 'ipLocationProvince') + ', ' + $_.get(entityData, 'ipLocationCity') || '-'}}</span> <span>{{ipLocationRegion(entityData)}}</span>
<span v-else-if="entityData.ipLocationProvince !== 'null'">{{$_.get(entityData, 'ipLocationProvince')}}</span>
<span v-else-if="entityData.ipLocationCity !== 'null'">{{$_.get(entityData, 'ipLocationCity')}}</span>
<span v-else>-</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-cloud"></i> <i class="cn-icon cn-icon-cloud"></i>
@@ -128,6 +125,25 @@ export default {
isCollapse: true // 是否是折叠状态 isCollapse: true // 是否是折叠状态
} }
}, },
computed: {
ipLocationRegion () {
return function (entityData) {
const hasProvinceAndCity = entityData.ipLocationProvince && entityData.ipLocationCity &&
entityData.ipLocationProvince !== 'null' && entityData.ipLocationCity !== 'null'
const hasProvince = entityData.ipLocationProvince && entityData.ipLocationProvince !== 'null'
const hasCity = entityData.ipLocationCity && entityData.ipLocationCity !== 'null'
if (hasProvinceAndCity) {
return `${entityData.ipLocationProvince}, ${entityData.ipLocationCity}`
} else if (hasProvince) {
return entityData.ipLocationProvince
} else if (hasCity) {
return entityData.ipLocationCity
} else {
return '-'
}
}
}
},
setup () { setup () {
return { return {
unitConvert, unitConvert,