Skip to content

Commit

Permalink
Merge pull request #813 from cc-nfi/features/supertask-max-agents
Browse files Browse the repository at this point in the history
Add support for maximum amount of agents that should work on a supertask
  • Loading branch information
s3inlc committed Aug 28, 2023
2 parents c4cdfb4 + ed093b4 commit 0e4b833
Show file tree
Hide file tree
Showing 23 changed files with 478 additions and 107 deletions.
238 changes: 222 additions & 16 deletions ci/tests/integration/MaxAgentsTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,19 @@ public function run() {
HashtopolisTestFramework::log(HashtopolisTestFramework::LOG_INFO, "Running " . $this->getTestName() . "...");
$this->prepare();
try {
$this->testMaxAgents();
$response = $this->addHashlist(["name" => "NotSecureList", "isSecure" => false]);
$hashlistId = $response["hashlistId"];

$this->testTaskMaxAgents($hashlistId);
$this->testSuperTaskMaxAgents($hashlistId);
}
finally {
$this->cleanup();
}
HashtopolisTestFramework::log(HashtopolisTestFramework::LOG_INFO, $this->getTestName() . " completed");
}

private function testMaxAgents() {
$response = $this->addHashlist(["name" => "NotSecureList", "isSecure" => false]);
$hashlistId = $response["hashlistId"];

private function testTaskMaxAgents($hashlistId) {
$agent1 = $this->createAgent("agent-1");
$agent2 = $this->createAgent("agent-2");

Expand All @@ -70,14 +71,14 @@ private function testMaxAgents() {
// verify agent 1 is assigned to task 1
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent1["token"]]);
if ($response["taskId"] != $task1Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
return;
}

// verify agent 2 is assigned to task 1
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent2["token"]]);
if ($response["taskId"] != $task1Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected task with id '%d' for agent 2, instead got: %s", $task1Id, implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected task with id '%d' for agent 2, instead got: %s", $task1Id, implode(", ", $response)));
return;
}

Expand Down Expand Up @@ -107,7 +108,7 @@ private function testMaxAgents() {
// verify agent 2 is NOT assigned to task 1
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent2["token"]]);
if ($response["taskId"] == $task1Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected no task for agent 2, instead got: %s", implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected no task for agent 2, instead got: %s", implode(", ", $response)));
return;
}
// verify getting chunk by agent 2 for task 1 now fails, because the task is already saturated
Expand All @@ -116,7 +117,7 @@ private function testMaxAgents() {
"taskId" => $task1Id,
"token" => $agent2["token"]]);
if ($response["response"] !== "ERROR" || $response["message"] != "Task already saturated by other agents, no other task available!") {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected getChunk to fail, instead got: %s", implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected getChunk to fail, instead got: %s", implode(", ", $response)));
return;
}

Expand All @@ -131,7 +132,7 @@ private function testMaxAgents() {
// verify agent 1 is assigned to task 1
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent1["token"]]);
if ($response["taskId"] != $task1Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
return;
}

Expand All @@ -150,14 +151,14 @@ private function testMaxAgents() {
// verify agent 1 is assigned to task 1
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent1["token"]]);
if ($response["taskId"] != $task1Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
return;
}

// verify agent 2 is assigned to task 2
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent2["token"]]);
if ($response["taskId"] != $task2Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task2Id, implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected task with id '%d' for agent 2, instead got: %s", $task2Id, implode(", ", $response)));
return;
}

Expand All @@ -167,7 +168,7 @@ private function testMaxAgents() {
"taskId" => $task2Id,
"token" => $agent2["token"]]);
if ($response["response"] !== "SUCCESS") {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected getChunk to succeed, instead got: %s", implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected getChunk to succeed, instead got: %s", implode(", ", $response)));
return;
}

Expand All @@ -183,7 +184,7 @@ private function testMaxAgents() {
// verify agent 2 is assigned to task 1 (since it has higher priority than task 2)
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent2["token"]]);
if ($response["taskId"] != $task1Id) {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected task with id '%d' for agent 1, instead got: %s", $task1Id, implode(", ", $response)));
return;
}

Expand All @@ -193,10 +194,181 @@ private function testMaxAgents() {
"taskId" => $task1Id,
"token" => $agent2["token"]]);
if ($response["response"] !== "SUCCESS") {
$this->testFailed("MaxAgentsTest:testMaxAgents()", sprintf("Expected getChunk to succeed, instead got: %s", implode(", ", $response)));
$this->testFailed("MaxAgentsTest:testTaskMaxAgents()", sprintf("Expected getChunk to succeed, instead got: %s", implode(", ", $response)));
return;
}
$this->testSuccess("MaxAgentsTest:testTaskMaxAgents()");
}

