Skip to content

Commit

Permalink
Merge pull request #1185 from akto-api-security/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
notshivansh authored Jun 13, 2024
2 parents adc89c5 + 2c3bd71 commit f4433f3
Show file tree
Hide file tree
Showing 16 changed files with 279 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import com.akto.listener.InitializerListener;
import com.akto.log.LoggerMaker;
import com.akto.log.LoggerMaker.LogDb;
import com.akto.rules.RequiredConfigs;
import com.akto.store.SampleMessageStore;
import com.akto.store.TestingUtil;
import com.akto.test_editor.execution.VariableResolver;
Expand Down Expand Up @@ -293,6 +294,9 @@ public String runTestForGivenTemplate() {
return ERROR.toUpperCase();
}

// initiating map creation for storing required
RequiredConfigs.initiate();

ApiInfo.ApiInfoKey infoKey = new ApiInfo.ApiInfoKey(apiInfoKey.getInt(ApiInfo.ApiInfoKey.API_COLLECTION_ID),
apiInfoKey.getString(ApiInfo.ApiInfoKey.URL),
URLMethods.Method.valueOf(apiInfoKey.getString(ApiInfo.ApiInfoKey.METHOD)));
Expand Down Expand Up @@ -324,6 +328,7 @@ public String runTestForGivenTemplate() {
TestingUtil testingUtil = new TestingUtil(authMechanism, messageStore, null, null, customAuthTypes);
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);
if (testingRunResult == null) {
testingRunResult = new TestingRunResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,10 @@ public String fetchTestingRunResults() {
case SECURED:
testingRunResultFilters.add(Filters.eq(TestingRunResult.VULNERABLE, false));
testingRunResultFilters.add(Filters.nin(TestingRunResultDao.ERRORS_KEY, TestResult.TestError.getErrorsToSkipTests()));
testingRunResultFilters.add(Filters.eq(TestingRunResult.REQUIRES_CONFIG, false));
break;
case SKIPPED_EXEC_NEED_CONFIG:
testingRunResultFilters.add(Filters.eq(TestingRunResult.REQUIRES_CONFIG, true));
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { useSearchParams } from 'react-router-dom';
function GithubServerTable(props) {

const [searchParams, setSearchParams] = useSearchParams();

const updateQueryParams = (key, value) => {
const newSearchParams = new URLSearchParams(searchParams);
newSearchParams.set(key, value);
Expand Down Expand Up @@ -340,6 +339,7 @@ function GithubServerTable(props) {
selected={props?.selected}
onSelect={(x) => handleTabChange(x)}
/>
{props?.bannerComp?.selected === props?.selected ? props?.bannerComp?.comp : null}
<div className={tableHeightClass}>
<IndexTable
resourceName={props.resourceName}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function GithubSimpleTable(props) {
hasZebraStriping={props.hasZebraStriping}
filterStateUrl={props?.filterStateUrl}
hidePagination={props?.hidePagination}
bannerComp={props?.bannerComp}
/>

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {
ActionList,
Card,
ProgressBar,
Tooltip
Tooltip,
Banner
} from '@shopify/polaris';

import {
Expand Down Expand Up @@ -101,14 +102,14 @@ let filters = [

function SingleTestRunPage() {

const [testRunResults, setTestRunResults] = useState({ vulnerable: [], no_vulnerability_found: [], skipped: [] })
const [testRunResultsText, setTestRunResultsText] = useState({ vulnerable: [], no_vulnerability_found: [], skipped: [] })
const [testRunResults, setTestRunResults] = useState({ vulnerable: [], no_vulnerability_found: [], skipped: [], need_configurations: [] })
const [testRunResultsText, setTestRunResultsText] = useState({ vulnerable: [], no_vulnerability_found: [], skipped: [], need_configurations: [] })
const [ selectedTestRun, setSelectedTestRun ] = useState({});
const subCategoryFromSourceConfigMap = PersistStore(state => state.subCategoryFromSourceConfigMap);
const subCategoryMap = PersistStore(state => state.subCategoryMap);
const params= useParams()
const [loading, setLoading] = useState(false);
const [tempLoading , setTempLoading] = useState({vulnerable: false, no_vulnerability_found: false, skipped: false, running: false})
const [tempLoading , setTempLoading] = useState({vulnerable: false, no_vulnerability_found: false, skipped: false, running: false,need_configurations:false})
const [selectedTab, setSelectedTab] = useState("vulnerable")
const [selected, setSelected] = useState(0)
const [workflowTest, setWorkflowTest ] = useState(false);
Expand All @@ -120,6 +121,7 @@ function SingleTestRunPage() {
testsInsertedInDb: 0,
testingRunId: -1
})
const [missingConfigs, setMissingConfigs] = useState([])

const refreshId = useRef(null);
const hexId = params.hexId;
Expand Down Expand Up @@ -166,6 +168,7 @@ function SingleTestRunPage() {
prev.vulnerable = true;
prev.no_vulnerability_found = true;
prev.skipped = true;
prev.need_configurations = true
return {...prev};
});
let testRunResults = [];
Expand All @@ -183,6 +186,15 @@ function SingleTestRunPage() {
fillTempData(testRunResults, 'skipped')
fillData(transform.getPrettifiedTestRunResults(testRunResults), 'skipped')

await api.fetchTestingRunResults(summaryHexId, "SKIPPED_EXEC_NEED_CONFIG").then(({ testingRunResults }) => {
testRunResults = transform.prepareTestRunResults(hexId, testingRunResults, subCategoryMap, subCategoryFromSourceConfigMap)
})
fillTempData(testRunResults, 'need_configurations')
fillData(transform.getPrettifiedTestRunResults(testRunResults), 'need_configurations')
if(testRunResults.length > 0){
setMissingConfigs(transform.getMissingConfigs(testRunResults))
}

await api.fetchTestingRunResults(summaryHexId, "SECURED").then(({ testingRunResults }) => {
testRunResults = transform.prepareTestRunResults(hexId, testingRunResults, subCategoryMap, subCategoryFromSourceConfigMap)
})
Expand Down Expand Up @@ -287,7 +299,31 @@ const promotedBulkActions = (selectedDataHexIds) => {
}
}

const definedTableTabs = ['Vulnerable', 'Skipped', 'No vulnerability found']
const baseUrl = window.location.origin+"/dashboard/testing/roles/details?system=";

const bannerComp = (
missingConfigs.length > 0 ?
<div className="banner-wrapper">
<Banner status="critical">
<HorizontalStack gap={3}>
<Box>
<Text fontWeight="semibold">
{`${missingConfigs.length} configuration${missingConfigs.length > 1 ? 's' : ''} missing: `}
</Text>
</Box>
<HorizontalStack gap={2}>
{missingConfigs.map((config) => {
return(<Link url={baseUrl + config.toUpperCase()} key={config} target="_blank">
{config}
</Link>)
})}
</HorizontalStack>
</HorizontalStack>
</Banner>
</div> : null
)

const definedTableTabs = ['Vulnerable', 'Need configurations','Skipped', 'No vulnerability found']

const { tabsInfo } = useTable()
const tableCountObj = func.getTabsCount(definedTableTabs, testRunResults)
Expand All @@ -301,6 +337,7 @@ const promotedBulkActions = (selectedDataHexIds) => {
setLoading(false)
},200)
}

const resultTable = (
<GithubSimpleTable
key={"table"}
Expand All @@ -325,6 +362,11 @@ const promotedBulkActions = (selectedDataHexIds) => {
tableTabs={tableTabs}
onSelect={handleSelectedTab}
filterStateUrl={"/dashboard/testing/" + selectedTestRun?.id + "/#" + selectedTab}
bannerComp={{
"comp": bannerComp,
"selected": 1
}
}
/>
)

Expand Down Expand Up @@ -408,7 +450,7 @@ const promotedBulkActions = (selectedDataHexIds) => {
)
}

const allResultsLength = testRunResults.skipped.length + testRunResults.no_vulnerability_found.length + testRunResults.vulnerable.length + progress
const allResultsLength = testRunResults.skipped.length + testRunResults.need_configurations.length + testRunResults.no_vulnerability_found.length + testRunResults.vulnerable.length + progress
const useComponents = (!workflowTest && allResultsLength === 0) ? [<EmptyData key="empty"/>] : components
const headingComp = (
<Box paddingBlockStart={1}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
.filterClass .Polaris-Filters__FiltersWrapper {
border-bottom:0
}

.div-link{
cursor: pointer;
}
.div-link:hover{
border-bottom: 1px solid #B98900;
}

.banner-wrapper .Polaris-Banner--withinContentContainer{
border-radius: 0px !important;
border: unset !important;
}

.banner-wrapper .Polaris-Banner--statusCritical {
background-color: #FFF4F4 !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {ResourcesMajor,
ReplayMinor,
PlayMinor,
} from '@shopify/polaris-icons';
import React, { } from 'react'
import React from 'react'
import { Text,HorizontalStack, Badge, Link, List, Box, Icon, Avatar, Tag, Tooltip} from '@shopify/polaris';
import { history } from "@/util/history";
import PersistStore from "../../../main/PersistStore";
Expand Down Expand Up @@ -291,7 +291,7 @@ const transform = {
const prettifiedTest={
...obj,
testName: transform.prettifyTestName(data.name || "Test", iconObj.icon,iconObj.color, iconObj.tooltipContent),
severity: observeFunc.getIssuesList(transform.filterObjectByValueGreaterThanZero(testingRunResultSummary.countIssues))
severity: observeFunc.getIssuesList(transform.filterObjectByValueGreaterThanZero(testingRunResultSummary.countIssues || {"HIGH" : 0, "MEDIUM": 0, "LOW": 0}))
}
return prettifiedTest
}else{
Expand Down Expand Up @@ -602,7 +602,7 @@ const transform = {
const date = new Date(obj.startTimestamp * 1000)
return{
...obj,
prettifiedSeverities: observeFunc.getIssuesList(obj.countIssues),
prettifiedSeverities: observeFunc.getIssuesList(obj.countIssues || {"HIGH" : 0, "MEDIUM": 0, "LOW": 0}),
startTime: date.toLocaleTimeString() + " on " + date.toLocaleDateString(),
id: obj.hexId
}
Expand Down Expand Up @@ -749,7 +749,7 @@ getCollapsibleRow(urls, severity){
getTestErrorType(message){
const errorsObject = TestingStore.getState().errorsObject
for(var key in errorsObject){
if(errorsObject[key] === message){
if(errorsObject[key] === message || message.includes(errorsObject[key])){
return key
}
}
Expand All @@ -765,7 +765,25 @@ getPrettifiedTestRunResults(testRunResults){
if(test?.errorsList.length > 0){
const errorType = this.getTestErrorType(test.errorsList[0])
key = key + ': ' + errorType
error_message = errorsObject[errorType]
if(errorType === "ROLE_NOT_FOUND"){
const baseUrl = window.location.origin+"/dashboard/testing/roles/details?system="
const missingConfigs = func.toSentenceCase(test.errorsList[0].split(errorsObject["ROLE_NOT_FOUND"])[0]).split(" ");
error_message = (
<HorizontalStack gap={"1"}>
{missingConfigs.map((config, index) => {
return(
config.length > 0 ?
<div className="div-link" onClick={(e) => {e.stopPropagation();window.open(baseUrl + config.toUpperCase(), "_blank")}} key={index}>
<span style={{ lineHeight: '16px', fontSize: '14px', color: "#B98900"}}>{func.toSentenceCase(config || "")}</span>
</div>
: null
)
})}
</HorizontalStack>
)
}else{
error_message = errorsObject[errorType]
}
}

if(testRunResultsObj.hasOwnProperty(key)){
Expand Down Expand Up @@ -997,12 +1015,36 @@ getHeaders: (tab)=> {
return header;
})

case "need_configurations":
return headers.filter((header) => header.title !== "CWE tags").map((header) => {
if (header.title === "Severity") {
// Modify the object as needed
return { type: CellType.TEXT, title: "Configuration missing", value: 'errorMessage' };
}
return header;
})

default:
return headers
}
},
convertErrorEnumsToErrorObjects(errorEnums){
console.log(errorEnums)
getMissingConfigs(testResults){
const errorsObject = TestingStore.getState().errorsObject
if(Object.keys(errorsObject).length === 0){
return []
}
const configsSet = new Set();
testResults.forEach((res) => {
if(res?.errorsList.length > 0 && res.errorsList[0].includes(errorsObject["ROLE_NOT_FOUND"])){
const config = func.toSentenceCase(res.errorsList[0].split(errorsObject["ROLE_NOT_FOUND"])[0])
if(config.length > 0){
let allConfigs = config.split(" ")
allConfigs.filter(x => x.length > 1).forEach((x) => configsSet.add(func.toSentenceCase(x)))
}
}
})

return [...configsSet]
}
}

Expand Down
43 changes: 43 additions & 0 deletions apps/testing/src/main/java/com/akto/rules/RequiredConfigs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.akto.rules;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.akto.dao.testing.TestRolesDao;
import com.akto.dto.testing.TestRoles;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;

public class RequiredConfigs {

private static final RequiredConfigs requiredConfigs = new RequiredConfigs();

public static RequiredConfigs getRequiredConfigs() {
return requiredConfigs;
}

private static List<TestRoles> testRolesList = new ArrayList<>();

private static final Map<String,Boolean> validRolesExist = new HashMap<>();

public static void initiate() {
validRolesExist.clear();
testRolesList = TestRolesDao.instance.findAll(
Filters.empty(),
Projections.fields(
Projections.include(TestRoles.NAME)
)
);
for(TestRoles role: testRolesList){
validRolesExist.put(role.getName(), true);
}
}

public static Map<String,Boolean> getCurrentConfigsMap(){
return validRolesExist;
}

}

8 changes: 8 additions & 0 deletions apps/testing/src/main/java/com/akto/test_editor/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,14 @@ public static ApiAccessType getApiAccessTypeFromString(String apiAccessType){
}
}

public static Boolean commandRequiresConfig(String key){
String ACCESS_ROLES = "roles_access";
if (key.contains(ACCESS_ROLES) || key.equals("replace_auth_header")) {
return true;
}
return false;
}

public static Object getEpochTime(Object value) {
Object val = null;
if (value.equals("${current_epoch_seconds}")) {
Expand Down
3 changes: 2 additions & 1 deletion apps/testing/src/main/java/com/akto/testing/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.akto.notifications.slack.NewIssuesModel;
import com.akto.notifications.slack.SlackAlerts;
import com.akto.notifications.slack.SlackSender;
import com.akto.rules.RequiredConfigs;
import com.akto.util.AccountTask;
import com.akto.util.Constants;
import com.akto.util.DashboardMode;
Expand Down Expand Up @@ -242,7 +243,6 @@ public void run() {
int accountId = account.getId();

int start = Context.now();

TestingRunResultSummary trrs = findPendingTestingRunResultSummary();
boolean isSummaryRunning = trrs != null && trrs.getState().equals(State.RUNNING);
TestingRun testingRun;
Expand Down Expand Up @@ -377,6 +377,7 @@ public void run() {

}
}
RequiredConfigs.initiate();
testExecutor.init(testingRun, summaryId, syncLimit);
raiseMixpanelEvent(summaryId, testingRun, accountId);
} catch (Exception e) {
Expand Down
Loading

0 comments on commit f4433f3

Please sign in to comment.