Skip to content

Commit fca39ad

Browse files
Merge pull request #2065 from akto-api-security/feature/custom_mini_testing_selection_dashboard
Feature/custom mini testing selection dashboard
2 parents 9ab65cb + fd4a877 commit fca39ad

File tree

9 files changed

+163
-107
lines changed

9 files changed

+163
-107
lines changed

apps/dashboard/src/main/java/com/akto/action/testing/StartTestAction.java

+61-76
Original file line numberDiff line numberDiff line change
@@ -3,95 +3,51 @@
33
import com.akto.action.UserAction;
44
import com.akto.billing.UsageMetricUtils;
55
import com.akto.dao.context.Context;
6+
import com.akto.dao.monitoring.ModuleInfoDao;
67
import com.akto.dao.test_editor.YamlTemplateDao;
7-
import com.akto.dao.testing.DeleteTestRunsDao;
8-
import com.akto.dao.testing.TestRolesDao;
9-
import com.akto.dao.testing.TestingRunConfigDao;
10-
import com.akto.dao.testing.TestingRunDao;
11-
import com.akto.dao.testing.TestingRunResultDao;
12-
import com.akto.dao.testing.TestingRunResultSummariesDao;
13-
import com.akto.dao.testing.VulnerableTestingRunResultDao;
14-
import com.akto.dao.testing.WorkflowTestsDao;
8+
import com.akto.dao.testing.*;
159
import com.akto.dao.testing.sources.TestSourceConfigsDao;
1610
import com.akto.dao.testing_run_findings.TestingRunIssuesDao;
17-
import com.akto.dao.testing.*;
18-
import com.akto.dao.testing.config.TestSuiteDao;
19-
import com.akto.dto.ApiCollection;
20-
import com.akto.dto.billing.FeatureAccess;
21-
import com.akto.dto.testing.config.EditableTestingRunConfig;
22-
import com.akto.dto.testing.config.TestSuites;
2311
import com.akto.dto.ApiInfo;
2412
import com.akto.dto.ApiToken.Utility;
2513
import com.akto.dto.CollectionConditions.TestConfigsAdvancedSettings;
2614
import com.akto.dto.User;
15+
import com.akto.dto.billing.FeatureAccess;
16+
import com.akto.dto.monitoring.ModuleInfo;
2717
import com.akto.dto.test_editor.Info;
2818
import com.akto.dto.test_run_findings.TestingIssuesId;
2919
import com.akto.dto.test_run_findings.TestingRunIssues;
30-
import com.akto.dto.testing.AuthMechanism;
31-
import com.akto.dto.testing.AutoTicketingDetails;
32-
import com.akto.dto.testing.CollectionWiseTestingEndpoints;
33-
import com.akto.dto.testing.CustomTestingEndpoints;
34-
import com.akto.dto.testing.DeleteTestRuns;
35-
import com.akto.dto.testing.GenericTestResult;
36-
import com.akto.dto.testing.MultiExecTestResult;
37-
import com.akto.dto.testing.TestResult;
20+
import com.akto.dto.testing.*;
3821
import com.akto.dto.testing.TestResult.TestError;
39-
import com.akto.dto.testing.TestingEndpoints;
40-
import com.akto.dto.testing.TestingRun;
4122
import com.akto.dto.testing.TestingRun.State;
4223
import com.akto.dto.testing.TestingRun.TestingRunType;
43-
import com.akto.dto.testing.TestingRunConfig;
44-
import com.akto.dto.testing.TestingRunResult;
45-
import com.akto.dto.testing.TestingRunResultSummary;
46-
import com.akto.dto.testing.WorkflowTest;
47-
import com.akto.dto.testing.WorkflowTestingEndpoints;
4824
import com.akto.dto.testing.config.EditableTestingRunConfig;
4925
import com.akto.dto.testing.info.CurrentTestsStatus;
5026
import com.akto.dto.testing.info.CurrentTestsStatus.StatusForIndividualTest;
5127
import com.akto.dto.testing.sources.TestSourceConfig;
52-
import com.akto.dto.usage.MetricTypes;
5328
import com.akto.log.LoggerMaker;
5429
import com.akto.log.LoggerMaker.LogDb;
55-
import com.akto.testing.TestCompletion;
5630
import com.akto.usage.UsageMetricCalculator;
57-
import com.akto.usage.UsageMetricHandler;
5831
import com.akto.util.Constants;
59-
import com.akto.util.UsageUtils;
6032
import com.akto.util.enums.GlobalEnums;
6133
import com.akto.util.enums.GlobalEnums.Severity;
6234
import com.akto.util.enums.GlobalEnums.TestErrorSource;
6335
import com.akto.utils.DeleteTestRunUtils;
6436
import com.akto.utils.Utils;
6537
import com.google.gson.Gson;
66-
import com.mongodb.client.model.Aggregates;
67-
import com.mongodb.client.model.Filters;
68-
import com.mongodb.client.model.Projections;
69-
import com.mongodb.client.model.Sorts;
70-
import com.mongodb.client.model.Updates;
38+
import com.mongodb.client.model.*;
7139
import com.mongodb.client.result.InsertOneResult;
7240
import com.opensymphony.xwork2.Action;
73-
import java.time.Instant;
74-
import java.util.ArrayList;
75-
import java.util.Arrays;
76-
import java.util.HashMap;
77-
import java.util.HashSet;
78-
import java.util.Iterator;
79-
import java.util.List;
80-
import java.util.Map;
81-
import java.util.Set;
82-
import java.util.UUID;
83-
import java.util.concurrent.Callable;
84-
import java.util.concurrent.ExecutorService;
85-
import java.util.concurrent.Executors;
86-
import java.util.concurrent.Future;
87-
import java.util.concurrent.ScheduledExecutorService;
88-
import java.util.concurrent.TimeUnit;
89-
import java.util.regex.Pattern;
90-
import java.util.stream.Collectors;
9141
import org.apache.commons.lang3.StringUtils;
9242
import org.bson.conversions.Bson;
9343
import org.bson.types.ObjectId;
9444