private function testSuperTaskMaxAgents($hashlistId) {
// disable existing tasks
$response = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "listTasks",
"accessKey" => "mykey"
], HashtopolisTestFramework::REQUEST_UAPI);
foreach ($response["tasks"] as $task) {
$this->setTaskPriority($task["taskId"], 0);
}

// register 3 agents
$agent1 = $this->createAgent("agent-pt-1");
$agent2 = $this->createAgent("agent-pt-2");
$agent3 = $this->createAgent("agent-pt-3");

// create 3 pretasks
$response = $this->createPretask([
"name" => "pretask-1",
"attackCmd" => "#HL# -a 3 ?l?l?l?l?l?l",
"priority" => 1,
"maxAgents" => 0
]);
$response = $this->createPretask([
"name" => "pretask-2",
"attackCmd" => "#HL# -a 3 ?l?l?l?l?l?l",
"priority" => 0,
"maxAgents" => 1
]);
$response = $this->createPretask([
"name" => "pretask-3",
"attackCmd" => "#HL# -a 3 ?l?l?l?l?l?l",
"priority" => 100,
"maxAgents" => 2
]);

// collect pretask information
$response = HashtopolisTestFramework::doRequest([
"section" => "pretask",
"request" => "listPretasks",
"accessKey" => "mykey"
], HashtopolisTestFramework::REQUEST_UAPI);
$pretasks = array_map(fn($pretask) => $pretask["pretaskId"], $response["pretasks"]);

// create a supertask for all pretasks above, and get the supertask id
$response = HashtopolisTestFramework::doRequest([
"section" => "supertask",
"request" => "createSupertask",
"accessKey" => "mykey",
"name" => "supertask-1",
"pretasks" => $pretasks
], HashtopolisTestFramework::REQUEST_UAPI);
$response = HashtopolisTestFramework::doRequest([
"section" => "supertask",
"request" => "listSupertasks",
"accessKey" => "mykey"
], HashtopolisTestFramework::REQUEST_UAPI);
$supertaskId = $response["supertasks"][0]["supertaskId"];

// execute the supertask
$response = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "runSupertask",
"accessKey" => "mykey",
"supertaskId" => $supertaskId,
"hashlistId" => $hashlistId,
"crackerVersionId" => 1
], HashtopolisTestFramework::REQUEST_UAPI);

// get the taskwrapper created from the supertask
$response = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "listTasks",
"accessKey" => "mykey"
], HashtopolisTestFramework::REQUEST_UAPI);
$taskWrapper = current(array_filter($response["tasks"], fn($task) => $task["name"] == "supertask-1"));

// Check if the max agents of the wrapper is 0, since it should not take over the maxAgents value of the pretasks
if ($taskWrapper["maxAgents"] != 0) {
$this->testFailed("MaxAgentsTest:testSupertaskMaxAgents()", sprintf("Expected taskwrapper to have maxAgents value of 0, instead got: %s", $taskWrapper["maxAgents"]));
return;
}

// request a task for agent 1
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent1["token"]]);
$task = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "getTask",
"accessKey" => "mykey",
"taskId" => $response["taskId"]
], HashtopolisTestFramework::REQUEST_UAPI);
// check that agent 1 is assigned to pretask-3, as it has the highest priority
if ($task["name"] != "pretask-3") {
$this->testFailed("MaxAgentsTest:testSupertaskMaxAgents()", sprintf("Expected agent 1 to be assigned to pretask-3, instead assigned to to: %s", $task["name"]));
return;
}

// now update the max allowed agents of the supertask to 1
$response = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "setSupertaskMaxAgents",
"accessKey" => "mykey",
"supertaskId" => $taskWrapper["supertaskId"],
"supertaskMaxAgents" => 1
], HashtopolisTestFramework::REQUEST_UAPI);

// request a task for agent 2
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent2["token"]]);
// check that no task is given, since the limit of 1 max agent on the supertask has been reached
if ($response["taskId"] != null) {
$this->testFailed("MaxAgentsTest:testSupertaskMaxAgents()", sprintf("Expected no task for agent 2, instead got task with id: %s", $response["taskId"]));
return;
}

// now update the max allowed agents of the supertask to 2
$response = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "setSupertaskMaxAgents",
"accessKey" => "mykey",
"supertaskId" => $taskWrapper["supertaskId"],
"supertaskMaxAgents" => 2
], HashtopolisTestFramework::REQUEST_UAPI);

