Skip to content

Commit a65be9d

Browse files
Merge pull request #1981 from akto-api-security/feature/remediation
Feature/remediation
2 parents 2f5c600 + 6178684 commit a65be9d

File tree

15 files changed

+1794
-82
lines changed

15 files changed

+1794
-82
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.akto.action.testing;
2+
3+
import org.apache.commons.lang3.StringUtils;
4+
5+
import com.akto.action.UserAction;
6+
import com.akto.dao.testing.RemediationsDao;
7+
import com.akto.dto.testing.Remediation;
8+
import com.akto.util.Constants;
9+
10+
public class TestTemplatesAction extends UserAction {
11+
12+
public String execute(){
13+
throw new IllegalStateException("Not implemented");
14+
}
15+
16+
String testId;
17+
String remediation;
18+
public String fetchRemediationInfo() {
19+
20+
if (StringUtils.isEmpty(testId)) {
21+
addActionError("testId is empty");
22+
return ERROR.toUpperCase();
23+
}
24+
25+
Remediation remediationObj = RemediationsDao.instance.findOne(Constants.ID, testId);
26+
27+
if (remediationObj == null) {
28+
this.remediation = "";
29+
} else {
30+
this.remediation = remediationObj.getRemediationText();
31+
}
32+
33+
return SUCCESS.toUpperCase();
34+
}
35+
36+
public String getTestId() {
37+
return this.testId;
38+
}
39+
40+
public void setTestId(String testId) {
41+
this.testId = testId;
42+
}
43+
44+
public String getRemediation() {
45+
return this.remediation;
46+
}
47+
48+
public void setRemediation(String remediation) {
49+
this.remediation = remediation;
50+
}
51+
52+
53+
}

apps/dashboard/src/main/java/com/akto/action/testing_issues/IssuesAction.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.mongodb.client.result.InsertOneResult;
4444
import com.opensymphony.xwork2.Action;
4545

