Skip to content

Commit 00b5780

Browse files
committed
Merge remote-tracking branch 'origin/release/v11.2.1' into release/v11.2.1
2 parents 6365f57 + 65bd80f commit 00b5780

50 files changed

Lines changed: 860 additions & 293 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/src/main/java/com/park/utmstack/config/RestTemplateConfiguration.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import org.slf4j.LoggerFactory;
1010
import org.springframework.context.annotation.Bean;
1111
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.http.client.ClientHttpResponse;
1213
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
14+
import org.springframework.web.client.DefaultResponseErrorHandler;
1315
import org.springframework.web.client.RestTemplate;
1416

1517
import javax.net.ssl.HostnameVerifier;
@@ -37,6 +39,19 @@ public RestTemplate restTemplateWithSsl() {
3739
return rest;
3840
}
3941

42+
@Bean(name = "rawRestTemplate")
43+
public RestTemplate rawRestTemplate() {
44+
RestTemplate rest = new RestTemplate();
45+
rest.setErrorHandler(new DefaultResponseErrorHandler() {
46+
@Override
47+
public boolean hasError(ClientHttpResponse response) {
48+
return false;
49+
}
50+
});
51+
return rest;
52+
}
53+
54+
4055
private HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
4156
final String ctx = CLASSNAME + ".clientHttpRequestFactory";
4257
try {
Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
package com.park.utmstack.service.compliance;
22

3-
public class ComplianceFileResponse {
4-
byte [] pdfBytes;
5-
6-
public ComplianceFileResponse(byte[] pdfBytes) {
7-
this.pdfBytes = pdfBytes;
8-
}
9-
public ComplianceFileResponse(){}
3+
import lombok.Builder;
4+
import lombok.Data;
105

11-
public byte[] getPdfBytes() {
12-
return pdfBytes;
13-
}
6+
@Data
7+
@Builder
8+
public class ComplianceFileResponse {
9+
// Success fields
10+
private byte[] pdfBytes;
1411

15-
public void setPdfBytes(byte[] pdfBytes) {
16-
this.pdfBytes = pdfBytes;
17-
}
12+
// Error fields
13+
private boolean error;
14+
private String message;
15+
private String details;
1816
}
17+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.park.utmstack.service.dto.web_pdf;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class PdfServiceResponse {
7+
private boolean error;
8+
private String message;
9+
private String details;
10+
private byte[] pdfBytes;
11+
}
12+

backend/src/main/java/com/park/utmstack/service/util/PdfService.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import com.park.utmstack.config.Constants;
44
import com.park.utmstack.service.compliance.ComplianceFileResponse;
5+
import com.park.utmstack.service.dto.web_pdf.PdfServiceResponse;
56
import com.park.utmstack.service.federation_service.UtmFederationServiceClientService;
67
import com.park.utmstack.service.web_clients.rest_template.RestTemplateService;
8+
import com.park.utmstack.util.exceptions.ApiException;
79
import org.slf4j.Logger;
810
import org.slf4j.LoggerFactory;
11+
import org.springframework.http.HttpStatus;
912
import org.springframework.http.ResponseEntity;
1013
import org.springframework.stereotype.Service;
1114
import org.springframework.transaction.annotation.Transactional;
@@ -60,7 +63,7 @@ public byte[] getPdf(String url, String accessKey, String accessType) throws Exc
6063
ResponseEntity<ComplianceFileResponse> rs = restTemplateService.get(urlService, ComplianceFileResponse.class);
6164
log.info("Requesting PDF creation to URL : {}", Constants.PDF_SERVICE_URL + "?url=" + url);
6265
if (!rs.getStatusCode().is2xxSuccessful()) {
63-
log.error(ctx + ": " + restTemplateService.extractErrorMessage(rs));
66+
log.error(ctx + ": {}", restTemplateService.extractErrorMessage(rs));
6467
} else {
6568
byte[] pdfInBytes = Objects.requireNonNull(rs.getBody()).getPdfBytes();
6669
if (pdfInBytes != null && pdfInBytes.length > 0) {
@@ -72,6 +75,51 @@ public byte[] getPdf(String url, String accessKey, String accessType) throws Exc
7275
return null;
7376
}
7477

78+
public PdfServiceResponse downloadPdf(String url, String accessKey, String accessType) {
79+
final String ctx = CLASSNAME + ".getPdf";
80+
81+
String urlService = UriComponentsBuilder.fromUriString(Constants.PDF_SERVICE_URL)
82+
.queryParam("baseUrl", Constants.FRONT_BASE_URL)
83+
.queryParam("url", url)
84+
.queryParam("accessKey", accessKey)
85+
.queryParam("accessType", accessType)
86+
.build().toUriString();
87+
try {
88+
log.info("Requesting PDF creation to URL : {}", urlService);
89+
ResponseEntity<PdfServiceResponse> rs =
90+
restTemplateService.getRaw(urlService, PdfServiceResponse.class);
91+
92+
if (!rs.getStatusCode().is2xxSuccessful()) {
93+
PdfServiceResponse errorBody = rs.getBody();
94+
95+
String message = (errorBody != null && errorBody.getMessage() != null)
96+
? errorBody.getMessage()
97+
: "Unknown error returned from PDF service";
98+
99+
throw new ApiException(message, rs.getStatusCode());
100+
}
101+
102+
103+
PdfServiceResponse body = rs.getBody();
104+
105+
if (body == null || body.getPdfBytes() == null || body.getPdfBytes().length == 0) {
106+
log.error("{}: No data returned from PDF service", ctx);
107+
108+
PdfServiceResponse error = new PdfServiceResponse();
109+
error.setError(true);
110+
error.setMessage("No data returned from PDF service");
111+
return error;
112+
}
113+
114+
return body;
115+
116+
} catch (Exception e){
117+
log.error("{}: Exception occurred while requesting PDF service: {}", ctx, e.getMessage());
118+
throw new ApiException(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
119+
}
120+
}
121+
122+
75123
/**
76124
* Enum used to define type of access used when accessing the PDF microservice
77125
* */

backend/src/main/java/com/park/utmstack/service/web_clients/rest_template/RestTemplateService.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
66
import com.park.utmstack.web.rest.util.HeaderUtil;
7+
import lombok.extern.slf4j.Slf4j;
8+
import org.springframework.beans.factory.annotation.Qualifier;
79
import org.springframework.core.ParameterizedTypeReference;
810
import org.springframework.http.*;
911
import org.springframework.stereotype.Service;
@@ -15,17 +17,22 @@
1517
import java.util.Objects;
1618

1719
@Service
20+
@Slf4j
1821
public class RestTemplateService {
1922
private static final String CLASSNAME = "RestTemplateService";
2023

2124
private final RestTemplate rest;
25+
private final RestTemplate rawRestTemplate;
2226
private final RestTemplate restTemplateWithSsl;
2327

2428
private final HttpHeaders headers = new HttpHeaders();
2529

26-
public RestTemplateService(RestTemplate restTemplate, RestTemplate restTemplateWithSsl) {
30+
public RestTemplateService(RestTemplate restTemplate,
31+
RestTemplate restTemplateWithSsl,
32+
@Qualifier("rawRestTemplate") RestTemplate rawRestTemplate) {
2733
this.rest = restTemplate;
2834
this.restTemplateWithSsl = restTemplateWithSsl;
35+
this.rawRestTemplate = rawRestTemplate;
2936
headers.add("Content-Type", "application/json");
3037
headers.add("Accept", "*/*");
3138
}
@@ -42,6 +49,12 @@ public <T> ResponseEntity<T> get(String url, Class<T> type) throws Exception {
4249
}
4350
}
4451

52+
public <T> ResponseEntity<T> getRaw(String url, Class<T> type) {
53+
HttpEntity<String> requestEntity = new HttpEntity<>("", headers);
54+
return rawRestTemplate.exchange(url, HttpMethod.GET, requestEntity, type);
55+
}
56+
57+
4558
public <T> ResponseEntity<T> get(String url, Class<T> type, HttpHeaders headers) throws Exception {
4659
final String ctx = CLASSNAME + ".get";
4760
try {
@@ -169,10 +182,4 @@ public RestTemplateService addHeader(String key, List<String> value) {
169182
return this;
170183
}
171184

172-
public RestTemplateService acceptingSsl() {
173-
174-
175-
return this;
176-
177-
}
178185
}
Lines changed: 26 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
package com.park.utmstack.web.rest.util;
22

3-
import com.park.utmstack.domain.application_events.enums.ApplicationEventType;
43
import com.park.utmstack.security.jwt.JWTFilter;
5-
import com.park.utmstack.service.application_events.ApplicationEventService;
4+
import com.park.utmstack.service.dto.web_pdf.PdfServiceResponse;
65
import com.park.utmstack.service.util.PdfService;
7-
import com.park.utmstack.util.ResponseUtil;
86
import com.park.utmstack.web.rest.errors.BadRequestAlertException;
9-
import javassist.NotFoundException;
7+
import lombok.RequiredArgsConstructor;
108
import org.slf4j.Logger;
119
import org.slf4j.LoggerFactory;
1210
import org.springframework.http.HttpHeaders;
13-
import org.springframework.http.HttpStatus;
1411
import org.springframework.http.MediaType;
1512
import org.springframework.http.ResponseEntity;
1613
import org.springframework.web.bind.annotation.*;
@@ -19,63 +16,41 @@
1916
* REST controller for managing {@link PdfGeneratorResource}.
2017
*/
2118
@RestController
19+
@RequiredArgsConstructor
2220
@RequestMapping("/api")
2321
public class PdfGeneratorResource {
2422

2523
private static final String CLASSNAME = "PdfGeneratorResource";
2624
private final Logger log = LoggerFactory.getLogger(PdfGeneratorResource.class);
2725

28-
private final ApplicationEventService applicationEventService;
29-
30-
3126
private final PdfService pdfService;
3227

33-
public PdfGeneratorResource(
34-
ApplicationEventService applicationEventService,
35-
PdfService pdfService) {
36-
this.applicationEventService = applicationEventService;
37-
this.pdfService = pdfService;
38-
}
28+
@GetMapping("/generate-pdf-report")
29+
public ResponseEntity<?> getPdfReportInBytes(@RequestParam String url,
30+
@RequestParam PdfService.PdfAccessTypes accessType,
31+
@RequestParam String filename,
32+
@RequestHeader(JWTFilter.AUTHORIZATION_HEADER) String accessKey) {
3933

40-
/**
41-
* {@code GET /generate-pdf-report} : get pdf report in bytes, from a dashboard or compliance.
42-
*
43-
* @return the {@link ResponseEntity} with status {@code 200 (OK)} and the pdf report in bytes in body.
44-
*/
45-
@RequestMapping(
46-
value = "/generate-pdf-report",
47-
produces = MediaType.APPLICATION_PDF_VALUE,
48-
method = RequestMethod.GET
49-
)
50-
public ResponseEntity getPdfReportInBytes(@RequestParam String url,
51-
@RequestParam PdfService.PdfAccessTypes accessType,
52-
@RequestParam String filename,
53-
@RequestHeader(JWTFilter.AUTHORIZATION_HEADER) String accessKey) {
5434
final String ctx = CLASSNAME + ".getPdfReportInBytes";
55-
try {
56-
if (accessType == PdfService.PdfAccessTypes.PDF_TYPE_INTERNAL) {
57-
throw new BadRequestAlertException("Access type ("+ accessType.get() +") not allowed","pdfreport","accesskeynotvalid");
58-
}
59-
log.debug("REST request to get pdf report");
60-
61-
HttpHeaders headers = new HttpHeaders();
62-
headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
63-
headers.add(HttpHeaders.PRAGMA, "no-cache");
64-
headers.add(HttpHeaders.EXPIRES, "0");
65-
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + filename);
66-
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE);
6735

68-
byte [] resultPdf = pdfService.getPdf( url, accessKey.substring(7), accessType.get());
69-
if (resultPdf != null && resultPdf.length > 0 ) {
70-
return ResponseEntity.ok().headers(headers).body(resultPdf);
71-
} else {
72-
throw new NotFoundException("We couldn't generate the pdf, reason: No data returned from PDF service");
73-
}
74-
} catch (Exception e) {
75-
String msg = ctx + ": " + e.getLocalizedMessage();
76-
log.error(msg);
77-
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
78-
return ResponseUtil.buildErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR, msg);
36+
if (accessType == PdfService.PdfAccessTypes.PDF_TYPE_INTERNAL) {
37+
throw new BadRequestAlertException(String.format("PDF Service not implemented for %s", accessType), CLASSNAME, null);
7938
}
39+
40+
log.debug("REST request to get pdf report");
41+
42+
PdfServiceResponse pdfResponse =
43+
pdfService.downloadPdf(url, accessKey.substring(7), accessType.get());
44+
45+
HttpHeaders headers = new HttpHeaders();
46+
headers.add(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
47+
headers.add(HttpHeaders.PRAGMA, "no-cache");
48+
headers.add(HttpHeaders.EXPIRES, "0");
49+
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + filename);
50+
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE);
51+
52+
return ResponseEntity.ok()
53+
.headers(headers)
54+
.body(pdfResponse.getPdfBytes());
8055
}
8156
}

installer/docker/plugins.go

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func SetPluginsConfigs(conf *config.Config, stack *StackConfig) error {
3939
analysisPipeline := PluginsConfig{}
4040
analysisPipeline.Plugins = make(map[string]PluginConfig)
4141
analysisPipeline.Plugins["analysis"] = PluginConfig{
42-
Order: []string{"com.utmstack.events", "cel"},
42+
Order: []string{"com.utmstack.events", "cel", "feeds"},
4343
}
4444

4545
correlationPipeline := PluginsConfig{}
@@ -48,15 +48,6 @@ func SetPluginsConfigs(conf *config.Config, stack *StackConfig) error {
4848
Order: []string{"com.utmstack.alerts", "com.utmstack.soc-ai"},
4949
}
5050

51-
inputPipeline := PluginsConfig{}
52-
inputPipeline.Plugins = make(map[string]PluginConfig)
53-
inputPipeline.Plugins["http-input"] = PluginConfig{
54-
Port: 8082,
55-
}
56-
inputPipeline.Plugins["grpc-input"] = PluginConfig{
57-
Port: 8083,
58-
}
59-
6051
notificationPipeline := PluginsConfig{}
6152
notificationPipeline.Plugins = make(map[string]PluginConfig)
6253
notificationPipeline.Plugins["notification"] = PluginConfig{
@@ -103,11 +94,6 @@ func SetPluginsConfigs(conf *config.Config, stack *StackConfig) error {
10394
return fmt.Errorf("error writing correlation pipeline config: %w", err)
10495
}
10596

106-
err = utils.WriteYAML(filepath.Join(pipelineDir, "system_plugins_input.yaml"), inputPipeline)
107-
if err != nil {
108-
return fmt.Errorf("error writing input pipeline config: %w", err)
109-
}
110-
11197
err = utils.WriteYAML(filepath.Join(pipelineDir, "system_plugins_notification.yaml"), notificationPipeline)
11298
if err != nil {
11399
return fmt.Errorf("error writing notification pipeline config: %w", err)

plugins/alerts/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ module github.com/utmstack/UTMStack/plugins/alerts
33
go 1.25.5
44

55
require (
6-
github.com/threatwinds/go-sdk v1.1.4
6+
github.com/google/uuid v1.6.0
7+
github.com/threatwinds/go-sdk v1.1.6
78
github.com/tidwall/gjson v1.18.0
89
google.golang.org/protobuf v1.36.11
910
)
@@ -24,7 +25,6 @@ require (
2425
github.com/goccy/go-json v0.10.5 // indirect
2526
github.com/goccy/go-yaml v1.19.2 // indirect
2627
github.com/google/cel-go v0.26.1 // indirect
27-
github.com/google/uuid v1.6.0 // indirect
2828
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
2929
github.com/json-iterator/go v1.1.12 // indirect
3030
github.com/klauspost/cpuid/v2 v2.3.0 // indirect

plugins/alerts/go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
9191
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9292
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
9393
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
94-
github.com/threatwinds/go-sdk v1.1.4 h1:RASWY7333hFHqUl5oVDeLrBdS+cOMehZyTUgl/dZfPg=
95-
github.com/threatwinds/go-sdk v1.1.4/go.mod h1:N19iqJPaNAoWwZTCuFvV0hIvT0D1jOR1KkKYgAoPLmw=
94+
github.com/threatwinds/go-sdk v1.1.6 h1:ouQsAzAnNKTj65aZWQnJGXQSt+2qiKukdOQlZMrKHDQ=
95+
github.com/threatwinds/go-sdk v1.1.6/go.mod h1:N19iqJPaNAoWwZTCuFvV0hIvT0D1jOR1KkKYgAoPLmw=
9696
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
9797
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
9898
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=

0 commit comments

Comments
 (0)