// request a task for agent 2
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent2["token"]]);
$task = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "getTask",
"accessKey" => "mykey",
"taskId" => $response["taskId"]
], HashtopolisTestFramework::REQUEST_UAPI);
// check that agent 2 is now assigned to pretask-3, as it has the highest priority and has maxAgents value of 2
if ($task["name"] != "pretask-3") {
$this->testFailed("MaxAgentsTest:testSupertaskMaxAgents()", sprintf("Expected agent 2 to be assigned to pretask-3, instead assigned to to: %s", $task["name"]));
return;
}
$this->testSuccess("MaxAgentsTest:testMaxAgents()");

// request a task for agent 3
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent3["token"]]);
// check that no task is given, since the limit of 2 max agents on the supertask has been reached
if ($response["taskId"] != null) {
$this->testFailed("MaxAgentsTest:testSupertaskMaxAgents()", sprintf("Expected no task for agent 3, instead got task with id: %s", $response["taskId"]));
return;
}

// now update the max allowed agents of the supertask to unlimited
$response = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "setSupertaskMaxAgents",
"accessKey" => "mykey",
"supertaskId" => $taskWrapper["supertaskId"],
"supertaskMaxAgents" => 0
], HashtopolisTestFramework::REQUEST_UAPI);

// request a task for agent 3
$response = HashtopolisTestFramework::doRequest(["action" => "getTask", "token" => $agent3["token"]]);
$task = HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "getTask",
"accessKey" => "mykey",
"taskId" => $response["taskId"]
], HashtopolisTestFramework::REQUEST_UAPI);
// check that agent 3 is now assigned to pretask-1, as pretask-3 is saturated and pretask-2 has 0 priority
if ($task["name"] != "pretask-1") {
$this->testFailed("MaxAgentsTest:testSupertaskMaxAgents()", sprintf("Expected agent 3 to be assigned to pretask-1, instead assigned to to: %s", $task["name"]));
return;
}

$this->testSuccess("MaxAgentsTest:testSuperTaskMaxAgents()");
}

private function addFile($name, $type) {
Expand Down Expand Up @@ -303,6 +475,40 @@ private function createTask($values = []) {
return HashtopolisTestFramework::doRequest($query, HashtopolisTestFramework::REQUEST_UAPI);
}

private function createPretask($values = []) {
$query = [
"section" => "pretask",
"request" => "createPretask",
"name" => "",
"attackCmd" => "",
"chunksize" => 600,
"statusTimer" => 5,
"benchmarkType" => "speed",
"color" => "",
"isCpuOnly" => false,
"isSmall" => false,
"crackerTypeId" => 1,
"files" => [],
"priority" => 0,
"maxAgents" => 16,
"accessKey" => "mykey"
];
foreach ($values as $key => $value) {
$query[$key] = $value;
}
return HashtopolisTestFramework::doRequest($query, HashtopolisTestFramework::REQUEST_UAPI);
}

private function setTaskPriority($taskId, $priority) {
return HashtopolisTestFramework::doRequest([
"section" => "task",
"request" => "setTaskPriority",
"accessKey" => "mykey",
"taskId" => $taskId,
"priority" => $priority
], HashtopolisTestFramework::REQUEST_UAPI);
}

public function getTestName() {
return "Max Agents Test";
}
Expand Down
3 changes: 3 additions & 0 deletions doc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
- Clicking pretask in Supertask create screen now directs correctly to the pretask and not a task with the same id (#945)
- Pretask attackCmd parameter was not checked for maximum length of 256 on creation (#963)

## New feature
- Number of agents per supertask/taskwrapper can be limited (#769).


# v0.13.1 -> v0.14.0

Expand Down
24 changes: 24 additions & 0 deletions doc/user-api/sections/task.tex
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,30 @@
}
\end{verbatim}
}
\subsection*{\textit{setSupertaskMaxAgents}}
Set the maximum number of assigned agents for a running supertask. Takes effect when agents request a new chunk.
{
\color{blue}
\begin{verbatim}
{
"section": "task",
"request": "setSupertaskMaxAgents",
"supertaskId": 42,
"supertaskMaxAgents": 2,
"accessKey": "mykey"
}
\end{verbatim}
}
{
\color{OliveGreen}
\begin{verbatim}
{
"section": "task",
"request": "setSupertaskMaxAgents",
"response": "OK"
}
\end{verbatim}
}
\subsection*{\textit{setTaskName}}
Set the name for a task.
{
Expand Down
Loading

0 comments on commit 0e4b833

Please sign in to comment.