46+
import org.apache.commons.lang3.StringUtils;
4647
import org.bson.Document;
4748
import org.bson.conversions.Bson;
4849
import org.bson.types.ObjectId;
@@ -490,6 +491,14 @@ public static BasicDBObject createSubcategoriesInfoObj(TestConfig testConfig) {
490491
infoObj.put("_name", testConfig.getId());
491492
infoObj.put("content", testConfig.getContent());
492493
infoObj.put("templateSource", testConfig.getTemplateSource());
494+
495+
String remediationContent = info.getRemediation();
496+
497+
if (!StringUtils.isEmpty(remediationContent)) {
498+
infoObj.put("remediation", remediationContent);
499+
}
500+
501+
493502
infoObj.put("updatedTs", testConfig.getUpdateTs());
494503
infoObj.put("author", testConfig.getAuthor());
495504

@@ -546,7 +555,6 @@ public String fetchAllSubCategories() {
546555
return SUCCESS.toUpperCase();
547556
}
548557

549-
550558
public String updateIssueStatus () {
551559
if (issueId == null || statusToBeUpdated == null || ignoreReason == null) {
552560
throw new IllegalStateException();

apps/dashboard/src/main/java/com/akto/listener/InitializerListener.java

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3168,6 +3168,13 @@ public void run() {
31683168
return;
31693169
}
31703170

3171+
try {
3172+
processRemedationFilesZip(testingTemplates);
3173+
} catch (Exception e) {
3174+
e.printStackTrace();
3175+
loggerMaker.infoAndAddToDb("Unable to import remediations", LogDb.DASHBOARD);
3176+
}
3177+
31713178
Map<String, byte[]> allYamlTemplates = TestTemplateUtils.getZipFromMultipleRepoAndBranch(getAktoDefaultTestLibs());
31723179
AccountTask.instance.executeTask((account) -> {
31733180
try {
@@ -3200,6 +3207,88 @@ public void run() {
32003207
}, 0, 4, TimeUnit.HOURS);
32013208
}
32023209

3210+
public static void processRemedationFilesZip(byte[] zipFile) {
3211+
if (zipFile != null) {
3212+
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(zipFile);
3213+
ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
3214+
3215+
ZipEntry entry;
3216+
List<Remediation> remediations = RemediationsDao.instance.findAll(Filters.empty(), Projections.include(Remediation.TEST_ID, Remediation.HASH));
3217+
Map<String, List<Remediation>> mapRemediationIdToHash = remediations.stream().collect(Collectors.groupingBy(Remediation::getid));
3218+
3219+
int countUnchangedRemediations = 0;
3220+
int countTotalRemediations = 0;
3221+
3222+
while ((entry = zipInputStream.getNextEntry()) != null) {
3223+
if (!entry.isDirectory()) {
3224+
String entryName = entry.getName();
3225+
3226+
boolean isRemediation = entryName.contains("remediation");
3227+
if (!isRemediation) {
3228+
loggerMaker.infoAndAddToDb(
3229+
String.format("%s not a remediation file, skipping", entryName),
3230+
LogDb.DASHBOARD);
3231+
continue;
3232+
}
3233+
3234+
if (!entryName.endsWith(".md")) {
3235+
loggerMaker.infoAndAddToDb(
3236+
String.format("%s not a md file, skipping", entryName),
3237+
LogDb.DASHBOARD);
3238+
continue;
3239+
}
3240+
3241+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
3242+
byte[] buffer = new byte[1024];
3243+
int bytesRead;
3244+
while ((bytesRead = zipInputStream.read(buffer)) != -1) {
3245+
outputStream.write(buffer, 0, bytesRead);
3246+
}
3247+
3248+
String templateContent = new String(outputStream.toByteArray(), "UTF-8");
3249+
3250+
List<Remediation> remediationsInDb = mapRemediationIdToHash.get(entryName);
3251+
int remediationHashFromFile = templateContent.hashCode();
3252+
3253+
countTotalRemediations++;
3254+
if (remediationsInDb != null && remediationsInDb.size() >= 1) {
3255+
int remediationHashInDb = remediationsInDb.get(0).getHash();
3256+
3257+
if (remediationHashFromFile == remediationHashInDb) {
3258+
countUnchangedRemediations++;
3259+
} else {
3260+
loggerMaker.infoAndAddToDb("Updating remediation content: " + entryName, LogDb.DASHBOARD);
3261+
Bson updates =
3262+
Updates.combine(
3263+
Updates.set(Remediation.REMEDIATION_TEXT, templateContent),
3264+
Updates.set(Remediation.HASH, remediationHashFromFile)
3265+
);
3266+
3267+
RemediationsDao.instance.updateOne(Remediation.TEST_ID, Remediation.REMEDIATION_TEXT, updates);
3268+
}
3269+
} else {
3270+
loggerMaker.infoAndAddToDb("Inserting remediation content: " + entryName, LogDb.DASHBOARD);
3271+
RemediationsDao.instance.insertOne(new Remediation(entryName, templateContent, remediationHashFromFile));
3272+
}
3273+
}
3274+
3275+
zipInputStream.closeEntry();
3276+
}
3277+
3278+
if (countTotalRemediations != countUnchangedRemediations) {
3279+
loggerMaker.infoAndAddToDb(countUnchangedRemediations + "/" + countTotalRemediations + "remediations unchanged", LogDb.DASHBOARD);
3280+
}
3281+
3282+
} catch (Exception ex) {
3283+
cacheLoggerMaker.errorAndAddToDb(ex,
3284+
String.format("Error while processing Test template files zip. Error %s", ex.getMessage()),
3285+
LogDb.DASHBOARD);
3286+
}
3287+
} else {
3288+
loggerMaker.infoAndAddToDb("Received null zip file");
3289+
}
3290+
}
3291+
32033292
public static void processTemplateFilesZip(byte[] zipFile, String author, String source, String repositoryUrl) {
32043293
if (zipFile != null) {
32053294
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(zipFile);

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4026,6 +4026,26 @@
40264026
</result>
40274027
</action>
40284028

4029+
4030+
4031+
<action name="api/fetchRemediationInfo" class="com.akto.action.testing.TestTemplatesAction" method="fetchRemediationInfo">
4032+
<interceptor-ref name="json"/>
4033+
<interceptor-ref name="defaultStack" />
4034+
<result name="FORBIDDEN" type="json">
4035+
<param name="statusCode">403</param>
4036+
<param name="ignoreHierarchy">false</param>
4037+
<param name="includeProperties">^actionErrors.*</param>
4038+
</result>
4039+
<result name="SUCCESS" type="json">
4040+
<param name="root">remediation</param>
4041+
</result>
4042+
<result name="ERROR" type="json">
4043+
<param name="statusCode">422</param>
4044+
<param name="ignoreHierarchy">false</param>
4045+
<param name="includeProperties">^actionErrors.*</param>
4046+
</result>
4047+
</action>
4048+
40294049
<action name="api/getReportFilters" class="com.akto.action.testing_issues.IssuesAction" method="getReportFilters">
40304050
<interceptor-ref name="json"/>
40314051
<interceptor-ref name="defaultStack" />

0 commit comments

Comments
 (0)