45+
import java.time.Instant;
46+
import java.util.*;
47+
import java.util.concurrent.*;
48+
import java.util.regex.Pattern;
49+
import java.util.stream.Collectors;
50+
9551
public class StartTestAction extends UserAction {
9652

9753
private TestingEndpoints.Type type;
@@ -161,7 +117,7 @@ private static List<ObjectId> getTestsWithSeverity(List<String> severities) {
161117
private boolean sendSlackAlert = false;
162118
private boolean sendMsTeamsAlert = false;
163119

164-
private TestingRun createTestingRun(int scheduleTimestamp, int periodInSeconds) {
120+
private TestingRun createTestingRun(int scheduleTimestamp, int periodInSeconds, String miniTestingServiceName) {
165121
User user = getSUser();
166122

167123
if (!StringUtils.isEmpty(this.overriddenTestAppUrl)) {
@@ -221,9 +177,10 @@ private TestingRun createTestingRun(int scheduleTimestamp, int periodInSeconds)
221177

222178
return new TestingRun(scheduleTimestamp, user.getLogin(),
223179
testingEndpoints, testIdConfig, State.SCHEDULED, periodInSeconds, testName, this.testRunTime,
224-
this.maxConcurrentRequests, this.sendSlackAlert, this.sendMsTeamsAlert);
180+
this.maxConcurrentRequests, this.sendSlackAlert, this.sendMsTeamsAlert, miniTestingServiceName);
225181
}
226182

183+
String selectedMiniTestingServiceName;
227184
private List<String> selectedTests;
228185
private List<TestConfigsAdvancedSettings> testConfigsAdvancedSettings;
229186

@@ -268,7 +225,7 @@ public String startTest() {
268225
}
269226
if (localTestingRun == null) {
270227
try {
271-
localTestingRun = createTestingRun(scheduleTimestamp, getPeriodInSeconds(recurringDaily, recurringWeekly, recurringMonthly));
228+
localTestingRun = createTestingRun(scheduleTimestamp, getPeriodInSeconds(recurringDaily, recurringWeekly, recurringMonthly), selectedMiniTestingServiceName);
272229
// pass boolean from ui, which will tell if testing is coniinuous on new endpoints
273230
if (this.continuousTesting) {
274231
localTestingRun.setPeriodInSeconds(-1);
@@ -331,7 +288,7 @@ public String startTest() {
331288
Updates.set(TestingRun.STATE, TestingRun.State.COMPLETED),
332289
Updates.set(TestingRun.END_TIMESTAMP, Context.now())));
333290
}
334-
291+
335292
}
336293

337294
if (this.overriddenTestAppUrl != null || this.selectedTests != null) {
@@ -342,7 +299,7 @@ public String startTest() {
342299
testingRunConfig.setTestSuiteIds(testSuiteIdsObj);
343300
this.testIdConfig = testingRunConfig.getId();
344301
TestingRunConfigDao.instance.insertOne(testingRunConfig);
345-
}
302+
}
346303

347304
}
348305

@@ -760,7 +717,7 @@ public String fetchTestRunResultsCount() {
760717
return ERROR.toUpperCase();
761718
}
762719

763-
720+
764721
int accountId = Context.accountId.get();
765722

766723
testCountMap = new HashMap<>();
@@ -787,9 +744,9 @@ public String fetchTestRunResultsCount() {
787744
} catch (Exception e) {
788745
e.printStackTrace();
789746
}
790-
747+
791748
}
792-
749+
793750
} catch (Exception e) {
794751
e.printStackTrace();
795752
return ERROR.toUpperCase();
@@ -938,9 +895,9 @@ public String fetchVulnerableTestRunResults() {
938895
}else{
939896
testingRunResultList = TestingRunResultDao.instance.findAll(filters, skip, 50, null);
940897
}
941-
942898

943-
899+
900+
944901
// Map<String, String> sampleDataVsCurlMap = new HashMap<>();
945902
// for (TestingRunResult runResult: testingRunResultList) {
946903
// WorkflowTest workflowTest = runResult.getWorkflowTest();
@@ -1306,11 +1263,11 @@ public String modifyTestingRunConfig(){
13061263
if (editableTestingRunConfig.getTestSubCategoryList() != null && !editableTestingRunConfig.getTestSubCategoryList().equals(existingTestingRunConfig.getTestSubCategoryList())) {
13071264
updates.add(Updates.set(TestingRunConfig.TEST_SUBCATEGORY_LIST, editableTestingRunConfig.getTestSubCategoryList()));
13081265
}
1309-
1266+
13101267
if (editableTestingRunConfig.getTestRoleId() != null && !editableTestingRunConfig.getTestRoleId().equals(existingTestingRunConfig.getTestRoleId())) {
13111268
updates.add(Updates.set(TestingRunConfig.TEST_ROLE_ID, editableTestingRunConfig.getTestRoleId()));
13121269
}
1313-
1270+
13141271
if (editableTestingRunConfig.getOverriddenTestAppUrl() != null && !editableTestingRunConfig.getOverriddenTestAppUrl().equals(existingTestingRunConfig.getOverriddenTestAppUrl())) {
13151272
updates.add(Updates.set(TestingRunConfig.OVERRIDDEN_TEST_APP_URL, editableTestingRunConfig.getOverriddenTestAppUrl()));
13161273
}
@@ -1320,17 +1277,17 @@ public String modifyTestingRunConfig(){
13201277
updates.add(Updates.set(TestingRunConfig.AUTO_TICKETING_DETAILS,
13211278
editableTestingRunConfig.getAutoTicketingDetails()));
13221279
}
1323-
1280+
13241281
if (!updates.isEmpty()) {
13251282
TestingRunConfigDao.instance.updateOne(
13261283
Filters.eq(Constants.ID, this.testingRunConfigId),
1327-
Updates.combine(updates)
1284+
Updates.combine(updates)
13281285
);
13291286
}
13301287
}
13311288

13321289
if (editableTestingRunConfig.getTestingRunHexId() != null) {
1333-
1290+
13341291
TestingRun existingTestingRun = TestingRunDao.instance.findOne(Filters.eq(Constants.ID, new ObjectId(editableTestingRunConfig.getTestingRunHexId())));
13351292

13361293
if (existingTestingRun != null) {
@@ -1375,15 +1332,15 @@ public String modifyTestingRunConfig(){
13751332
)
13761333
);
13771334
}
1378-
1335+
13791336
if (!updates.isEmpty()) {
13801337
TestingRunDao.instance.updateOne(
13811338
Filters.eq(Constants.ID,new ObjectId(editableTestingRunConfig.getTestingRunHexId())),
1382-
Updates.combine(updates)
1339+
Updates.combine(updates)
13831340
);
13841341
}
13851342
}
1386-
1343+
13871344
}
13881345

