mirror of
https://github.com/its-a-feature/Mythic
synced 2026-06-08 14:55:38 +00:00
updates to task and response database tracking
This commit is contained in:
@@ -62,6 +62,7 @@ import {
|
||||
gridValuePassesFilter,
|
||||
isGridColumnFilterActive
|
||||
} from "../../MythicComponents/MythicResizableGrid/GridColumnFilterDialog";
|
||||
import {MythicConfirmDialog} from "../../MythicComponents/MythicConfirmDialog";
|
||||
|
||||
export const getCustomBrowsersQuery = gql(`
|
||||
query getCustomBrowsersQuery{
|
||||
@@ -261,6 +262,7 @@ function CallbacksTablePreMemo(props){
|
||||
const [openContextMenu, setOpenContextMenu] = React.useState(false);
|
||||
const [openHideMultipleDialog, setOpenHideMultipleDialog] = React.useState(false);
|
||||
const [openTriggerDialog, setOpenTriggerDialog] = React.useState({open: false, trigger_on_checkin_after_time: 0, display_id: 0});
|
||||
const [openUnlockDialog, setOpenUnlockDialog] = React.useState({open: false, display_id: 0, lockOwner: ""});
|
||||
const [openTaskMultipleDialog, setOpenTaskMultipleDialog] = React.useState({open: false, data: {}});
|
||||
const [filterOptions, setFilterOptions] = React.useState({});
|
||||
const [selectedColumn, setSelectedColumn] = React.useState({});
|
||||
@@ -388,6 +390,28 @@ function CallbacksTablePreMemo(props){
|
||||
updateTrigger({variables: {callback_display_id: openTriggerDialog.display_id, trigger_on_checkin_after_time: newTriggerValue}})
|
||||
setOpenTriggerDialog({...openTriggerDialog, open: false});
|
||||
}
|
||||
const onOpenTriggerDialog = React.useCallback((callback) => {
|
||||
setOpenTriggerDialog({
|
||||
open: true,
|
||||
trigger_on_checkin_after_time: callback.trigger_on_checkin_after_time,
|
||||
display_id: callback.display_id,
|
||||
});
|
||||
}, []);
|
||||
const onOpenUnlockDialog = React.useCallback((callback) => {
|
||||
setOpenUnlockDialog({
|
||||
open: true,
|
||||
display_id: callback.display_id,
|
||||
lockOwner: callback.locked_operator?.username || "unknown operator",
|
||||
});
|
||||
}, []);
|
||||
const onCloseUnlockDialog = React.useCallback(() => {
|
||||
setOpenUnlockDialog({open: false, display_id: 0, lockOwner: ""});
|
||||
}, []);
|
||||
const onSubmitUnlockDialog = React.useCallback(() => {
|
||||
if(openUnlockDialog.display_id > 0){
|
||||
unlockCallback({variables: {callback_display_id: openUnlockDialog.display_id}});
|
||||
}
|
||||
}, [openUnlockDialog.display_id, unlockCallback]);
|
||||
async function getCustomBrowsersForContextMenu(){
|
||||
return await getCustomBrowsers({}).then(result => {return result.data?.custombrowser});
|
||||
}
|
||||
@@ -521,13 +545,13 @@ function CallbacksTablePreMemo(props){
|
||||
}, type: "item"
|
||||
},
|
||||
{
|
||||
name: rowDataStatic.locked ? 'Unlock (Locked by ' + rowDataStatic.locked_operator.username + ')' : 'Lock Callback',
|
||||
name: rowDataStatic.locked ? 'Unlock (Locked by ' + (rowDataStatic.locked_operator?.username || "unknown operator") + ')' : 'Lock Callback',
|
||||
icon: callbackMenuIcon(rowDataStatic.locked ? <LockIcon fontSize="small"/> : <LockOpenIcon fontSize="small" />, rowDataStatic.locked ? "warning" : "neutral"),
|
||||
className: "mythic-callback-action-menu-item",
|
||||
click: ({event}) => {
|
||||
event.stopPropagation();
|
||||
if(rowDataStatic.locked){
|
||||
unlockCallback({variables: {callback_display_id: rowDataStatic.display_id}})
|
||||
onOpenUnlockDialog(rowDataStatic);
|
||||
}else{
|
||||
lockCallback({variables: {callback_display_id: rowDataStatic.display_id}})
|
||||
}
|
||||
@@ -540,7 +564,7 @@ function CallbacksTablePreMemo(props){
|
||||
className: "mythic-callback-action-menu-item",
|
||||
click: ({event}) => {
|
||||
event.stopPropagation();
|
||||
setOpenTriggerDialog({open: true, trigger_on_checkin_after_time: rowDataStatic.trigger_on_checkin_after_time, display_id: rowDataStatic.display_id})
|
||||
onOpenTriggerDialog(rowDataStatic);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -894,6 +918,8 @@ function CallbacksTablePreMemo(props){
|
||||
}}
|
||||
key={`callback${row.id}_${c.name}`}
|
||||
callbackDropdown={callbackDropdown}
|
||||
onOpenTriggerDialog={onOpenTriggerDialog}
|
||||
onOpenUnlockDialog={onOpenUnlockDialog}
|
||||
/>;
|
||||
case "Groups":
|
||||
return <CallbacksTableStringCell
|
||||
@@ -1008,7 +1034,7 @@ function CallbacksTablePreMemo(props){
|
||||
})];
|
||||
}
|
||||
}, [])
|
||||
}, [callbacks, callbackLocalUpdates, sortData, filterOptions, columnVisibility, clickedCallbackID]);
|
||||
}, [callbacks, callbackLocalUpdates, sortData, filterOptions, columnVisibility, clickedCallbackID, onOpenTriggerDialog, onOpenUnlockDialog]);
|
||||
const onSubmitFilterOptions = (value) => {
|
||||
const nextFilterOptions = getUpdatedGridFilterOptions(filterOptions, selectedColumn.key, value);
|
||||
setFilterOptions(nextFilterOptions);
|
||||
@@ -1217,6 +1243,17 @@ function CallbacksTablePreMemo(props){
|
||||
}
|
||||
/>
|
||||
}
|
||||
{openUnlockDialog.open &&
|
||||
<MythicConfirmDialog
|
||||
open={openUnlockDialog.open}
|
||||
title={"Unlock Callback?"}
|
||||
dialogText={`Unlock callback ${openUnlockDialog.display_id} currently locked by ${openUnlockDialog.lockOwner}?`}
|
||||
acceptText={"Unlock"}
|
||||
acceptColor={"warning"}
|
||||
onClose={onCloseUnlockDialog}
|
||||
onSubmit={onSubmitUnlockDialog}
|
||||
/>
|
||||
}
|
||||
{openReorderDialog &&
|
||||
<MythicDialog fullWidth={true} maxWidth="sm" open={openReorderDialog}
|
||||
onClose={()=>{setOpenReorderDialog(false);}}
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import {useMutation } from '@apollo/client';
|
||||
import SnoozeIcon from '@mui/icons-material/Snooze';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import {faQuestion, faSkullCrossbones, faRobot} from '@fortawesome/free-solid-svg-icons';
|
||||
import {faQuestion, faRobot} from '@fortawesome/free-solid-svg-icons';
|
||||
import {faLinux, faApple, faWindows, faChrome, faAndroid} from '@fortawesome/free-brands-svg-icons';
|
||||
import { MythicStyledTooltip } from '../../MythicComponents/MythicStyledTooltip';
|
||||
import { MythicSelectFromRawListDialog } from '../../MythicComponents/MythicSelectFromListDialog';
|
||||
@@ -29,10 +29,11 @@ import {GetMythicSetting} from "../../MythicComponents/MythicSavedUserSetting";
|
||||
import TerminalIcon from '@mui/icons-material/Terminal';
|
||||
import VerticalSplitIcon from '@mui/icons-material/VerticalSplit';
|
||||
import NotificationsActiveTwoToneIcon from '@mui/icons-material/NotificationsActiveTwoTone';
|
||||
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
|
||||
import {faSocks} from '@fortawesome/free-solid-svg-icons';
|
||||
import {TagsDisplay, ViewEditTags} from "../../MythicComponents/MythicTag";
|
||||
|
||||
export const CallbacksTableIDCell = React.memo(({rowData, callbackDropdown}) =>{
|
||||
export const CallbacksTableIDCell = React.memo(({rowData, callbackDropdown, onOpenTriggerDialog, onOpenUnlockDialog}) =>{
|
||||
const dropdownAnchorRef = React.useRef(null);
|
||||
const onOpenTab = useContext(OnOpenTabContext);
|
||||
const interactType = GetMythicSetting({setting_name: "interactType", default_value: "interact"})
|
||||
@@ -99,6 +100,14 @@ export const CallbacksTableIDCell = React.memo(({rowData, callbackDropdown}) =>{
|
||||
event.stopPropagation();
|
||||
callbackDropdown({rowDataStatic, event});
|
||||
};
|
||||
const handleOpenTriggerDialog = (event) => {
|
||||
event.stopPropagation();
|
||||
onOpenTriggerDialog?.(rowDataStatic);
|
||||
};
|
||||
const handleOpenUnlockDialog = (event) => {
|
||||
event.stopPropagation();
|
||||
onOpenUnlockDialog?.(rowDataStatic);
|
||||
};
|
||||
const localOnOpenTab = () => {
|
||||
onOpenTab({tabType: interactType, tabID: rowDataStatic.id + interactType, callbackID: rowDataStatic.id, displayID: rowDataStatic.display_id});
|
||||
}
|
||||
@@ -132,16 +141,22 @@ export const CallbacksTableIDCell = React.memo(({rowData, callbackDropdown}) =>{
|
||||
</IconButton>
|
||||
{rowDataStatic.locked &&
|
||||
<MythicStyledTooltip title={`Locked by ${lockOwner}`}>
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeLock">
|
||||
<button type="button"
|
||||
className="mythic-callback-statusBadge mythic-callback-statusBadgeButton mythic-callback-statusBadgeLock"
|
||||
aria-label={`Unlock callback ${rowDataStatic.display_id}`}
|
||||
onClick={handleOpenUnlockDialog}>
|
||||
<LockIcon fontSize="inherit" />
|
||||
</span>
|
||||
</button>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
{rowDataStatic.trigger_on_checkin_after_time > 0 &&
|
||||
<MythicStyledTooltip title={`Alert on callback after no checkin for ${rowDataStatic.trigger_on_checkin_after_time} minutes`}>
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeAlert">
|
||||
<button type="button"
|
||||
className="mythic-callback-statusBadge mythic-callback-statusBadgeButton mythic-callback-statusBadgeAlert"
|
||||
aria-label={`Adjust alert trigger for callback ${rowDataStatic.display_id}`}
|
||||
onClick={handleOpenTriggerDialog}>
|
||||
<NotificationsActiveTwoToneIcon fontSize="inherit" />
|
||||
</span>
|
||||
</button>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
{rowDataStatic.callbackports.length > 0 &&
|
||||
@@ -179,7 +194,7 @@ export const CallbacksTableLastCheckinCell = React.memo( ({rowData, cellData, me
|
||||
{rowData.dead &&
|
||||
<MythicStyledTooltip title={"Based on callback's last checkin and sleep info, it's likely dead"}>
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeDead">
|
||||
<FontAwesomeIcon icon={faSkullCrossbones} />
|
||||
<WarningAmberIcon fontSize="inherit" />
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
@@ -193,7 +208,7 @@ export const CallbacksTableLastCheckinCell = React.memo( ({rowData, cellData, me
|
||||
{rowData.dead &&
|
||||
<MythicStyledTooltip title={"Based on callback's last checkin and sleep info, it's likely dead"}>
|
||||
<span className="mythic-callback-statusBadge mythic-callback-statusBadgeDead">
|
||||
<FontAwesomeIcon icon={faSkullCrossbones} />
|
||||
<WarningAmberIcon fontSize="inherit" />
|
||||
</span>
|
||||
</MythicStyledTooltip>
|
||||
}
|
||||
@@ -493,7 +508,7 @@ export const CallbacksTableSleepCell = React.memo( ({rowData, cellData, updateSl
|
||||
<div className="mythic-callback-cellInline mythic-callback-cellInlineCenter">
|
||||
<MythicStyledTooltip title={cellData === "" ? "No sleep information set" : "View or edit sleep information"}>
|
||||
<IconButton
|
||||
className={`mythic-callback-iconButton mythic-callback-cellIconButton ${cellData === "" ? "mythic-callback-cellIconButtonWarning" : "mythic-callback-cellIconButtonInfo"}`}
|
||||
className={`mythic-callback-iconButton mythic-callback-cellIconButton ${cellData === "" ? "mythic-callback-cellIconButtonHoverWarning" : "mythic-callback-cellIconButtonHoverInfo"}`}
|
||||
onClick={onOpenSleepDialog}
|
||||
>
|
||||
<SnoozeIcon fontSize="small" />
|
||||
|
||||
@@ -111,9 +111,6 @@ function CallbackSearchTableRow(props){
|
||||
label={props.active ? "Active" : "Inactive"}
|
||||
status={props.active ? "active" : "inactive"}
|
||||
/>
|
||||
{props.dead &&
|
||||
<MythicStatusChip label="Likely dead" status="warning" />
|
||||
}
|
||||
{props.locked &&
|
||||
<MythicStatusChip label="Locked" status="locked" />
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import {MythicPageHeader, MythicPageHeaderChip} from "../../MythicComponents/Myt
|
||||
export function Search(props){
|
||||
|
||||
const navigate = useNavigate();
|
||||
const tabTypes = ["callbacks", "tasks", "payloads", "files", "credentials", "keylogs", "artifacts", "tokens", "socks", "processes", "tags", "browsers"];
|
||||
const tabTypes = ["callbacks", "tasks", "payloads", "files", "credentials", "keylogs", "artifacts", "tokens", "proxies", "processes", "tags", "browsers"];
|
||||
const tabLabels = {
|
||||
artifacts: "Artifacts",
|
||||
browsers: "Browser scripts",
|
||||
@@ -30,7 +30,7 @@ export function Search(props){
|
||||
keylogs: "Keylogs",
|
||||
payloads: "Payloads",
|
||||
processes: "Processes",
|
||||
socks: "SOCKS",
|
||||
proxies: "proxies",
|
||||
tags: "Tags",
|
||||
tasks: "Tasks",
|
||||
tokens: "Tokens",
|
||||
@@ -70,8 +70,8 @@ export function Search(props){
|
||||
return <SearchTabTokensPanel key={"tokenspanel"} index={value} me={props.me} value={value} changeSearchParam={changeSearchParam} />
|
||||
case "artifacts":
|
||||
return <SearchTabArtifactsPanel key={"artifactspanel"} index={value} me={props.me} value={value} changeSearchParam={changeSearchParam} />
|
||||
case "socks":
|
||||
return <SearchTabSocksPanel key={"sockspanel"} index={value} me={props.me} value={value} changeSearchParam={changeSearchParam} />
|
||||
case "proxies":
|
||||
return <SearchTabSocksPanel key={"proxiespanel"} index={value} me={props.me} value={value} changeSearchParam={changeSearchParam} />
|
||||
case "processes":
|
||||
return <SearchTabProcessPanel key={"processpanel"} index={value} me={props.me} value={value} changeSearchParam={changeSearchParam} />
|
||||
case "tags":
|
||||
@@ -133,7 +133,7 @@ export function Search(props){
|
||||
return <SearchTabCallbacksLabel key={"callbackstab"} me={props.me}/>;
|
||||
case "artifacts":
|
||||
return <SearchTabArtifactsLabel key={"artifactstab"} me={props.me}/>;
|
||||
case "socks":
|
||||
case "proxies":
|
||||
return <SearchTabSocksLabel key={"sockstab"} me={props.me}/>;
|
||||
case "processes":
|
||||
return <SearchTabProcessesLabel key={"processtab"} me={props.me}/>;
|
||||
|
||||
@@ -47,7 +47,7 @@ subscription portsSub{
|
||||
|
||||
export function SearchTabSocksLabel(props){
|
||||
return (
|
||||
<MythicSearchTabLabel label={"PROXIES"} iconComponent={
|
||||
<MythicSearchTabLabel label={"Proxies"} iconComponent={
|
||||
<FontAwesomeIcon icon={faSocks} size="lg" style={{marginTop: "4px", marginBottom: "5px"}}/>} {...props}/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -877,6 +877,16 @@ tspan {
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonHoverInfo.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.info.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonHoverWarning.MuiIconButton-root:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-cellIconButtonError.MuiIconButton-root {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
@@ -917,55 +927,50 @@ tspan {
|
||||
}
|
||||
.mythic-callback-statusBadge {
|
||||
align-items: center;
|
||||
appearance: none;
|
||||
background-color: ${(props) => props.theme.palette.mode === "dark" ? "rgba(255,255,255,0.045)" : "rgba(0,0,0,0.025)"};
|
||||
border: 1px solid ${(props) => props.theme.table?.borderSoft || props.theme.borderColor};
|
||||
border-radius: ${(props) => props.theme.shape.borderRadius}px;
|
||||
box-sizing: border-box;
|
||||
color: ${(props) => props.theme.palette.text.secondary};
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
font-size: 0.82rem;
|
||||
font-family: inherit;
|
||||
height: 20px;
|
||||
justify-content: center;
|
||||
line-height: 1;
|
||||
margin-left: 0.08rem;
|
||||
padding: 0;
|
||||
transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
|
||||
width: 22px;
|
||||
}
|
||||
.mythic-callback-statusBadgeAlert {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.14 : 0.08)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.36 : 0.24)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
.mythic-callback-statusBadgeButton {
|
||||
cursor: pointer;
|
||||
}
|
||||
.mythic-callback-statusBadgeProxy {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.info.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeLock {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeDead {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.12 : 0.07)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.32 : 0.2)};
|
||||
color: ${(props) => props.theme.palette.error.main};
|
||||
.mythic-callback-statusBadgeButton:focus-visible {
|
||||
outline: 2px solid ${(props) => alpha(props.theme.palette.primary.main, 0.55)};
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.mythic-callback-statusBadgeAlert:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.22 : 0.13)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.58 : 0.42)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeProxy:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
color: ${(props) => props.theme.palette.info.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeLock:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.info.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.22 : 0.13)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.58 : 0.42)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-statusBadgeDead:hover {
|
||||
background-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.2 : 0.12)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.error.main, props.theme.palette.mode === "dark" ? 0.54 : 0.36)};
|
||||
background-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.22 : 0.13)};
|
||||
border-color: ${(props) => alpha(props.theme.palette.warning.main, props.theme.palette.mode === "dark" ? 0.58 : 0.42)};
|
||||
color: ${(props) => props.theme.palette.warning.main};
|
||||
}
|
||||
.mythic-callback-statusBadge svg {
|
||||
display: block;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
From grafana/grafana
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
{{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ if gt (.Alerts.Resolved | len) 0 }}, RESOLVED:{{ .Alerts.Resolved | len }}{{ end }}{{ end }}] {{ .GroupLabels.SortedPairs.Values | join " " }} {{ if gt (len .CommonLabels) (len .GroupLabels) }}({{ with .CommonLabels.Remove .GroupLabels.Names }}{{ .Values | join " " }}{{ end }}){{ end }}{{ end }}
|
||||
|
||||
{{ define "__text_values_list" }}{{ $len := len .Values }}{{ if $len }}{{ $first := gt $len 1 }}{{ range $refID, $value := .Values -}}
|
||||
{{ $refID }}={{ $value }}{{ if $first }}, {{ end }}{{ $first = false }}{{ end -}}
|
||||
{{ else }}[no value]{{ end }}{{ end }}
|
||||
|
||||
{{ define "__text_alert_list" }}{{ range . }}
|
||||
Value: {{ template "__text_values_list" . }}
|
||||
Labels:
|
||||
{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||
{{ end }}Annotations:
|
||||
{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||
{{ end }}{{ if gt (len .GeneratorURL) 0 }}Source: {{ .GeneratorURL }}
|
||||
{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: {{ .SilenceURL }}
|
||||
{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: {{ .DashboardURL }}
|
||||
{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: {{ .PanelURL }}
|
||||
{{ end }}{{ end }}{{ end }}
|
||||
|
||||
{{ define "default.title" }}{{ template "__subject" . }}{{ end }}
|
||||
|
||||
{{ define "default.message" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing**
|
||||
{{ template "__text_alert_list" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }}
|
||||
|
||||
{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved**
|
||||
{{ template "__text_alert_list" .Alerts.Resolved }}{{ end }}{{ end }}
|
||||
|
||||
|
||||
{{ define "__teams_text_alert_list" }}{{ range . }}
|
||||
Value: {{ template "__text_values_list" . }}
|
||||
Labels:
|
||||
{{ range .Labels.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||
{{ end }}
|
||||
Annotations:
|
||||
{{ range .Annotations.SortedPairs }} - {{ .Name }} = {{ .Value }}
|
||||
{{ end }}
|
||||
{{ if gt (len .GeneratorURL) 0 }}Source: [{{ .GeneratorURL }}]({{ .GeneratorURL }})
|
||||
|
||||
{{ end }}{{ if gt (len .SilenceURL) 0 }}Silence: [{{ .SilenceURL }}]({{ .SilenceURL }})
|
||||
|
||||
{{ end }}{{ if gt (len .DashboardURL) 0 }}Dashboard: [{{ .DashboardURL }}]({{ .DashboardURL }})
|
||||
|
||||
{{ end }}{{ if gt (len .PanelURL) 0 }}Panel: [{{ .PanelURL }}]({{ .PanelURL }})
|
||||
|
||||
{{ end }}
|
||||
{{ end }}{{ end }}
|
||||
|
||||
|
||||
{{ define "teams.default.message" }}{{ if gt (len .Alerts.Firing) 0 }}**Firing**
|
||||
{{ template "__teams_text_alert_list" .Alerts.Firing }}{{ if gt (len .Alerts.Resolved) 0 }}
|
||||
|
||||
{{ end }}{{ end }}{{ if gt (len .Alerts.Resolved) 0 }}**Resolved**
|
||||
{{ template "__teams_text_alert_list" .Alerts.Resolved }}{{ end }}{{ end }}
|
||||
Binary file not shown.
@@ -110,6 +110,14 @@ type Mutation {
|
||||
): createArtifactOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createC2Instance(
|
||||
c2_instance: String!
|
||||
instance_name: String!
|
||||
c2profile_id: Int!
|
||||
): createc2instanceOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createCallback(
|
||||
newCallback: newCallbackConfig
|
||||
@@ -206,14 +214,6 @@ type Mutation {
|
||||
): createTaskOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createC2Instance(
|
||||
c2_instance: String!
|
||||
instance_name: String!
|
||||
c2profile_id: Int!
|
||||
): createc2instanceOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
custombrowserExportFunction(
|
||||
tree_type: String!
|
||||
@@ -415,6 +415,14 @@ type Query {
|
||||
): ProfileOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
importC2Instance(
|
||||
c2_instance: jsonb!
|
||||
instance_name: String!
|
||||
c2profile_name: String!
|
||||
): createc2instanceOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
importCallbackConfig(
|
||||
config: jsonb!
|
||||
@@ -427,14 +435,6 @@ type Mutation {
|
||||
): importTagtypesOutput
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
importC2Instance(
|
||||
c2_instance: jsonb!
|
||||
instance_name: String!
|
||||
c2profile_name: String!
|
||||
): createc2instanceOutput
|
||||
}
|
||||
|
||||
type Query {
|
||||
meHook: meHookOutput
|
||||
}
|
||||
@@ -1324,3 +1324,4 @@ type custombrowserExportFunctionOutput {
|
||||
status: String!
|
||||
error: String
|
||||
}
|
||||
|
||||
|
||||
@@ -181,6 +181,17 @@ actions:
|
||||
- role: mythic_admin
|
||||
- role: developer
|
||||
comment: Generate an artifact and optionally associate it with a specific task by its task ID
|
||||
- name: createC2Instance
|
||||
definition:
|
||||
kind: synchronous
|
||||
handler: '{{MYTHIC_ACTIONS_URL_BASE}}/create_c2parameter_instance_webhook'
|
||||
forward_client_headers: true
|
||||
permissions:
|
||||
- role: operator
|
||||
- role: operation_admin
|
||||
- role: mythic_admin
|
||||
- role: developer
|
||||
comment: Creates a new saved instance of a C2 Profile with a given name
|
||||
- name: createCallback
|
||||
definition:
|
||||
kind: synchronous
|
||||
@@ -292,17 +303,6 @@ actions:
|
||||
- role: operation_admin
|
||||
- role: operator
|
||||
comment: Creates a new task in Mythic for the specified callback_display_id or callback_display_ids
|
||||
- name: createC2Instance
|
||||
definition:
|
||||
kind: synchronous
|
||||
handler: '{{MYTHIC_ACTIONS_URL_BASE}}/create_c2parameter_instance_webhook'
|
||||
forward_client_headers: true
|
||||
permissions:
|
||||
- role: operator
|
||||
- role: operation_admin
|
||||
- role: mythic_admin
|
||||
- role: developer
|
||||
comment: Creates a new saved instance of a C2 Profile with a given name
|
||||
- name: custombrowserExportFunction
|
||||
definition:
|
||||
kind: synchronous
|
||||
@@ -613,6 +613,16 @@ actions:
|
||||
- role: mythic_admin
|
||||
- role: operation_admin
|
||||
- role: operator
|
||||
- name: importC2Instance
|
||||
definition:
|
||||
kind: synchronous
|
||||
handler: '{{MYTHIC_ACTIONS_URL_BASE}}/import_c2parameter_instance_webhook'
|
||||
forward_client_headers: true
|
||||
permissions:
|
||||
- role: operator
|
||||
- role: operation_admin
|
||||
- role: mythic_admin
|
||||
- role: developer
|
||||
- name: importCallbackConfig
|
||||
definition:
|
||||
kind: synchronous
|
||||
@@ -633,16 +643,6 @@ actions:
|
||||
- role: operation_admin
|
||||
- role: mythic_admin
|
||||
- role: developer
|
||||
- name: importC2Instance
|
||||
definition:
|
||||
kind: synchronous
|
||||
handler: '{{MYTHIC_ACTIONS_URL_BASE}}/import_c2parameter_instance_webhook'
|
||||
forward_client_headers: true
|
||||
permissions:
|
||||
- role: operator
|
||||
- role: operation_admin
|
||||
- role: mythic_admin
|
||||
- role: developer
|
||||
- name: meHook
|
||||
definition:
|
||||
kind: ""
|
||||
|
||||
@@ -183,10 +183,10 @@ select_permissions:
|
||||
filter:
|
||||
_and:
|
||||
- _or:
|
||||
- created_by:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
- created_by:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator_id:
|
||||
_lte: X-Hasura-Scope-apitoken-read-operator
|
||||
- role: operator
|
||||
@@ -251,13 +251,13 @@ update_permissions:
|
||||
filter:
|
||||
_and:
|
||||
- _or:
|
||||
- created_by:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator:
|
||||
account_type:
|
||||
_eq: bot
|
||||
- created_by:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator:
|
||||
account_type:
|
||||
_eq: bot
|
||||
- operator_id:
|
||||
_lte: X-Hasura-Scope-apitoken-write-operator
|
||||
check: null
|
||||
|
||||
@@ -11,14 +11,6 @@ object_relationships:
|
||||
- name: payloadtype
|
||||
using:
|
||||
foreign_key_constraint_on: payload_type_id
|
||||
array_relationships:
|
||||
- name: browserscriptoperations
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: browserscript_id
|
||||
table:
|
||||
name: browserscriptoperation
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: mythic_admin
|
||||
permission:
|
||||
@@ -81,9 +73,9 @@ select_permissions:
|
||||
filter:
|
||||
_and:
|
||||
- operator_id:
|
||||
_eq: X-Hasura-User-Id
|
||||
_eq: X-Hasura-User-Id
|
||||
- operator_id:
|
||||
_lte: X-Hasura-Scope-operator-read-operator
|
||||
_lte: X-Hasura-Scope-operator-read-operator
|
||||
- role: operation_admin
|
||||
permission:
|
||||
columns:
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
table:
|
||||
name: browserscriptoperation
|
||||
schema: public
|
||||
object_relationships:
|
||||
- name: browserscript
|
||||
using:
|
||||
foreign_key_constraint_on: browserscript_id
|
||||
- name: operation
|
||||
using:
|
||||
foreign_key_constraint_on: operation_id
|
||||
@@ -70,7 +70,6 @@ select_permissions:
|
||||
- updated_at
|
||||
filter: {}
|
||||
comment: ""
|
||||
|
||||
update_permissions:
|
||||
- role: mythic_admin
|
||||
permission:
|
||||
|
||||
+8
-8
@@ -22,10 +22,10 @@ select_permissions:
|
||||
_and:
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_eq: x-hasura-current-operation-id
|
||||
_eq: x-hasura-current-operation-id
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
comment: ""
|
||||
- role: operation_admin
|
||||
permission:
|
||||
@@ -40,10 +40,10 @@ select_permissions:
|
||||
_and:
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_eq: x-hasura-current-operation-id
|
||||
_eq: x-hasura-current-operation-id
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
comment: ""
|
||||
- role: operator
|
||||
permission:
|
||||
@@ -58,10 +58,10 @@ select_permissions:
|
||||
_and:
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_eq: x-hasura-current-operation-id
|
||||
_eq: x-hasura-current-operation-id
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
comment: ""
|
||||
- role: spectator
|
||||
permission:
|
||||
@@ -76,8 +76,8 @@ select_permissions:
|
||||
_and:
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_eq: x-hasura-current-operation-id
|
||||
_eq: x-hasura-current-operation-id
|
||||
- eventgroup:
|
||||
operation_id:
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
_lte: x-hasura-scope-eventing-read-operation
|
||||
comment: ""
|
||||
|
||||
@@ -20,11 +20,11 @@ insert_permissions:
|
||||
check:
|
||||
_and:
|
||||
- callback:
|
||||
operation_id:
|
||||
_eq: X-Hasura-current-operation-id
|
||||
operation_id:
|
||||
_eq: X-Hasura-current-operation-id
|
||||
- callback:
|
||||
operation_id:
|
||||
_lte: X-Hasura-Scope-callback-write-operation
|
||||
operation_id:
|
||||
_lte: X-Hasura-Scope-callback-write-operation
|
||||
set:
|
||||
operator_id: x-hasura-user-id
|
||||
columns:
|
||||
@@ -36,11 +36,11 @@ insert_permissions:
|
||||
check:
|
||||
_and:
|
||||
- callback:
|
||||
operation_id:
|
||||
_eq: X-Hasura-current-operation-id
|
||||
operation_id:
|
||||
_eq: X-Hasura-current-operation-id
|
||||
- callback:
|
||||
operation_id:
|
||||
_lte: X-Hasura-Scope-callback-write-operation
|
||||
_lte: X-Hasura-Scope-callback-write-operation
|
||||
set:
|
||||
operator_id: x-hasura-user-id
|
||||
columns:
|
||||
|
||||
@@ -9,13 +9,6 @@ object_relationships:
|
||||
using:
|
||||
foreign_key_constraint_on: apitokens_id
|
||||
array_relationships:
|
||||
- name: browserscriptoperations
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: operation_id
|
||||
table:
|
||||
name: browserscriptoperation
|
||||
schema: public
|
||||
- name: c2profileparametersinstances
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
|
||||
@@ -151,4 +151,4 @@ select_permissions:
|
||||
callback:
|
||||
operation_id:
|
||||
_lte: X-Hasura-Scope-response-read-operation
|
||||
allow_aggregations: true
|
||||
allow_aggregations: true
|
||||
|
||||
@@ -318,7 +318,6 @@ update_permissions:
|
||||
- operation_id:
|
||||
_lte: X-Hasura-Scope-tag-write-operation
|
||||
delete_permissions:
|
||||
|
||||
- role: mythic_admin
|
||||
permission:
|
||||
filter:
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
- "!include public_attackcommand.yaml"
|
||||
- "!include public_attacktask.yaml"
|
||||
- "!include public_browserscript.yaml"
|
||||
- "!include public_browserscriptoperation.yaml"
|
||||
- "!include public_buildparameter.yaml"
|
||||
- "!include public_buildparameterinstance.yaml"
|
||||
- "!include public_c2profile.yaml"
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
var DB *sqlx.DB
|
||||
var currentMigrationVersion int64 = 3003019
|
||||
var currentMigrationVersion int64 = 3003020
|
||||
|
||||
// initial structs made with './tables-to-go -u mythic_user -p [password here] -h [ip here] -v -d mythic_db -of output -pn database_structs'
|
||||
// package pulled from https://github.com/fraenky8/tables-to-go
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
-- SQL in section 'Up' is executed when this migration is applied
|
||||
|
||||
alter table "public"."apitokens" add column IF NOT EXISTS "scopes" text[] not null default '{}'::text[];
|
||||
drop table IF EXISTS "public"."browserscriptoperation";
|
||||
|
||||
-- +migrate Down
|
||||
-- SQL in section 'Down' is executed when this migration is rolled back
|
||||
@@ -0,0 +1,170 @@
|
||||
-- +migrate Up
|
||||
-- SQL in section 'Up' is executed when this migration is applied
|
||||
|
||||
create table if not exists "public"."operation_display_counters" (
|
||||
operation_id integer primary key references "public"."operation"(id) on delete cascade,
|
||||
last_task_display_id integer not null default 0,
|
||||
last_callback_display_id integer not null default 0
|
||||
);
|
||||
|
||||
insert into "public"."operation_display_counters" (
|
||||
operation_id,
|
||||
last_task_display_id,
|
||||
last_callback_display_id
|
||||
)
|
||||
select
|
||||
op.id,
|
||||
coalesce((select max(display_id) from "public"."task" where operation_id = op.id), 0),
|
||||
coalesce((select max(display_id) from "public"."callback" where operation_id = op.id), 0)
|
||||
from "public"."operation" op
|
||||
on conflict (operation_id) do update
|
||||
set
|
||||
last_task_display_id = greatest(
|
||||
"public"."operation_display_counters".last_task_display_id,
|
||||
excluded.last_task_display_id
|
||||
),
|
||||
last_callback_display_id = greatest(
|
||||
"public"."operation_display_counters".last_callback_display_id,
|
||||
excluded.last_callback_display_id
|
||||
);
|
||||
|
||||
do $$
|
||||
begin
|
||||
if exists (
|
||||
select 1
|
||||
from "public"."task"
|
||||
group by operation_id, display_id
|
||||
having count(*) > 1
|
||||
) then
|
||||
raise exception 'Cannot add task(operation_id, display_id) uniqueness because duplicate task display IDs already exist';
|
||||
end if;
|
||||
|
||||
if exists (
|
||||
select 1
|
||||
from "public"."callback"
|
||||
group by operation_id, display_id
|
||||
having count(*) > 1
|
||||
) then
|
||||
raise exception 'Cannot add callback(operation_id, display_id) uniqueness because duplicate callback display IDs already exist';
|
||||
end if;
|
||||
end $$;
|
||||
|
||||
create unique index if not exists task_operation_display_id_unique
|
||||
on "public"."task" using btree (operation_id, display_id);
|
||||
|
||||
create unique index if not exists callback_operation_display_id_unique
|
||||
on "public"."callback" using btree (operation_id, display_id);
|
||||
|
||||
create or replace function public.new_task_display_id() returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
insert into "public"."operation_display_counters" (operation_id)
|
||||
values (new.operation_id)
|
||||
on conflict (operation_id) do nothing;
|
||||
|
||||
update "public"."operation_display_counters"
|
||||
set last_task_display_id = last_task_display_id + 1
|
||||
where operation_id = new.operation_id
|
||||
returning last_task_display_id into new.display_id;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function public.new_callback_display_id() returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
insert into "public"."operation_display_counters" (operation_id)
|
||||
values (new.operation_id)
|
||||
on conflict (operation_id) do nothing;
|
||||
|
||||
update "public"."operation_display_counters"
|
||||
set last_callback_display_id = last_callback_display_id + 1
|
||||
where operation_id = new.operation_id
|
||||
returning last_callback_display_id into new.display_id;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
update "public"."task"
|
||||
set response_count = response_counts.total
|
||||
from (
|
||||
select
|
||||
task.id,
|
||||
count(response.id)::integer as total
|
||||
from "public"."task"
|
||||
left join "public"."response" on response.task_id = task.id
|
||||
group by task.id
|
||||
) response_counts
|
||||
where task.id = response_counts.id
|
||||
and task.response_count is distinct from response_counts.total;
|
||||
|
||||
create or replace function public.update_task_response_count() returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
update "public"."task"
|
||||
set response_count = response_count + 1
|
||||
where id = new.task_id;
|
||||
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
-- +migrate Down
|
||||
-- SQL in section 'Down' is executed when this migration is rolled back
|
||||
|
||||
create or replace function public.update_task_response_count() returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
declare
|
||||
current_max integer;
|
||||
begin
|
||||
select count(*)
|
||||
into current_max
|
||||
from response
|
||||
where task_id = new.task_id;
|
||||
|
||||
update task set response_count = current_max where id = new.task_id;
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function public.new_callback_display_id() returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
declare
|
||||
current_max integer;
|
||||
begin
|
||||
select greatest(0, max(display_id))
|
||||
into current_max
|
||||
from callback
|
||||
where operation_id = new.operation_id;
|
||||
|
||||
new.display_id := current_max + 1;
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function public.new_task_display_id() returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
declare
|
||||
current_max integer;
|
||||
begin
|
||||
select greatest(0, max(display_id))
|
||||
into current_max
|
||||
from task
|
||||
where operation_id = new.operation_id;
|
||||
|
||||
new.display_id := current_max + 1;
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop index if exists "public"."callback_operation_display_id_unique";
|
||||
drop index if exists "public"."task_operation_display_id_unique";
|
||||
drop table if exists "public"."operation_display_counters";
|
||||
@@ -152,12 +152,6 @@ func MythicRPCCallbackCreate(input MythicRPCCallbackCreateMessage) MythicRPCCall
|
||||
return response
|
||||
}
|
||||
defer transaction.Rollback()
|
||||
_, err = transaction.Exec(`LOCK TABLE callback`)
|
||||
if err != nil {
|
||||
logging.LogError(err, "Failed to lock callback table")
|
||||
response.Error = err.Error()
|
||||
return response
|
||||
}
|
||||
if input.EventStepInstanceID != nil {
|
||||
callback.EventStepInstanceID.Valid = true
|
||||
callback.EventStepInstanceID.Int64 = int64(*input.EventStepInstanceID)
|
||||
|
||||
@@ -555,11 +555,6 @@ func addTaskToDatabase(task *databaseStructs.Task) error {
|
||||
return err
|
||||
}
|
||||
defer transaction.Rollback()
|
||||
_, err = transaction.Exec(`LOCK TABLE task`)
|
||||
if err != nil {
|
||||
logging.LogError(err, "Failed to lock callback table")
|
||||
return err
|
||||
}
|
||||
statement, err := transaction.PrepareNamed(`INSERT INTO task
|
||||
(agent_task_id,command_name,callback_id,operator_id,command_id,token_id,params,
|
||||
original_params,display_params,status,tasking_location,parameter_group_name,
|
||||
@@ -571,26 +566,29 @@ func addTaskToDatabase(task *databaseStructs.Task) error {
|
||||
:parent_task_id, :subtask_callback_function, :group_callback_function, :subtask_group_name, :operation_id,
|
||||
:is_interactive_task, :interactive_task_type, :eventstepinstance_id, :status_timestamp_submitted,
|
||||
:command_payload_type, :mythic_parsed_params)
|
||||
RETURNING id`)
|
||||
RETURNING id, display_id`)
|
||||
if err != nil {
|
||||
logging.LogError(err, "Failed to make a prepared statement for new task creation")
|
||||
return err
|
||||
}
|
||||
err = statement.Get(&task.ID, task)
|
||||
defer statement.Close()
|
||||
taskIDs := struct {
|
||||
ID int `db:"id"`
|
||||
DisplayID int `db:"display_id"`
|
||||
}{}
|
||||
err = statement.Get(&taskIDs, task)
|
||||
if err != nil {
|
||||
logging.LogError(err, "Failed to create new task in database")
|
||||
return err
|
||||
}
|
||||
task.ID = taskIDs.ID
|
||||
task.DisplayID = taskIDs.DisplayID
|
||||
err = transaction.Commit()
|
||||
if err != nil {
|
||||
logging.LogError(err, "Failed to commit transaction of creating new callback")
|
||||
logging.LogError(err, "Failed to commit transaction of creating new task")
|
||||
return err
|
||||
}
|
||||
go emitTaskLog(task.ID)
|
||||
err = database.DB.Get(&task.DisplayID, `SELECT display_id FROM task WHERE id=$1`, task.ID)
|
||||
if err != nil {
|
||||
logging.LogError(err, "Failed to get task display ID from task table")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
From prometheuscommunity/postgres-exporter
|
||||
@@ -1,61 +0,0 @@
|
||||
pg_stat_statements:
|
||||
query: "SELECT
|
||||
pg_get_userbyid(userid) as user,
|
||||
pg_database.datname,
|
||||
pg_stat_statements.queryid,
|
||||
pg_stat_statements.query,
|
||||
pg_stat_statements.calls,
|
||||
pg_stat_statements.total_exec_time as time_milliseconds,
|
||||
pg_stat_statements.rows,
|
||||
pg_stat_statements.shared_blks_hit,
|
||||
pg_stat_statements.shared_blks_read,
|
||||
pg_stat_statements.shared_blks_dirtied,
|
||||
pg_stat_statements.shared_blks_written,
|
||||
pg_stat_statements.local_blks_hit,
|
||||
pg_stat_statements.local_blks_read,
|
||||
pg_stat_statements.local_blks_dirtied,
|
||||
pg_stat_statements.local_blks_written,
|
||||
pg_stat_statements.temp_blks_read,
|
||||
pg_stat_statements.temp_blks_written,
|
||||
pg_stat_statements.blk_read_time,
|
||||
pg_stat_statements.blk_write_time
|
||||
FROM pg_stat_statements
|
||||
JOIN pg_database
|
||||
ON pg_database.oid = pg_stat_statements.dbid"
|
||||
metrics:
|
||||
- user:
|
||||
usage: "LABEL"
|
||||
description: "The user who executed the statement"
|
||||
- datname:
|
||||
usage: "LABEL"
|
||||
description: "The database in which the statement was executed"
|
||||
- queryid:
|
||||
usage: "LABEL"
|
||||
description: "Internal hash code, computed from the statement's parse tree"
|
||||
- query:
|
||||
usage: "LABEL"
|
||||
description: "Processed query"
|
||||
- calls:
|
||||
usage: "COUNTER"
|
||||
description: "Number of times executed"
|
||||
- time_milliseconds:
|
||||
usage: "COUNTER"
|
||||
description: "Total time spent in the statement, in milliseconds"
|
||||
- rows:
|
||||
usage: "COUNTER"
|
||||
description: "Total number of rows retrieved or affected by the statement"
|
||||
- shared_blks_hit:
|
||||
usage: "COUNTER"
|
||||
description: "Total number of shared block cache hits by the statement"
|
||||
- shared_blks_read:
|
||||
usage: "COUNTER"
|
||||
description: "Total number of shared blocks read by the statement"
|
||||
- shared_blks_dirtied:
|
||||
usage: "COUNTER"
|
||||
description: "Total number of shared blocks dirtied by the statement"
|
||||
- shared_blks_written:
|
||||
usage: "COUNTER"
|
||||
description: "Total number of shared blocks written by the statement"
|
||||
- local_blks_hit:
|
||||
usage: "COUNTER"
|
||||
description: "Total number of local block cache hits by the statement"
|
||||
@@ -1 +0,0 @@
|
||||
From prom/prometheus
|
||||
@@ -1,10 +0,0 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
scrape_configs:
|
||||
- job_name: mythic_prometheus
|
||||
static_configs:
|
||||
- targets: ["mythic_prometheus:9090"]
|
||||
- job_name: mythic_postgres_exporter
|
||||
static_configs:
|
||||
- targets: ["mythic_postgres_exporter:9187"]
|
||||
Reference in New Issue
Block a user