Skip to content

Commit

Permalink
Merge pull request akto-api-security#340 from akto-api-security/featu…
Browse files Browse the repository at this point in the history
…re/change_test_host

ask for new host while running test
  • Loading branch information
ankush-jain-akto committed Jun 14, 2023
2 parents 532ed97 + e8af7eb commit fcbdcd2
Show file tree
Hide file tree
Showing 46 changed files with 235 additions and 1,970 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
import com.akto.log.LoggerMaker.LogDb;
import com.akto.util.Constants;
import com.akto.util.enums.GlobalEnums.TestErrorSource;
import com.akto.utils.Utils;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.model.Updates;
import org.apache.commons.lang3.StringUtils;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;

Expand Down Expand Up @@ -59,6 +61,7 @@ public class StartTestAction extends UserAction {
private String triggeredBy;
private boolean isTestRunByTestEditor;

private String overriddenTestAppUrl;
private static final LoggerMaker loggerMaker = new LoggerMaker(StartTestAction.class);

private static List<ObjectId> getCicdTests(){
Expand All @@ -75,6 +78,15 @@ private static List<ObjectId> getCicdTests(){
private TestingRun createTestingRun(int scheduleTimestamp, int periodInSeconds) {
User user = getSUser();

if (!StringUtils.isEmpty(this.overriddenTestAppUrl)) {
boolean isValidUrl = Utils.isValidURL(this.overriddenTestAppUrl);

if (!isValidUrl) {
addActionError("The override url is invalid. Please check the url again.");
return null;
}
}

AuthMechanism authMechanism = AuthMechanismsDao.instance.findOne(new BasicDBObject());
if (authMechanism == null && testIdConfig == 0) {
addActionError("Please set authentication mechanism before you test any APIs");
Expand Down Expand Up @@ -107,7 +119,7 @@ private TestingRun createTestingRun(int scheduleTimestamp, int periodInSeconds)
return null;
}
if (this.selectedTests != null) {
TestingRunConfig testingRunConfig = new TestingRunConfig(Context.now(), null, this.selectedTests,authMechanism.getId());
TestingRunConfig testingRunConfig = new TestingRunConfig(Context.now(), null, this.selectedTests,authMechanism.getId(), this.overriddenTestAppUrl);
this.testIdConfig = testingRunConfig.getId();
TestingRunConfigDao.instance.insertOne(testingRunConfig);
}
Expand Down Expand Up @@ -518,6 +530,14 @@ public void setIsTestRunByTestEditor(boolean testRunByTestEditor) {
isTestRunByTestEditor = testRunByTestEditor;
}

public void setOverriddenTestAppUrl(String overriddenTestAppUrl) {
this.overriddenTestAppUrl = overriddenTestAppUrl;
}

public String getOverriddenTestAppUrl() {
return overriddenTestAppUrl;
}

public enum CallSource{
TESTING_UI,
AKTO_GPT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ public static void webhookSenderUtil(CustomWebhook webhook) {
OriginalHttpResponse response = null; // null response means api request failed. Do not use new OriginalHttpResponse() in such cases else the string parsing fails.

try {
response = ApiExecutor.sendRequest(request, true);
response = ApiExecutor.sendRequest(request, true, null);
loggerMaker.infoAndAddToDb("webhook request sent", LogDb.DASHBOARD);
} catch (Exception e) {
errors.add("API execution failed");
Expand Down Expand Up @@ -985,7 +985,7 @@ public void updateDeploymentStatus(BackwardCompatibility backwardCompatibility)
String headers = "{\"Content-Type\": \"application/json\"}";
OriginalHttpRequest request = new OriginalHttpRequest(getUpdateDeploymentStatusUrl(), "", "POST", body, OriginalHttpRequest.buildHeadersMap(headers), "");
try {
OriginalHttpResponse response = ApiExecutor.sendRequest(request, false);
OriginalHttpResponse response = ApiExecutor.sendRequest(request, false, null);
loggerMaker.infoAndAddToDb(String.format("Update deployment status reponse: %s", response.getBody()), LogDb.DASHBOARD);
} catch (Exception e) {
loggerMaker.errorAndAddToDb(String.format("Failed to update deployment status, will try again on next boot up : %s", e.toString()), LogDb.DASHBOARD);
Expand Down
14 changes: 13 additions & 1 deletion apps/dashboard/src/main/java/com/akto/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.*;
import java.util.regex.Matcher;
Expand All @@ -49,6 +52,15 @@ public static Map<String, String> getVariableMap(ArrayNode variables){
return result;
}

public static boolean isValidURL(String url) {
try {
new URL(url).toURI();
return true;
} catch (MalformedURLException | URISyntaxException e) {
return false;
}
}

public static String replaceVariables(String payload, Map<String, String> variableMap) {
String regex = "\\{\\{(.*?)\\}\\}";
Pattern p = Pattern.compile(regex);
Expand Down Expand Up @@ -115,7 +127,7 @@ public static Map<String, String> convertApiInAktoFormat(JsonNode apiInfo, Map<S

OriginalHttpRequest originalHttpRequest = new OriginalHttpRequest(result.get("path"), "", result.get("method"), requestPayload, reqHeadersListMap , "http");
try {
OriginalHttpResponse res = ApiExecutor.sendRequest(originalHttpRequest, true);
OriginalHttpResponse res = ApiExecutor.sendRequest(originalHttpRequest, true, null);
responseHeadersString = convertHeaders(res.getHeaders());
responsePayload = res.getBody();
statusCode = res.getStatusCode()+"";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.*;

import com.akto.utils.Utils;
import org.junit.Test;

import com.akto.MongoBasedTest;
Expand Down Expand Up @@ -163,4 +164,9 @@ public void testDeleteCustomWebhook(){
assertEquals(1,customWebhooks.size());
}

@Test
public void testValidURL() {
System.out.println(Utils.isValidURL("asdad"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
</div>
<v-checkbox v-model="recurringDaily" label="Run daily" on-icon="$far_check-square"
off-icon="$far_square" class="run-daily-box" :ripple="false" />

</div>
<div class="d-flex">
<v-checkbox v-model="hasOverriddenTestAppUrl" label="Use different target for testing" on-icon="$far_check-square"
off-icon="$far_square" class="run-daily-box" :ripple="false" />

<v-text-field v-if="hasOverriddenTestAppUrl"
class="form-field-text"
type="text"
label="Override test app host"
v-model="overriddenTestAppUrl"
></v-text-field>

</div>
<div class="d-flex">
</div>
<div class="d-flex" style="gap: 20px">
<div>
Expand Down Expand Up @@ -53,11 +68,13 @@
<script>
import func from '@/util/func'
import SimpleMenu from "@/apps/dashboard/shared/components/SimpleMenu"
import SimpleTextField from '@/apps/dashboard/shared/components/SimpleTextField'
export default {
name: "ScheduleBox",
components: {
SimpleMenu
SimpleMenu,
SimpleTextField
},
data() {
let hours = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Expand Down Expand Up @@ -97,6 +114,8 @@ export default {
return {
startTimestamp: func.timeNow(),
overriddenTestAppUrl: '',
hasOverriddenTestAppUrl: false,
label: "Now",
recurringDaily: false,
hourlyTimes: [{ label: "Now", click: () => this.setForNow() }, ...amTimes, ...pmTimes],
Expand Down Expand Up @@ -131,8 +150,9 @@ export default {
this.label = "Now"
},
schedule() {
let overriddenHost = this.hasOverriddenTestAppUrl ? this.overriddenTestAppUrl : null
return this.$emit("schedule", { recurringDaily: this.recurringDaily, startTimestamp: this.startTimestamp,
testRunTime : this.testRunTime, maxConcurrentRequests: this.maxConcurrentRequests})
testRunTime : this.testRunTime, maxConcurrentRequests: this.maxConcurrentRequests, overriddenTestAppUrl: overriddenHost})
}
},
computed: {
Expand Down Expand Up @@ -180,3 +200,39 @@ export default {
opacity: 1 !important
}
</style>


<style scoped lang="sass">
.form-field-text
padding-top: 0px !important
margin-top: 0px !important
margin-left: 20px
</style>

<style scoped>
.form-field-text >>> .v-label {
font-size: 12px;
color: var(--themeColor);
font-weight: 400;
}
.form-field-text >>> input {
font-size: 12px;
color: var(--themeColorDark) !important;
}
.form-field-text >>> .v-text-field__details {
display: none !important;
}
.form-field-text >>> .v-input__slot {
margin-bottom: 0px !important;
}
.run-daily-box >>> .v-text-field__details {
display: none !important;
}
.run-daily-box >>> .v-input__slot {
margin-bottom: 0px !important;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -530,16 +530,16 @@ export default {
}
})
},
async startTest({recurringDaily, startTimestamp, selectedTests, testName, testRunTime, maxConcurrentRequests}) {
async startTest({recurringDaily, startTimestamp, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl}) {
let apiInfoKeyList = this.toApiInfoKeyList(this.filteredItemsForScheduleTest)
let filtersSelected = this.filteredItemsForScheduleTest.length === this.allEndpoints.length
let store = this.$store
let apiCollectionId = this.apiCollectionId
if (filtersSelected) {
await store.dispatch('testing/scheduleTestForCollection', {apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests})
await store.dispatch('testing/scheduleTestForCollection', {apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl})
} else {
await store.dispatch('testing/scheduleTestForCustomEndpoints', {apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, source: "TESTING_UI"})
await store.dispatch('testing/scheduleTestForCustomEndpoints', {apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source: "TESTING_UI"})
}
this.showTestSelectorDialog = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default {
let currObj = this.mapCategoryToSubcategory[this.selectedCategory]
currObj.selected = this.globalCheckbox ? [...currObj.all] : []
},
emitTestSelection({recurringDaily, startTimestamp, testRunTime, maxConcurrentRequests}) {
emitTestSelection({recurringDaily, startTimestamp, testRunTime, maxConcurrentRequests, overriddenTestAppUrl}) {
if (!this.testName) {
window._AKTO.$emit('SHOW_SNACKBAR', {
show: true,
Expand All @@ -165,7 +165,8 @@ export default {
selectedTests,
testRunTime,
maxConcurrentRequests,
testName: this.testName
testName: this.testName,
overriddenTestAppUrl
}
return this.$emit('testsSelected', ret)
},
Expand Down Expand Up @@ -235,14 +236,16 @@ export default {
.category-list-container
width: 40%
min-width: 40%
max-width: 40%
flex-grow: 0
.test-list
height: 400px
height: 350px
overflow: scroll
.category-list
height: 400px
height: 350px
overflow: scroll
.column-title
Expand Down
8 changes: 4 additions & 4 deletions apps/dashboard/web/src/apps/dashboard/views/testing/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,21 @@ export default {
})
},

scheduleTestForCustomEndpoints(apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, source) {
scheduleTestForCustomEndpoints(apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source) {
return request({
url: '/api/startTest',
method: 'post',
data: {apiInfoKeyList, type: "CUSTOM", startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, source}
data: {apiInfoKeyList, type: "CUSTOM", startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source}
}).then((resp) => {
return resp
})
},

scheduleTestForCollection(apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests) {
scheduleTestForCollection(apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl) {
return request({
url: '/api/startTest',
method: 'post',
data: {apiCollectionId, type: "COLLECTION_WISE", startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests}
data: {apiCollectionId, type: "COLLECTION_WISE", startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl}
}).then((resp) => {
return resp
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ const testing = {
commit('SAVE_TESTING_RUNS', resp)
})
},
scheduleTestForCollection({commit}, {apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName,testRunTime, maxConcurrentRequests} ) {
return api.scheduleTestForCollection(apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests).then((resp) => {
scheduleTestForCollection({commit}, {apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName,testRunTime, maxConcurrentRequests, overriddenTestAppUrl} ) {
return api.scheduleTestForCollection(apiCollectionId, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl).then((resp) => {
commit('SAVE_TESTING_RUNS', resp)
})
},
Expand All @@ -85,8 +85,8 @@ const testing = {
commit('SAVE_TESTING_RUNS', resp)
})
},
scheduleTestForCustomEndpoints({commit}, {apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, source} ) {
return api.scheduleTestForCustomEndpoints(apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, source).then((resp) => {
scheduleTestForCustomEndpoints({commit}, {apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source} ) {
return api.scheduleTestForCustomEndpoints(apiInfoKeyList, startTimestamp, recurringDaily, selectedTests, testName, testRunTime, maxConcurrentRequests, overriddenTestAppUrl, source).then((resp) => {
commit('SAVE_TESTING_RUNS', resp)
})
},
Expand Down
26 changes: 0 additions & 26 deletions apps/testing/src/main/java/com/akto/rules/AddJkuToJwtTest.java

This file was deleted.

This file was deleted.

Loading

0 comments on commit fcbdcd2

Please sign in to comment.