13891346

@@ -1468,7 +1425,7 @@ public void run() {
14681425
Updates.set(TestingRunResult.IS_IGNORED_RESULT, true)
14691426
);
14701427
}
1471-
1428+
14721429
} catch (Exception e) {
14731430
e.printStackTrace();
14741431
}
@@ -1511,6 +1468,22 @@ private boolean validateAutoTicketingDetails(AutoTicketingDetails autoTicketingD
15111468
return true;
15121469
}
15131470

1471+
private Set<String> miniTestingServiceNames;
1472+
public String fetchMiniTestingServiceNames() {
1473+
List<ModuleInfo> moduleInfos = ModuleInfoDao.instance.findAll(Filters.and(
1474+
Filters.eq(ModuleInfo.MODULE_TYPE, ModuleInfo.ModuleType.MINI_TESTING),
1475+
Filters.gt(ModuleInfo.LAST_HEARTBEAT_RECEIVED, Context.now() - 20 * 60)));
1476+
if (this.miniTestingServiceNames == null) {
1477+
this.miniTestingServiceNames = new HashSet<>();
1478+
}
1479+
for (ModuleInfo moduleInfo : moduleInfos) {
1480+
if (moduleInfo.getName() != null) {
1481+
this.miniTestingServiceNames.add(moduleInfo.getName());
1482+
}
1483+
}
1484+
return SUCCESS.toUpperCase();
1485+
}
1486+
15141487

