feat: add default timeout in script manager closes #352
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.1.7 on 2021-03-31 01:08
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('scripts', '0005_auto_20201207_1606'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='script',
|
||||||
|
name='default_timeout',
|
||||||
|
field=models.PositiveIntegerField(default=90),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -29,6 +29,7 @@ class Script(BaseAuditModel):
|
|||||||
favorite = models.BooleanField(default=False)
|
favorite = models.BooleanField(default=False)
|
||||||
category = models.CharField(max_length=100, null=True, blank=True)
|
category = models.CharField(max_length=100, null=True, blank=True)
|
||||||
code_base64 = models.TextField(null=True, blank=True)
|
code_base64 = models.TextField(null=True, blank=True)
|
||||||
|
default_timeout = models.PositiveIntegerField(default=90)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class ScriptTableSerializer(ModelSerializer):
|
|||||||
"shell",
|
"shell",
|
||||||
"category",
|
"category",
|
||||||
"favorite",
|
"favorite",
|
||||||
|
"default_timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ class ScriptSerializer(ModelSerializer):
|
|||||||
"category",
|
"category",
|
||||||
"favorite",
|
"favorite",
|
||||||
"code_base64",
|
"code_base64",
|
||||||
|
"default_timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class TestScriptViews(TacticalTestCase):
|
|||||||
"shell": "powershell",
|
"shell": "powershell",
|
||||||
"category": "New",
|
"category": "New",
|
||||||
"code": "Some Test Code\nnew Line",
|
"code": "Some Test Code\nnew Line",
|
||||||
|
"default_timeout": 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
# test without file upload
|
# test without file upload
|
||||||
@@ -55,6 +56,7 @@ class TestScriptViews(TacticalTestCase):
|
|||||||
"shell": "cmd",
|
"shell": "cmd",
|
||||||
"category": "New",
|
"category": "New",
|
||||||
"filename": file,
|
"filename": file,
|
||||||
|
"default_timeout": 4455,
|
||||||
}
|
}
|
||||||
|
|
||||||
# test with file upload
|
# test with file upload
|
||||||
@@ -79,6 +81,7 @@ class TestScriptViews(TacticalTestCase):
|
|||||||
"description": "Description Change",
|
"description": "Description Change",
|
||||||
"shell": script.shell,
|
"shell": script.shell,
|
||||||
"code": "Test Code\nAnother Line",
|
"code": "Test Code\nAnother Line",
|
||||||
|
"default_timeout": 13344556,
|
||||||
}
|
}
|
||||||
|
|
||||||
# test edit a userdefined script
|
# test edit a userdefined script
|
||||||
@@ -104,6 +107,7 @@ class TestScriptViews(TacticalTestCase):
|
|||||||
"shell": script.shell,
|
"shell": script.shell,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
"code": "Test Code\nAnother Line",
|
"code": "Test Code\nAnother Line",
|
||||||
|
"default_timeout": 54345,
|
||||||
}
|
}
|
||||||
# test marking a builtin script as favorite
|
# test marking a builtin script as favorite
|
||||||
resp = self.client.put(
|
resp = self.client.put(
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class GetAddScripts(APIView):
|
|||||||
"category": request.data["category"],
|
"category": request.data["category"],
|
||||||
"description": request.data["description"],
|
"description": request.data["description"],
|
||||||
"shell": request.data["shell"],
|
"shell": request.data["shell"],
|
||||||
|
"default_timeout": request.data["default_timeout"],
|
||||||
"script_type": "userdefined", # force all uploads to be userdefined. built in scripts cannot be edited by user
|
"script_type": "userdefined", # force all uploads to be userdefined. built in scripts cannot be edited by user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -511,9 +511,10 @@ export default {
|
|||||||
}, 500);
|
}, 500);
|
||||||
},
|
},
|
||||||
runFavScript(scriptpk, agentpk) {
|
runFavScript(scriptpk, agentpk) {
|
||||||
|
let default_timeout = this.favoriteScripts.find(i => i.value === scriptpk).timeout;
|
||||||
const data = {
|
const data = {
|
||||||
pk: agentpk,
|
pk: agentpk,
|
||||||
timeout: 900,
|
timeout: default_timeout,
|
||||||
scriptPK: scriptpk,
|
scriptPK: scriptpk,
|
||||||
output: "forget",
|
output: "forget",
|
||||||
args: [],
|
args: [],
|
||||||
@@ -532,7 +533,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.favoriteScripts = r.data
|
this.favoriteScripts = r.data
|
||||||
.filter(k => k.favorite === true)
|
.filter(k => k.favorite === true)
|
||||||
.map(script => ({ label: script.name, value: script.id }))
|
.map(script => ({ label: script.name, value: script.id, timeout: script.default_timeout }))
|
||||||
.sort((a, b) => a.label.localeCompare(b.label));
|
.sort((a, b) => a.label.localeCompare(b.label));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -291,6 +291,7 @@
|
|||||||
props.row.description
|
props.row.description
|
||||||
}}</q-tooltip>
|
}}</q-tooltip>
|
||||||
</q-td>
|
</q-td>
|
||||||
|
<q-td>{{ props.row.default_timeout }}</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
@@ -368,8 +369,15 @@ export default {
|
|||||||
align: "left",
|
align: "left",
|
||||||
sortable: false,
|
sortable: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "default_timeout",
|
||||||
|
label: "Default Timeout (seconds)",
|
||||||
|
field: "default_timeout",
|
||||||
|
align: "left",
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
visibleColumns: ["favorite", "name", "category", "desc", "shell"],
|
visibleColumns: ["favorite", "name", "category", "desc", "shell", "default_timeout"],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -92,6 +92,7 @@
|
|||||||
map-options
|
map-options
|
||||||
emit-value
|
emit-value
|
||||||
options-dense
|
options-dense
|
||||||
|
@input="setDefaultTimeout"
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section v-if="mode === 'script'" class="q-pt-none">
|
<q-card-section v-if="mode === 'script'" class="q-pt-none">
|
||||||
@@ -138,11 +139,7 @@
|
|||||||
style="max-width: 150px"
|
style="max-width: 150px"
|
||||||
label="Timeout (seconds)"
|
label="Timeout (seconds)"
|
||||||
stack-label
|
stack-label
|
||||||
:rules="[
|
:rules="[val => !!val || '*Required', val => val >= 5 || 'Minimum is 5 seconds']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 10 || 'Minimum is 10 seconds',
|
|
||||||
val => val <= 25200 || 'Maximum is 25,200 seconds',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
|
||||||
@@ -200,6 +197,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setDefaultTimeout() {
|
||||||
|
this.timeout = this.scriptOptions.find(i => i.value === this.scriptPK).timeout;
|
||||||
|
},
|
||||||
getScripts() {
|
getScripts() {
|
||||||
let scripts;
|
let scripts;
|
||||||
this.$axios.get("/scripts/scripts/").then(r => {
|
this.$axios.get("/scripts/scripts/").then(r => {
|
||||||
@@ -209,7 +209,7 @@ export default {
|
|||||||
scripts = r.data.filter(i => i.script_type !== "builtin");
|
scripts = r.data.filter(i => i.script_type !== "builtin");
|
||||||
}
|
}
|
||||||
this.scriptOptions = scripts
|
this.scriptOptions = scripts
|
||||||
.map(script => ({ label: script.name, value: script.id }))
|
.map(script => ({ label: script.name, value: script.id, timeout: script.default_timeout }))
|
||||||
.sort((a, b) => a.label.localeCompare(b.label));
|
.sort((a, b) => a.label.localeCompare(b.label));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
map-options
|
map-options
|
||||||
emit-value
|
emit-value
|
||||||
options-dense
|
options-dense
|
||||||
|
@input="setDefaultTimeout"
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
@@ -73,11 +74,7 @@
|
|||||||
style="max-width: 150px"
|
style="max-width: 150px"
|
||||||
label="Timeout (seconds)"
|
label="Timeout (seconds)"
|
||||||
stack-label
|
stack-label
|
||||||
:rules="[
|
:rules="[val => !!val || '*Required', val => val >= 5 || 'Minimum is 5 seconds']"
|
||||||
val => !!val || '*Required',
|
|
||||||
val => val >= 10 || 'Minimum is 10 seconds',
|
|
||||||
val => val <= 25200 || 'Maximum is 25,200 seconds',
|
|
||||||
]"
|
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions align="center">
|
<q-card-actions align="center">
|
||||||
@@ -92,7 +89,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import mixins from "@/mixins/mixins";
|
import mixins from "@/mixins/mixins";
|
||||||
import { mapGetters, mapState } from "vuex";
|
import { mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "RunScript",
|
name: "RunScript",
|
||||||
@@ -123,6 +120,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setDefaultTimeout() {
|
||||||
|
this.timeout = this.scriptOptions.find(i => i.value === this.scriptPK).timeout;
|
||||||
|
},
|
||||||
getScripts() {
|
getScripts() {
|
||||||
let scripts;
|
let scripts;
|
||||||
this.$axios.get("/scripts/scripts/").then(r => {
|
this.$axios.get("/scripts/scripts/").then(r => {
|
||||||
@@ -132,7 +132,7 @@ export default {
|
|||||||
scripts = r.data.filter(i => i.script_type !== "builtin");
|
scripts = r.data.filter(i => i.script_type !== "builtin");
|
||||||
}
|
}
|
||||||
this.scriptOptions = scripts
|
this.scriptOptions = scripts
|
||||||
.map(script => ({ label: script.name, value: script.id }))
|
.map(script => ({ label: script.name, value: script.id, timeout: script.default_timeout }))
|
||||||
.sort((a, b) => a.label.localeCompare(b.label));
|
.sort((a, b) => a.label.localeCompare(b.label));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -48,6 +48,17 @@
|
|||||||
label="Shell Type"
|
label="Shell Type"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="q-pa-sm col-2">
|
||||||
|
<q-input
|
||||||
|
type="number"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
:readonly="readonly"
|
||||||
|
v-model.number="localScript.default_timeout"
|
||||||
|
label="Timeout (seconds)"
|
||||||
|
:rules="[val => val >= 5 || 'Minimum is 5']"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="q-pa-sm col-3">
|
<div class="q-pa-sm col-3">
|
||||||
<q-select
|
<q-select
|
||||||
hint="Press Enter or Tab when adding a new value"
|
hint="Press Enter or Tab when adding a new value"
|
||||||
@@ -65,7 +76,7 @@
|
|||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="q-pa-sm col-4">
|
<div class="q-pa-sm col-2">
|
||||||
<q-input filled dense :readonly="readonly" v-model="localScript.description" label="Description" />
|
<q-input filled dense :readonly="readonly" v-model="localScript.description" label="Description" />
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
@@ -118,6 +129,7 @@ export default {
|
|||||||
category: "",
|
category: "",
|
||||||
favorite: false,
|
favorite: false,
|
||||||
script_type: "userdefined",
|
script_type: "userdefined",
|
||||||
|
default_timeout: 90,
|
||||||
},
|
},
|
||||||
maximized: false,
|
maximized: false,
|
||||||
filterOptions: [],
|
filterOptions: [],
|
||||||
@@ -217,7 +229,7 @@ export default {
|
|||||||
return !this.readonly ? "click" : null;
|
return !this.readonly ? "click" : null;
|
||||||
},
|
},
|
||||||
getMaxWidth() {
|
getMaxWidth() {
|
||||||
return this.maximized ? "" : "width: 60vw; max-width: 90vw";
|
return this.maximized ? "" : "width: 70vw; max-width: 90vw";
|
||||||
},
|
},
|
||||||
heightVar() {
|
heightVar() {
|
||||||
return this.maximized ? "--prism-height: 80vh" : "--prism-height: 70vh";
|
return this.maximized ? "--prism-height: 80vh" : "--prism-height: 70vh";
|
||||||
@@ -232,6 +244,7 @@ export default {
|
|||||||
this.localScript.shell = this.script.shell;
|
this.localScript.shell = this.script.shell;
|
||||||
this.localScript.category = this.script.category;
|
this.localScript.category = this.script.category;
|
||||||
this.localScript.script_type = this.script.script_type;
|
this.localScript.script_type = this.script.script_type;
|
||||||
|
this.localScript.default_timeout = this.script.default_timeout;
|
||||||
this.getCode();
|
this.getCode();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -67,6 +67,17 @@
|
|||||||
map-options
|
map-options
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
<q-card-section class="row">
|
||||||
|
<div class="col-4">Default Timeout (seconds)</div>
|
||||||
|
<q-input
|
||||||
|
type="number"
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
class="col-8"
|
||||||
|
v-model.number="script.default_timeout"
|
||||||
|
:rules="[val => val >= 5 || 'Minimum is 5']"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
<q-card-actions>
|
<q-card-actions>
|
||||||
<q-space />
|
<q-space />
|
||||||
<q-btn dense flat label="Cancel" v-close-popup />
|
<q-btn dense flat label="Cancel" v-close-popup />
|
||||||
@@ -92,6 +103,7 @@ export default {
|
|||||||
description: "",
|
description: "",
|
||||||
shell: "powershell",
|
shell: "powershell",
|
||||||
category: null,
|
category: null,
|
||||||
|
default_timeout: 90,
|
||||||
},
|
},
|
||||||
shellOptions: [
|
shellOptions: [
|
||||||
{ label: "Powershell", value: "powershell" },
|
{ label: "Powershell", value: "powershell" },
|
||||||
@@ -120,6 +132,7 @@ export default {
|
|||||||
formData.append("name", this.script.name);
|
formData.append("name", this.script.name);
|
||||||
formData.append("shell", this.script.shell);
|
formData.append("shell", this.script.shell);
|
||||||
formData.append("description", this.script.description);
|
formData.append("description", this.script.description);
|
||||||
|
formData.append("default_timeout", this.script.default_timeout);
|
||||||
|
|
||||||
this.$axios
|
this.$axios
|
||||||
.post("/scripts/scripts/", formData)
|
.post("/scripts/scripts/", formData)
|
||||||
|
|||||||
Reference in New Issue
Block a user