Skip to content

Commit

Permalink
Merge pull request #1351 from akto-api-security/feature/pre_script
Browse files Browse the repository at this point in the history
Feature/pre script
  • Loading branch information
ayushaga14 authored Aug 23, 2024
2 parents 56cd17d + d0bca09 commit 0f1015d
Show file tree
Hide file tree
Showing 9 changed files with 469 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.akto.dto.testing.GenericTestResult;
import com.akto.dto.testing.MultiExecTestResult;
import com.akto.dto.testing.TestResult;
import com.akto.dto.testing.TestingRunConfig;
import com.akto.dto.testing.TestResult.Confidence;
import com.akto.dto.testing.TestingRunResult;
import com.akto.dto.testing.WorkflowNodeDetails;
Expand Down Expand Up @@ -329,7 +330,8 @@ public String runTestForGivenTemplate() {
List<TestingRunResult.TestLog> testLogs = new ArrayList<>();
int lastSampleIndex = sampleDataList.get(0).getSamples().size() - 1;

testingRunResult = executor.runTestNew(infoKey, null, testingUtil, null, testConfig, null, true, testLogs);
TestingRunConfig testingRunConfig = new TestingRunConfig();
testingRunResult = executor.runTestNew(infoKey, null, testingUtil, null, testConfig, testingRunConfig, true, testLogs);
if (testingRunResult == null) {
testingRunResult = new TestingRunResult(
new ObjectId(), infoKey, testConfig.getInfo().getCategory().getName(), testConfig.getInfo().getSubCategory() ,Collections.singletonList(new TestResult(null, sampleDataList.get(0).getSamples().get(lastSampleIndex),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.akto.action.testing;

import java.util.UUID;

import org.apache.commons.lang3.NotImplementedException;
import org.bson.conversions.Bson;

import com.akto.action.UserAction;
import com.akto.dao.context.Context;
import com.akto.dao.testing.config.TestScriptsDao;
import com.akto.dto.testing.config.TestScript;
import com.akto.util.DashboardMode;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.opensymphony.xwork2.Action;

public class ScriptAction extends UserAction {

@Override
public String execute() throws Exception {
throw new NotImplementedException();
}

private TestScript testScript;

public String addScript() {

if (!DashboardMode.isSaasDeployment()) {
return Action.ERROR.toUpperCase();
}
if (this.testScript == null || this.testScript.getJavascript() == null) {
return Action.ERROR.toUpperCase();
}

TestScriptsDao.instance.insertOne(
new TestScript(
UUID.randomUUID().toString(),
this.testScript.getJavascript(),
TestScript.Type.PRE_REQUEST,
getSUser().getLogin(),
Context.now()
)
);

return Action.SUCCESS.toUpperCase();
}

public String fetchScript() {
this.testScript = TestScriptsDao.instance.findOne(new BasicDBObject());
return Action.SUCCESS.toUpperCase();
}

public String updateScript() {

if (!DashboardMode.isSaasDeployment()) {
return Action.ERROR.toUpperCase();
}

if (this.testScript == null || this.testScript.getJavascript() == null) {
return Action.ERROR.toUpperCase();
}

Bson filterQ = Filters.eq("_id", testScript.getId());
Bson updateQ =
Updates.combine(
Updates.set(TestScript.JAVASCRIPT, this.testScript.getJavascript()),
Updates.set(TestScript.AUTHOR, getSUser().getLogin()),
Updates.set(TestScript.LAST_UPDATED_AT, Context.now())
);
TestScriptsDao.instance.updateOne(filterQ, updateQ);
return Action.SUCCESS.toUpperCase();
}

public TestScript getTestScript() {
return testScript;
}

public void setTestScript(TestScript testScript) {
this.testScript = testScript;
}
}
74 changes: 74 additions & 0 deletions apps/dashboard/src/main/resources/struts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6028,6 +6028,80 @@
</result>
</action>

<action name="api/updateScript" class="com.akto.action.testing.ScriptAction" method="updateScript">
<interceptor-ref name="json"/>
<interceptor-ref name="defaultStack" />
<interceptor-ref name="roleAccessInterceptor">
<param name="featureLabel">USER_ACTIONS</param>
<param name="accessType">READ_WRITE</param>
</interceptor-ref>
<interceptor-ref name="usageInterceptor">
<param name="featureLabel">TEST_PRE_SCRIPT</param>
</interceptor-ref>

<result name="FORBIDDEN" type="json">
<param name="statusCode">403</param>
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">^actionErrors.*</param>
</result>
<result name="SUCCESS" type="json">
</result>
<result name="ERROR" type="json">
<param name="statusCode">422</param>
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">^actionErrors.*</param>
</result>
</action>

<action name="api/fetchScript" class="com.akto.action.testing.ScriptAction" method="fetchScript">
<interceptor-ref name="json"/>
<interceptor-ref name="defaultStack" />

<interceptor-ref name="roleAccessInterceptor">
<param name="featureLabel">USER_ACTIONS</param>
<param name="accessType">READ_WRITE</param>
</interceptor-ref>

<result name="FORBIDDEN" type="json">
<param name="statusCode">403</param>
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">^actionErrors.*</param>
</result>
<result name="SUCCESS" type="json">
</result>
<result name="ERROR" type="json">
<param name="statusCode">422</param>
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">^actionErrors.*</param>
</result>
</action>

<action name="api/addScript" class="com.akto.action.testing.ScriptAction" method="addScript">
<interceptor-ref name="json"/>
<interceptor-ref name="defaultStack" />
<interceptor-ref name="roleAccessInterceptor">
<param name="featureLabel">USER_ACTIONS</param>
<param name="accessType">READ_WRITE</param>
</interceptor-ref>
<interceptor-ref name="usageInterceptor">
<param name="featureLabel">TEST_PRE_SCRIPT</param>
</interceptor-ref>

<result name="FORBIDDEN" type="json">
<param name="statusCode">403</param>
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">^actionErrors.*</param>
</result>
<result name="SUCCESS" type="json">
</result>
<result name="ERROR" type="json">
<param name="statusCode">422</param>
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">^actionErrors.*</param>
</result>
</action>


</package>

</struts>
Original file line number Diff line number Diff line change
Expand Up @@ -406,4 +406,25 @@ export default {
data: {reportId, organizationName, reportDate, reportUrl}
})
},
fetchScript() {
return request({
url: '/api/fetchScript',
method: 'post',
data: {}
})
},
addScript({javascript}) {
return request({
url: '/api/addScript',
method: 'post',
data: {testScript:{javascript}}
})
},
updateScript(id, javascript) {
return request({
url: '/api/updateScript',
method: 'post',
data: {testScript:{id, javascript}}
})
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Button, Collapsible, Divider, LegacyCard, LegacyStack, Text } from "@shopify/polaris"
import { TextField, Button, Collapsible, Divider, LegacyCard, LegacyStack, Text } from "@shopify/polaris"
import { ChevronRightMinor, ChevronDownMinor } from '@shopify/polaris-icons';
import { useState } from "react";
import api from "../api"
Expand All @@ -20,9 +20,14 @@ function UserConfig() {
const [isLoading, setIsLoading] = useState(true)
const [hardcodedOpen, setHardcodedOpen] = useState(true);
const [initialLimit, setInitialLimit] = useState(0);
const [preRequestScript, setPreRequestScript] = useState({javascript: ""});

const handleToggleHardcodedOpen = () => setHardcodedOpen((prev) => !prev)

const handlePreRequestScriptChange = (value) => {
setPreRequestScript({...preRequestScript, javascript: value})
}

async function fetchAuthMechanismData() {
setIsLoading(true)
const authMechanismDataResponse = await api.fetchAuthMechanismData()
Expand All @@ -36,13 +41,27 @@ function UserConfig() {
await settingRequests.fetchAdminSettings().then((resp)=> {
setInitialLimit(resp.accountSettings.globalRateLimit);
})

await api.fetchScript().then((resp)=> {
if (resp) {
setPreRequestScript(resp.testScript)
}
});
setIsLoading(false)
}

useEffect(() => {
fetchAuthMechanismData()
}, [])

async function addOrUpdateScript() {
if (preRequestScript.id) {
api.updateScript(preRequestScript.id, preRequestScript.javascript)
} else {
api.addScript(preRequestScript)
}
}

async function handleStopAllTests() {
await api.stopAllTests()
setToastConfig({ isActive: true, isError: false, message: "All tests stopped!" })
Expand Down Expand Up @@ -121,7 +140,6 @@ function UserConfig() {
<Divider />
<LegacyCard.Section>
<div style={{ display: "grid", gridTemplateColumns: "max-content max-content", gap: "10px", alignItems: "center" }}>
<Text>Allowed requests / min:</Text>
<Dropdown
selected={handleSelect}
menuItems={dropdownItems}
Expand All @@ -135,7 +153,34 @@ function UserConfig() {
</LegacyCard>
)

const components = [<TestCollectionConfiguration/>, rateLimit]
const preRequestScriptComponent = (
<LegacyCard sectioned title="Configure Pre-request script" key="preRequestScript" primaryFooterAction={

{
content: "Save", destructive: false, onAction: () => {addOrUpdateScript()}
}

}>
<Divider />
<LegacyCard.Section>
<div style={{ display: "grid", gridTemplateColumns: "1fr", gap: "10px", alignItems: "center" }}>
<TextField
placeholder="Enter pre-request javascript here..."
value={preRequestScript?.javascript || ""}
onChange={handlePreRequestScriptChange}
multiline={10}
monospaced
autoComplete="off"
/>

</div>
</LegacyCard.Section>


</LegacyCard>
)

const components = [<TestCollectionConfiguration/>, rateLimit, preRequestScriptComponent]

return (
isLoading ? <SpinnerCentered />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.akto.dao.testing.config;

import com.akto.dao.*;
import com.akto.dto.testing.config.TestScript;
import com.mongodb.BasicDBObject;

public class TestScriptsDao extends AccountsContextDao<TestScript> {

public static final TestScriptsDao instance = new TestScriptsDao();

private TestScriptsDao() {}

public TestScript fetchTestScript() {
return TestScriptsDao.instance.findOne(new BasicDBObject());
}

@Override
public String getCollName() {
return "test_collection_properties";
}

@Override
public Class<TestScript> getClassT() {
return TestScript.class;
}
}
14 changes: 14 additions & 0 deletions libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.akto.util.HttpRequestResponseUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ctc.wstx.shaded.msv_core.util.Uri;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.mongodb.BasicDBObject;
Expand Down Expand Up @@ -223,6 +224,19 @@ public String getFullUrlIncludingDomain() throws Exception {
return url;
}

public String getUrlPath() throws Exception {
if (!url.startsWith("http")) {
return url;
} else {
try {
URI uri = new URI(url);
return uri.getPath();
} catch (Exception e) {
return url;
}
}
}

public String getFullUrlWithParams() {
return getFullUrlWithParams(this.url, this.queryParams);
}
Expand Down
Loading

0 comments on commit 0f1015d

Please sign in to comment.