15151488
public void setType(TestingEndpoints.Type type) {
15161489
this.type = type;
@@ -1893,7 +1866,7 @@ public void setSendMsTeamsAlert(boolean sendMsTeamsAlert) {
18931866
public void setRecurringWeekly(boolean recurringWeekly) {
18941867
this.recurringWeekly = recurringWeekly;
18951868
}
1896-
1869+
18971870
public void setRecurringMonthly(boolean recurringMonthly) {
18981871
this.recurringMonthly = recurringMonthly;
18991872
}
@@ -1905,4 +1878,16 @@ public void setTestSuiteIds(List<String> testSuiteIds) {
19051878
public void setAutoTicketingDetails(AutoTicketingDetails autoTicketingDetails) {
19061879
this.autoTicketingDetails = autoTicketingDetails;
19071880
}
1881+
1882+
public Set<String> getMiniTestingServiceNames() {
1883+
return miniTestingServiceNames;
1884+
}
1885+
1886+
public void setMiniTestingServiceNames(Set<String> miniTestingServiceNames) {
1887+
this.miniTestingServiceNames = miniTestingServiceNames;
1888+
}
1889+
1890+
public void setSelectedMiniTestingServiceName(String selectedMiniTestingServiceName) {
1891+
this.selectedMiniTestingServiceName = selectedMiniTestingServiceName;
1892+
}
19081893
}

apps/dashboard/src/main/resources/struts.xml

+23-3
Original file line numberDiff line numberDiff line change
@@ -9362,9 +9362,9 @@
93629362
<result name="UNAUTHORIZED" type="json">
93639363
<param name="statusCode">403</param>
93649364
<param name="ignoreHierarchy">false</param>
9365-
<param name="includeProperties">^actionErrors.*</param>
9365+
<param name="includeProperties">^actionErrors.*</param>
93669366
</result>
9367-
</action>
9367+
</action>
93689368

93699369
<action name="api/fetchAzureBoardsIntegration" class="com.akto.action.AzureBoardsIntegrationAction" method="fetchAzureBoardsIntegration" >
93709370
<interceptor-ref name="json"/>
@@ -9611,8 +9611,28 @@
96119611
<param name="ignoreHierarchy">false</param>
96129612
<param name="includeProperties">^actionErrors.*</param>
96139613
</result>
9614-
</action>
9614+
</action>
96159615

9616+
<action name="api/fetchMiniTestingServiceNames" class="com.akto.action.testing.StartTestAction" method="fetchMiniTestingServiceNames">
9617+
<interceptor-ref name="json"/>
9618+
<interceptor-ref name="defaultStack" />
9619+
<interceptor-ref name="roleAccessInterceptor">
9620+
<param name="featureLabel">TEST_RESULTS</param>
9621+
<param name="accessType">READ</param>
9622+
</interceptor-ref>
9623+
9624+
<result name="FORBIDDEN" type="json">
9625+
<param name="statusCode">403</param>
9626+
<param name="ignoreHierarchy">false</param>
9627+
<param name="includeProperties">^actionErrors.*</param>
9628+
</result>
9629+
<result name="SUCCESS" type="json" />
9630+
<result name="ERROR" type="json">
9631+
<param name="statusCode">422</param>
9632+
<param name="ignoreHierarchy">false</param>
9633+
<param name="includeProperties">^actionErrors.*</param>
9634+
</result>
9635+
</action>
96169636

96179637

96189638
</package>

apps/dashboard/src/test/java/com/akto/action/TestAccountAction.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ public class TestAccountAction extends MongoBasedTest {
2222

2323
@Test
2424
public void testInitializeAccount() {
25-
Context.accountId.set(ACCOUNT_ID);
25+
int testAccount = ACCOUNT_ID + 100;
26+
Context.accountId.set(testAccount);
2627
String email = "[email protected]";
2728
int newAccountId = 12390;
2829
String newAccountName = "NEW_ACCOUNT";
2930
Map<String, UserAccountEntry> accounts = new HashMap<>();
30-
accounts.put(ACCOUNT_ID + "", new UserAccountEntry(ACCOUNT_ID));
31+
accounts.put(testAccount + "", new UserAccountEntry(testAccount));
3132
UsersDao.instance.deleteAll(new BasicDBObject());
3233
RBACDao.instance.deleteAll(new BasicDBObject());
3334
UsersDao.instance.insertOne(new User("test", "[email protected]", accounts, null));
3435
User user = UsersDao.instance.findOne(new BasicDBObject());
35-
RBACDao.instance.insertOne(new RBAC(user.getId(), RBAC.Role.ADMIN.name(), ACCOUNT_ID));
36+
RBACDao.instance.insertOne(new RBAC(user.getId(), RBAC.Role.ADMIN.name(), testAccount));
3637
List<RBAC> rbacList = RBACDao.instance.findAll(new BasicDBObject());
3738

3839
assertEquals(1, user.getAccounts().size());
@@ -47,7 +48,7 @@ public void testInitializeAccount() {
4748

4849
Role role = RBACDao.getCurrentRoleForUser(user.getId(), newAccountId);
4950
assertEquals(Role.ADMIN, role);
50-
role = RBACDao.getCurrentRoleForUser(user.getId(), ACCOUNT_ID);
51+
role = RBACDao.getCurrentRoleForUser(user.getId(), testAccount);
5152
assertEquals(Role.ADMIN, role);
5253

5354

apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -579,20 +579,20 @@ export default {
579579
data: {}
580580
})
581581
},
582-
scheduleTestForCollection(apiCollectionId, startTimestamp, recurringDaily, recurringWeekly, recurringMonthly, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds = [], autoTicketingDetails) {
582+
scheduleTestForCollection(apiCollectionId, startTimestamp, recurringDaily, recurringWeekly, recurringMonthly, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds = [], selectedMiniTestingServiceName, autoTicketingDetails) {
583583
return request({
584584
url: '/api/startTest',
585585
method: 'post',
586-
data: { apiCollectionId, type: "COLLECTION_WISE", startTimestamp, recurringDaily, recurringWeekly, recurringMonthly,selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds, autoTicketingDetails}
586+
data: { apiCollectionId, type: "COLLECTION_WISE", startTimestamp, recurringDaily, recurringWeekly, recurringMonthly,selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds, selectedMiniTestingServiceName, autoTicketingDetails}
587587
}).then((resp) => {
588588
return resp
589589
})
590590
},
591-
scheduleTestForCustomEndpoints(apiInfoKeyList, startTimestamp, recurringDaily, recurringWeekly, recurringMonthly, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds = [], autoTicketingDetails) {
591+
scheduleTestForCustomEndpoints(apiInfoKeyList, startTimestamp, recurringDaily, recurringWeekly, recurringMonthly, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds = [], selectedMiniTestingServiceName, autoTicketingDetails) {
592592
return request({
593593
url: '/api/startTest',
594594
method: 'post',
595-
data: {apiInfoKeyList, type: "CUSTOM", startTimestamp, recurringDaily, recurringWeekly, recurringMonthly,selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds, autoTicketingDetails}
595+
data: {apiInfoKeyList, type: "CUSTOM", startTimestamp, recurringDaily, recurringWeekly, recurringMonthly,selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source, testRoleId, continuousTesting, sendSlackAlert, sendMsTeamsAlert, testConfigsAdvancedSettings, cleanUpTestingResources, testSuiteIds, selectedMiniTestingServiceName, autoTicketingDetails}
596596
}).then((resp) => {
597597
return resp
598598
})

0 commit comments

Comments
 (0)