| 1 | <template> |
| 2 | <div class="flex flex-wrap justify-end gap-2"> |
| 3 | <n-button v-if="socAlertFieldValue" type="success" secondary :size @click.stop="gotoSocAlertUrl()"> |
| 4 | <template #icon> |
| 5 | <Icon :name="ViewIcon" /> |
| 6 | </template> |
| 7 | View SOC Alert |
| 8 | </n-button> |
| 9 | <n-button |
| 10 | v-if="!socAlertFieldValue" |
| 11 | :loading="loadingSocAlert" |
| 12 | type="warning" |
| 13 | secondary |
| 14 | :size |
| 15 | @click.stop="createAlert()" |
| 16 | > |
| 17 | <template #icon> |
| 18 | <Icon :name="DangerIcon" /> |
| 19 | </template> |
| 20 | Create SOC Alert |
| 21 | </n-button> |
| 22 | <n-button v-if="alertAskMessage" type="success" secondary :size @click.stop="showSocResponse = true"> |
| 23 | <template #icon> |
| 24 | <Icon :name="ViewIcon" /> |
| 25 | </template> |
| 26 | View SOCFortress Response |
| 27 | </n-button> |
| 28 | <n-button |
| 29 | v-if="isAskVisible" |
| 30 | :loading="loadingAskSoc" |
| 31 | type="warning" |
| 32 | secondary |
| 33 | :size |
| 34 | @click.stop="askSOCFortress()" |
| 35 | > |
| 36 | <template #icon> |
| 37 | <Icon :name="AskIcon" /> |
| 38 | </template> |
| 39 | Ask SOCFortress |
| 40 | </n-button> |
| 41 | <!-- <n-button |
| 42 | v-if="isWazuhRulesVisible" |
| 43 | :loading="loadingWazuhRuleExclude" |
| 44 | secondary |
| 45 | :size |
| 46 | @click.stop="wazuhManagerRuleExclude()" |
| 47 | > |
| 48 | <template #icon> |
| 49 | <Icon :name="RulesIcon"/> |
| 50 | </template> |
| 51 | Exclude Rule in Wazuh |
| 52 | </n-button> --> |
| 53 | |
| 54 | <n-modal |
| 55 | v-model:show="showSocResponse" |
| 56 | preset="card" |
| 57 | :style="{ maxWidth: 'min(800px, 90vw)', overflow: 'hidden' }" |
| 58 | title="SOCFortress Response" |
| 59 | :bordered="false" |
| 60 | segmented |
| 61 | > |
| 62 | <n-input |
| 63 | :value="alertAskMessage" |
| 64 | type="textarea" |
| 65 | readonly |
| 66 | placeholder="SOCFortress Response" |
| 67 | size="large" |
| 68 | :autosize="{ |
| 69 | minRows: 3 |
| 70 | }" |
| 71 | /> |
| 72 | </n-modal> |
| 73 | |
| 74 | <n-modal |
| 75 | v-model:show="showWazuhRuleExclude" |
| 76 | preset="card" |
| 77 | :style="{ maxWidth: 'min(800px, 90vw)', overflow: 'hidden' }" |
| 78 | title="Recommended exclusion for a Wazuh Rule" |
| 79 | :bordered="false" |
| 80 | content-class="p-0!" |
| 81 | segmented |
| 82 | > |
| 83 | <AlertWazuhRules v-if="wazuhRuleData" :data="wazuhRuleData" /> |
| 84 | </n-modal> |
| 85 | </div> |
| 86 | </template> |
| 87 | |
| 88 | <script setup lang="ts"> |
| 89 | import type { ButtonSize } from "naive-ui" |
| 90 | import type { SocAlertField } from "./type.d" |
| 91 | import type { Alert, WazuhRuleExclude } from "@/types/alerts.d" |
| 92 | import { NButton, NInput, NModal, useMessage } from "naive-ui" |
| 93 | import { computed, onBeforeMount, ref, watch } from "vue" |
| 94 | import { useRouter } from "vue-router" |
| 95 | import Api from "@/api" |
| 96 | import Icon from "@/components/common/Icon.vue" |
| 97 | import AlertWazuhRules from "./AlertWazuhRules.vue" |
| 98 | |
| 99 | const { alert, size, socAlertField } = defineProps<{ |
| 100 | alert: Alert |
| 101 | size?: ButtonSize |
| 102 | socAlertField: SocAlertField |
| 103 | }>() |
| 104 | |
| 105 | const emit = defineEmits<{ |
| 106 | (e: "startLoading"): void |
| 107 | (e: "stopLoading"): void |
| 108 | (e: "updatedUrl", value: string): void |
| 109 | (e: "updatedId", value: number): void |
| 110 | (e: "updatedAskMessage", value: string): void |
| 111 | }>() |
| 112 | |
| 113 | const DangerIcon = "majesticons:exclamation-line" |
| 114 | const AskIcon = "majesticons:question-mark-circle-line" |
| 115 | const ViewIcon = "iconoir:eye-solid" |
| 116 | // const RulesIcon = "carbon:rule-cancelled" |
| 117 | |
| 118 | const router = useRouter() |
| 119 | const message = useMessage() |
| 120 | const showSocResponse = ref(false) |
| 121 | const showWazuhRuleExclude = ref(false) |
| 122 | const loadingSocAlert = ref(false) |
| 123 | const loadingAskSoc = ref(false) |
| 124 | const loadingWazuhRuleExclude = ref(false) |
| 125 | const loading = computed(() => loadingSocAlert.value || loadingAskSoc.value || loadingWazuhRuleExclude.value) |
| 126 | |
| 127 | const alertUrl = ref("") |
| 128 | const alertId = ref(0) |
| 129 | const alertAskMessage = ref("") |
| 130 | const wazuhRuleData = ref<WazuhRuleExclude | null>(null) |
| 131 | |
| 132 | const socAlertFieldValue = computed(() => (socAlertField === "alert_id" ? alertId.value : alertUrl.value)) |
| 133 | |
| 134 | const isAskVisible = computed(() => alert._source?.rule_group3 === "sigma" && !alertAskMessage.value) |
| 135 | // const _isWazuhRulesVisible = computed(() => alert._source) |
| 136 | |
| 137 | watch(loading, val => { |
| 138 | if (val) { |
| 139 | emit("startLoading") |
| 140 | } else { |
| 141 | emit("stopLoading") |
| 142 | } |
| 143 | }) |
| 144 | |
| 145 | watch(alertUrl, val => { |
| 146 | if (val) { |
| 147 | emit("updatedUrl", val) |
| 148 | } |
| 149 | }) |
| 150 | |
| 151 | watch(alertId, val => { |
| 152 | if (val) { |
| 153 | emit("updatedId", val) |
| 154 | } |
| 155 | }) |
| 156 | |
| 157 | watch(alertAskMessage, val => { |
| 158 | if (val) { |
| 159 | emit("updatedAskMessage", val) |
| 160 | } |
| 161 | }) |
| 162 | |
| 163 | function gotoSocAlertUrl() { |
| 164 | if (socAlertField === "alert_url") { |
| 165 | window.open(alertUrl.value, "_blank") |
| 166 | } else if (socAlertField === "alert_id") { |
| 167 | router.push({ name: "IncidentManagement-Alerts", query: alertId.value ? { alert_id: alertId.value } : {} }) |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | function askSOCFortress() { |
| 172 | loadingAskSoc.value = true |
| 173 | |
| 174 | Api.askSocfortress |
| 175 | .create(alert._index, alert._id) |
| 176 | .then(res => { |
| 177 | if (res.data.success) { |
| 178 | res.data.message && (alertAskMessage.value = res.data.message) |
| 179 | message.success("Asked SOCFortress Sigma.") |
| 180 | } else { |
| 181 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 182 | } |
| 183 | }) |
| 184 | .catch(err => { |
| 185 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 186 | }) |
| 187 | .finally(() => { |
| 188 | loadingAskSoc.value = false |
| 189 | }) |
| 190 | } |
| 191 | |
| 192 | /* |
| 193 | function wazuhManagerRuleExclude() { |
| 194 | if (wazuhRuleData.value) { |
| 195 | showWazuhRuleExclude.value = true |
| 196 | return |
| 197 | } |
| 198 | |
| 199 | loadingWazuhRuleExclude.value = true |
| 200 | |
| 201 | Api.wazuh.rules |
| 202 | .wazuhManagerRuleExclude(alert._source) |
| 203 | .then(res => { |
| 204 | if (res.data.success) { |
| 205 | wazuhRuleData.value = { |
| 206 | wazuh_rule: res.data.wazuh_rule, |
| 207 | explanation: res.data.explanation |
| 208 | } |
| 209 | showWazuhRuleExclude.value = true |
| 210 | } else { |
| 211 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 212 | } |
| 213 | }) |
| 214 | .catch(err => { |
| 215 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 216 | }) |
| 217 | .finally(() => { |
| 218 | loadingWazuhRuleExclude.value = false |
| 219 | }) |
| 220 | } |
| 221 | */ |
| 222 | |
| 223 | function createAlert() { |
| 224 | loadingSocAlert.value = true |
| 225 | |
| 226 | Api.alerts |
| 227 | .create(alert._index, alert._id) |
| 228 | .then(res => { |
| 229 | if (res.data.success) { |
| 230 | res.data.alert_url && (alertUrl.value = res.data.alert_url) |
| 231 | res.data.alert_id && (alertId.value = res.data.alert_id) |
| 232 | message.success(res.data?.message || "SOC Alert created.") |
| 233 | } else { |
| 234 | message.warning(res.data?.message || "An error occurred. Please try again later.") |
| 235 | } |
| 236 | }) |
| 237 | .catch(err => { |
| 238 | message.error(err.response?.data?.message || "An error occurred. Please try again later.") |
| 239 | }) |
| 240 | .finally(() => { |
| 241 | loadingSocAlert.value = false |
| 242 | }) |
| 243 | } |
| 244 | |
| 245 | onBeforeMount(() => { |
| 246 | alertUrl.value = alert._source.alert_url || "" |
| 247 | alertId.value = alert._source.alert_id || 0 |
| 248 | alertAskMessage.value = alert._source.ask_socfortress_message || "" |
| 249 | }) |
| 250 | </script> |