diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e4f7434c5f..6bfd068f08 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -36,7 +36,7 @@ If you find a bug or have an idea for a new feature, please open an issue on Git
## License
-By contributing to this project, you agree that your contributions will be licensed under the [LICENSE](LICENSE) file.
+By contributing to this project, you agree that your contributions will be licensed under the [LICENSE](https://github.com/akto-api-security/akto/blob/master/LICENSE.md) file.
## Contact
diff --git a/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java b/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java
index f73d8104ba..3e6bc319b7 100644
--- a/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java
+++ b/apps/dashboard/src/main/java/com/akto/listener/RuntimeListener.java
@@ -238,7 +238,7 @@ public static void addLlmSampleData(int accountId) {
}
try {
- String mockServiceUrl = "http://sampl-aktol-1exannwybqov-67928726.ap-south-1.elb.amazonaws.com:5000";
+ String mockServiceUrl = "https://vuln-llm.akto.io";
String data = convertStreamToString(InitializerListener.class.getResourceAsStream("/LlmSampleApiData.json"));
JSONArray dataobject = new JSONArray(data);
for (Object obj: dataobject) {
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/DropdownSearch.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/DropdownSearch.jsx
index 373ba57eac..5b18124b63 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/DropdownSearch.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/DropdownSearch.jsx
@@ -6,7 +6,7 @@ function DropdownSearch(props) {
const id = props.id ? props.id : "dropdown-search"
- const { disabled, label, placeholder, optionsList, setSelected, value , avatarIcon, preSelected, allowMultiple, itemName} = props
+ const { disabled, label, placeholder, optionsList, setSelected, value , avatarIcon, preSelected, allowMultiple, itemName, dropdownSearchKey} = props
const deselectedOptions = optionsList
const [selectedOptions, setSelectedOptions] = useState(preSelected ? preSelected : []);
@@ -56,8 +56,9 @@ function DropdownSearch(props) {
return;
}
const filterRegex = new RegExp(value, 'i');
+ const searchKey = dropdownSearchKey ? dropdownSearchKey : "label"
const resultOptions = deselectedOptions.filter((option) =>
- option.label.match(filterRegex),
+ option[searchKey].match(filterRegex)
);
setOptions(resultOptions);
setLoading(false);
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/customDiffEditor.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/customDiffEditor.js
index 7ade628db8..037c4295ac 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/customDiffEditor.js
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/components/shared/customDiffEditor.js
@@ -77,7 +77,7 @@ const transform = {
if(!isNaN(key)){
ret.push(parsedJson[key])
}else{
- ret.push({key: parsedJson[key]})
+ ret.push({[key]: parsedJson[key]})
}
})
return JSON.stringify(ret, null, 2)
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx
index 41626613a5..0648d2ffc7 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/observe/api_collections/ApiCollections.jsx
@@ -153,7 +153,7 @@ function ApiCollections() {
}}
>
-
+ func.handleKeyPress(e, createNewCollection)}>
-
+
)
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/QuickStart.css b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/QuickStart.css
index ec9cf4f379..2b4c218085 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/QuickStart.css
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/QuickStart.css
@@ -69,4 +69,14 @@
.update-connections .Polaris-Page--divider{
padding-top: 20px !important;
+}
+
+.overflow-text{
+ text-overflow: ellipsis;
+ overflow-x: hidden;
+ white-space: nowrap;
+}
+
+.right-card .Polaris-Scrollable{
+ overflow-x: hidden;
}
\ No newline at end of file
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/api.js b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/api.js
index a29a6e8b91..fe81939abd 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/api.js
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/api.js
@@ -67,6 +67,24 @@ const api = {
method: 'post',
data: {deploymentMethod}
})
+ },
+ fetchBurpPluginDownloadLink() {
+ return request({
+ url: '/api/fetchBurpPluginDownloadLink',
+ method: 'post',
+ data: {},
+ }).then((resp) => {
+ return resp
+ })
+ },
+ fetchBurpCredentials() {
+ return request({
+ url: '/api/fetchBurpCredentials',
+ method: 'post',
+ data: {},
+ }).then((resp) => {
+ return resp
+ })
}
}
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/BurpSource.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/BurpSource.jsx
index 76ccb3d3ac..4edb61020b 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/BurpSource.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/BurpSource.jsx
@@ -1,77 +1,104 @@
-import { Button, ButtonGroup, HorizontalStack, Icon, Spinner, Text, VerticalStack } from '@shopify/polaris'
-import React, { useState } from 'react'
-import { StatusActiveMajor } from "@shopify/polaris-icons"
+import { Box, Button, ButtonGroup, HorizontalStack, Text, VerticalStack } from '@shopify/polaris'
+import React, { useEffect, useState } from 'react'
import {useNavigate} from "react-router-dom"
import api from '../api'
-import func from '@/util/func'
-
+import func from "@/util/func"
+
function BurpSource() {
+ const navigate = useNavigate()
+ const [burpGithubLink, setBurpGithubLink] = useState("");
+ const [aktoIp, setAktoIp] = useState("");
+ const [aktoToken, setAktoToken] = useState("");
+ const [burpCollectionURL, setBurpCollectionURL] = useState("")
+
+ const getGithubLink = async() => {
+ await api.fetchBurpPluginDownloadLink().then((resp) => {
+ if (resp && resp.burpGithubLink) {
+ setBurpGithubLink(resp?.burpGithubLink)
+ }
+ })
+ }
+
+ const getCredentials = async() => {
+ await api.fetchBurpCredentials().then((resp) => {
+ if (!resp) return
+ setAktoIp(resp?.host)
+ setAktoToken(resp?.apiToken?.key)
+ })
+ }
+
+ const downloadBurpJar = async() => {
+ let downloadTime = func.timeNow()
+ let showBurpPluginConnectedFlag = false
- const [downloadInfo, setDownloadInfo] = useState(0)
- const [initialData, setInitialData] = useState(0)
- const [finalData, setFinalData] = useState(0)
-
- const downloadBurpExt = async() => {
- setDownloadInfo(1)
- await api.downloadBurpPluginJar().then((resp)=> {
- let downloadTime = func.timeNow()
-
- const href = URL.createObjectURL(resp);
- // create "a" HTML element with href to file & click
- const link = document.createElement('a');
- link.href = href;
- link.setAttribute('download', 'Akto.jar'); //or any other extension
- document.body.appendChild(link);
- link.click();
- // clean up "a" element & remove ObjectURL
- document.body.removeChild(link);
- URL.revokeObjectURL(href);
-
- setDownloadInfo(2)
- setInitialData(1)
-
- let interval = setInterval(() => {
- api.fetchBurpPluginInfo().then((response) => {
- let lastBootupTimestamp = response.burpPluginInfo.lastBootupTimestamp
+ await api.downloadBurpPluginJar()
+ window.open(burpGithubLink)
+
+ let interval = setInterval(() => {
+ api.fetchBurpPluginInfo().then((response) => {
+ let lastBootupTimestamp = response?.burpPluginInfo?.lastBootupTimestamp
if (lastBootupTimestamp > downloadTime) {
- setInitialData(2)
- setFinalData(1)
+ if (showBurpPluginConnectedFlag) {
+ func.setToast(true, false, "Burp plugin connected")
+ }
+ showBurpPluginConnectedFlag = false
if (response.burpPluginInfo.lastDataSentTimestamp > downloadTime) {
clearInterval(interval)
- setFinalData(2)
+ setBurpCollectionURL("/dashboard/observe/inventory")
+ func.setToast(true, false, "Data received from burp plugin")
}
}
})
- }, 5000)
- })
+ }, 2000)
+
}
- const navigate = useNavigate()
- const DownloadTextComponent = ({param_value}) => {
- switch(param_value){
- case 1:
- return ()
- case 2:
- return (
)
- default:
- return null
- }
+ const copyText = (text,messageText) => {
+ navigator.clipboard.writeText(text)
+ func.setToast(true, false, `${messageText} is copied to clipboard.`)
}
const steps = [
{
- text: "Download Akto's Burp extension.",
- component: ,
- textComponent:
+ text: "Download akto's burp extension",
+ component: ,
+ },
+ {
+ text: "Open Burp and add the downloaded jar file in extension tab."
+ },
+ {
+ text: 'Once the plugin is loaded click on "options" tab inside the plugin.'
},
{
- text: "Open Burp and add the downloaded jar file in extension tab.",
- textComponent:
+ text: "Copy the AKTO_IP and AKTO_TOKEN and paste in the options tab.",
+ component: (
+
+
+
+ AKTO_IP:
+
+
+
+ AKTO_TOKEN:
+
+
+
+
+ )
},
{
- text: "Start Burp proxy and browse any website. You will see traffic in 'Burp' collection in inventory.",
- textComponent: ,
- component: finalData === 2 ? : null
+ text: "Start Burp proxy and browse any website.",
+ component: (
+
+ You will see traffic in
+ {burpCollectionURL.length > 0 ? : Burp}
+ collection.
+
+ )
}
]
@@ -83,6 +110,11 @@ function BurpSource() {
navigate("/dashboard/settings/integrations/burp")
}
+ useEffect(()=> {
+ getGithubLink()
+ getCredentials()
+ },[])
+
return (
@@ -93,14 +125,10 @@ function BurpSource() {
{steps.map((element,index) => (
- {index + 1}.
- {element.text}
- {element.textComponent}
-
-
-
- {element.component}
+ {index + 1}.
+ {element?.text}
+ {element?.component}
))}
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/NewConnection.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/NewConnection.jsx
index 8cb8d5ca16..4291d4577f 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/NewConnection.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/quick_start/components/NewConnection.jsx
@@ -106,7 +106,7 @@ function NewConnection() {
const trafficScreenLabel = (
- setConnector(item)}/>
+ setConnector(item)} dropdownSearchKey="value"/>
{connectors?.component}
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/TestEditor.css b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/TestEditor.css
index 2acef9d4e2..fadaf9e55b 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/TestEditor.css
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/TestEditor.css
@@ -58,4 +58,12 @@
.editor-header .Polaris-Text--root{
max-width: 30vw;
+}
+
+.req-resp-tabs .Polaris-LegacyTabs__Title{
+ padding: 8px 0 !important;
+}
+
+.req-resp-tabs .Polaris-Box{
+ border: none !important;
}
\ No newline at end of file
diff --git a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/components/SampleApi.jsx b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/components/SampleApi.jsx
index a14dbf993f..86c1c67e82 100644
--- a/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/components/SampleApi.jsx
+++ b/apps/dashboard/web/polaris_web/web/src/apps/dashboard/pages/test_editor/components/SampleApi.jsx
@@ -1,6 +1,5 @@
-import { Box, Button, Divider, Frame, HorizontalStack, LegacyTabs, Modal, VerticalStack} from "@shopify/polaris"
-import { tokens } from "@shopify/polaris-tokens"
-import { UpdateInventoryMajor, ChevronUpMinor } from "@shopify/polaris-icons"
+import { Box, Button, Divider, Frame, HorizontalStack, LegacyTabs, Modal, Text, Tooltip} from "@shopify/polaris"
+import {ChevronUpMinor } from "@shopify/polaris-icons"
import { useEffect, useRef, useState } from "react";
@@ -122,12 +121,12 @@ const SampleApi = () => {
const handleTabChange = (selectedTabIndex) => {
setSelected(selectedTabIndex)
-
if (sampleData) {
+
if (selectedTabIndex == 0) {
- editorInstance.setValue(JSON.stringify(sampleData.requestJson["json"], null, 2))
+ editorInstance.setValue('\n' + sampleData?.requestJson["firstLine"] + '\n\n' + JSON.stringify(sampleData.requestJson["json"], null, 2))
} else {
- editorInstance.setValue(JSON.stringify(sampleData.responseJson["json"], null, 2))
+ editorInstance.setValue('\n' + sampleData?.responseJson["firstLine"] + '\n\n' + JSON.stringify(sampleData.responseJson["json"], null, 2))
}
}
}
@@ -167,7 +166,7 @@ const SampleApi = () => {
setSampleData({ requestJson, responseJson })
if (editorInstance) {
- editorInstance.setValue(JSON.stringify(requestJson["json"], null, 2))
+ editorInstance.setValue('\n' + requestJson["firstLine"] + '\n\n' + JSON.stringify(requestJson["json"], null, 2))
}
setTimeout(()=> {
setSampleDataList(sampleDataResponse.sampleDataList)
@@ -254,9 +253,19 @@ const SampleApi = () => {
return (
-
-
-
+
+
+
+
+
+
+
diff --git a/apps/dashboard/web/polaris_web/web/src/util/func.js b/apps/dashboard/web/polaris_web/web/src/util/func.js
index 8e902ff39a..7e818977cb 100644
--- a/apps/dashboard/web/polaris_web/web/src/util/func.js
+++ b/apps/dashboard/web/polaris_web/web/src/util/func.js
@@ -1067,6 +1067,13 @@ getSizeOfFile(bytes) {
}
return duration.trim();
},
+ handleKeyPress (event, funcToCall) {
+ const enterKeyPressed = event.keyCode === 13;
+ if (enterKeyPressed) {
+ event.preventDefault();
+ funcToCall();
+ }
+ }
}
export default func
\ No newline at end of file
diff --git a/apps/testing/src/main/java/com/akto/test_editor/execution/VariableResolver.java b/apps/testing/src/main/java/com/akto/test_editor/execution/VariableResolver.java
index 15906b8105..9fabbdfca9 100644
--- a/apps/testing/src/main/java/com/akto/test_editor/execution/VariableResolver.java
+++ b/apps/testing/src/main/java/com/akto/test_editor/execution/VariableResolver.java
@@ -26,26 +26,25 @@ public static String resolveExpression(Map
varMap, String expres
Pattern pattern = Pattern.compile("\\$\\{[^}]*\\}");
Matcher matcher = pattern.matcher(expression);
- if (matcher.find()) {
+ while (matcher.find()) {
try {
String match = matcher.group(0);
match = match.substring(2, match.length());
match = match.substring(0, match.length() - 1);
Object val = getValue(varMap, match);
String valString = val.toString();
- expression = expression.replaceAll("(\\$\\{[^}]*\\})", valString);
+ expression = expression.replaceFirst("(\\$\\{[^}]*\\})", valString);
} catch (Exception e) {
return expression;
}
+ }
+
+ Object val = getValue(varMap, expression);
+ if (val == null) {
+ return expression;
} else {
- Object val = getValue(varMap, expression);
- if (val == null) {
- return expression;
- } else {
- return val.toString();
- }
+ return val.toString();
}
- return expression;
}
diff --git a/apps/testing/src/test/java/com/akto/test_editor/execution/TestVariableResolver.java b/apps/testing/src/test/java/com/akto/test_editor/execution/TestVariableResolver.java
new file mode 100644
index 0000000000..edc6aac402
--- /dev/null
+++ b/apps/testing/src/test/java/com/akto/test_editor/execution/TestVariableResolver.java
@@ -0,0 +1,47 @@
+package com.akto.test_editor.execution;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class TestVariableResolver {
+
+ @Test
+ public void testResolveExpression() {
+ Map varMap = new HashMap<>();
+ varMap.put("var1", "user1");
+ varMap.put("var2", "user2");
+ String result = VariableResolver.resolveExpression(varMap, "${var1}");
+ assertEquals("user1", result);
+ result = VariableResolver.resolveExpression(varMap, "var1");
+ assertEquals("user1", result);
+
+ result = VariableResolver.resolveExpression(varMap, "${var1}!!!");
+ assertEquals("user1!!!", result);
+ result = VariableResolver.resolveExpression(varMap, "var1!!!");
+ assertEquals("var1!!!", result);
+
+ result = VariableResolver.resolveExpression(varMap, "${var1}${var2}");
+ assertEquals("user1user2", result);
+ result = VariableResolver.resolveExpression(varMap, "var1${var2}");
+ assertEquals("var1user2", result);
+
+ result = VariableResolver.resolveExpression(varMap, "${var1}&${var2}");
+ assertEquals("user1&user2", result);
+ result = VariableResolver.resolveExpression(varMap, "var1&${var2}");
+ assertEquals("var1&user2", result);
+
+ result = VariableResolver.resolveExpression(varMap, "${var3}");
+ assertEquals("${var3}", result);
+
+ result = VariableResolver.resolveExpression(varMap, "${var1}${var1}");
+ assertEquals("user1user1", result);
+
+ result = VariableResolver.resolveExpression(varMap, "akto");
+ assertEquals("akto", result);
+ }
+
+}