Skip to content

Commit

Permalink
[Feat] Controller, Service Layer 구현 완료 - #8
Browse files Browse the repository at this point in the history
  • Loading branch information
Juser0 committed Oct 3, 2023
1 parent a14a6dc commit 09f1a4d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 19 deletions.
1 change: 1 addition & 0 deletions manager/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
implementation 'org.jsoup:jsoup:1.16.1'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.List;

import static org.springframework.http.HttpStatus.*;
Expand All @@ -35,7 +36,7 @@ public ResponseEntity<CommonResponse<JsonNode>> scanSBOM(@RequestParam String to

@GetMapping("/report")
@Operation(summary = "Get SBOM Report", description = "Get Software Bill of Materials' security report")
public ResponseEntity<CommonResponse<List<SbomResponseDto>>> getReport(@RequestParam String token, @RequestParam String projectId, @RequestParam String baseUrl) throws JsonProcessingException {
public ResponseEntity<CommonResponse<List<SbomResponseDto>>> getReport(@RequestParam String token, @RequestParam String projectId, @RequestParam String baseUrl) throws IOException {
List<SbomResponseDto> sbomReport = sbomService.generateReport(token, projectId, baseUrl);
return ResponseEntity.status(OK).body(CommonResponse.resWithData("SBOM_REPORT_GENERATED", "SBOM 보안 보고서가 생성되었습니다", sbomReport));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public class SbomResponseDto {
private String source;
private String referenceUrl;
private String suggestion;
private List<String> recommendUrl;
private List<String> suggestionUrl;

@Builder
public SbomResponseDto(String name, String purl, String version, String group, String vulnId, String severity, String description, String source, String referenceUrl, String suggestion, List<String> recommendUrl) {
public SbomResponseDto(String name, String purl, String version, String group, String vulnId, String severity, String description, String source, String referenceUrl, String suggestion, List<String> suggestionUrl) {
this.name = name;
this.purl = purl;
this.version = version;
Expand All @@ -31,6 +31,6 @@ public SbomResponseDto(String name, String purl, String version, String group, S
this.source = source;
this.referenceUrl = referenceUrl;
this.suggestion = suggestion;
this.recommendUrl = recommendUrl;
this.suggestionUrl = suggestionUrl;
}
}
70 changes: 55 additions & 15 deletions manager/src/main/java/com/analyzer/sbom/service/SbomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
Expand All @@ -20,17 +27,32 @@ public class SbomService {
private final ObjectMapper objectMapper;

@Value("${webclient.nvd}")
private String ref;
private String cveUrl;

@Value("${webclient.nvdSelector}")
private String nvdSelector;

@Value("${webclient.snyk}")
private String snykUrl;

@Value("${webclient.snykXpath}")
private String snykXpath;

@Value("${webclient.snykSearchXpath}")
private String snykSearchXpath;

@Value("${webclient.snykBase}")
private String snykBase;

public JsonNode scanVulnerability(String token, String projectId, String baseUrl) throws JsonProcessingException {
String jsonData = getAPI(token, projectId, baseUrl);
return objectMapper.readTree(jsonData);
}

public List<SbomResponseDto> generateReport(String token, String projectId, String baseUrl) throws JsonProcessingException {
public List<SbomResponseDto> generateReport(String token, String projectId, String baseUrl) throws IOException {
String sbomResult = getAPI(token, projectId, baseUrl);

List<SbomResponseDto> sbomReport = new ArrayList<SbomResponseDto>();
List<SbomResponseDto> sbomReport = new ArrayList<>();

JsonNode jsonNode = objectMapper.readTree(sbomResult).get("findings");
if (jsonNode.isArray()) {
Expand All @@ -42,15 +64,21 @@ public List<SbomResponseDto> generateReport(String token, String projectId, Stri
String group = isExist(component, "group") ? component.get("group").asText() : "";

JsonNode attribution = finding.get("attribution");
String recommendUrl = isExist(attribution, "referenceUrl") ? attribution.get("referenceUrl").asText() : "";
String suggestionLink = isExist(attribution, "referenceUrl") ? attribution.get("referenceUrl").asText() : "";

JsonNode vulnerability = finding.get("vulnerability");
String severity = isExist(vulnerability, "severity") ? vulnerability.get("severity").asText() : "";
String vulnId = isExist(vulnerability, "vulnId") ? vulnerability.get("vulnId").asText() : "";
String source = isExist(vulnerability, "source") ? vulnerability.get("source").asText() : "";
String description = isExist(vulnerability, "description") ? vulnerability.get("description").asText() : "";

String referenceUrl = ref + vulnId;
String referenceUrl = cveUrl + vulnId;

List<String> suggestionUrl = getSuggestionUrl(referenceUrl);
suggestionUrl.add(getSuggestion(snykUrl + vulnId, true));
if(!Objects.equals(suggestionLink, "")) suggestionUrl.add(suggestionLink);

String suggestion = getSuggestion(snykUrl + vulnId, false);

SbomResponseDto sbomResponseDto = SbomResponseDto.builder()
.name(name)
Expand All @@ -62,8 +90,8 @@ public List<SbomResponseDto> generateReport(String token, String projectId, Stri
.source(source)
.description(description)
.referenceUrl(referenceUrl)
.recommendUrl(null)
.suggestion("")
.suggestionUrl(suggestionUrl)
.suggestion(suggestion)
.build();

sbomReport.add(sbomResponseDto);
Expand All @@ -72,32 +100,44 @@ public List<SbomResponseDto> generateReport(String token, String projectId, Stri
return sbomReport;
}

public String getAPI(String token, String projectId, String baseUrl) {
private String getAPI(String token, String projectId, String baseUrl) {
WebClient webClient = webClientBuilder
.baseUrl(baseUrl)
.defaultHeader("X-Api-Key", token)
.build();

String sbomResult = webClient
return webClient
.get()
.uri("/api/v1/finding/project/{projectId}/export", projectId)
.retrieve()
.bodyToMono(String.class)
.block();

return sbomResult;
}

private boolean isExist(JsonNode source, String fieldName) {
return source.has(fieldName);
}

private String getSuggestionUrl() {
return "";
private List<String> getSuggestionUrl(String cveUrl) throws IOException {
Document doc = Jsoup.connect(cveUrl).get();
Element table = doc.select(nvdSelector).first();
Elements tdElements = Objects.requireNonNull(table).select("td");

return tdElements.stream()
.flatMap(td -> td.select("a").stream())
.map(Element::text)
.collect(Collectors.toList());
}

private String getSuggestion() {
return "";
private String getSuggestion(String snykUrl, Boolean isLink) throws IOException {
Document doc = Jsoup.connect(snykUrl).get();
String link = String.join("", doc.selectXpath(snykXpath).eachAttr("href"));
String suggestionLink = snykBase + link;

Document solutionDoc = Jsoup.connect(suggestionLink).get();
String suggestion = solutionDoc.selectXpath(snykSearchXpath).text();

return isLink ? suggestionLink : suggestion;
}

}

0 comments on commit 09f1a4d

Please sign in to comment.