[MODIFY] 외부 Edge 패키지 등록 API 수정, EdgePkgInfoRequest 제거 및 EdgeSWVO 추가, RestTemplate 초기화 및 SSL 무시 설정 구현

main
bjkim 8 months ago
parent 143f83e298
commit ea87fef5b0

@ -2,16 +2,29 @@ package kr.re.etri.autoflow.controllers;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.re.etri.autoflow.payload.request.EdgePkgInfoRequest;
import jakarta.annotation.PostConstruct;
import kr.re.etri.autoflow.payload.request.EdgeSWVO;
import kr.re.etri.autoflow.service.ExternalAuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.cert.X509Certificate;
import java.util.Map;
@RestController
@ -22,6 +35,47 @@ public class ExternalAuthController {
private final ExternalAuthService externalAuthService;
private RestTemplate restTemplate;
@PostConstruct
public void init() {
this.restTemplate = createUnsafeRestTemplate();
}
/**
* SSL RestTemplate
*/
private RestTemplate createUnsafeRestTemplate() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
return new RestTemplate(requestFactory);
} catch (Exception e) {
throw new RuntimeException("Failed to create unsafe RestTemplate", e);
}
}
@Operation(summary = "외부 로그인 후 사용자 정보 조회", description = "외부 Spring 백엔드에 로그인 요청 후 id, name, token을 반환합니다.")
@PostMapping("/signin")
public ResponseEntity<ApiResponse> signin(@RequestBody SigninRequest request) {
@ -47,42 +101,50 @@ public class ExternalAuthController {
return ResponseEntity.ok(ApiResponse.failure(e.getMessage()));
}
}
private final String TARGET_URL = "https://cuuva.com:24443/api/datamanager/edge-pkg/add";
@PostMapping(value = "/add", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(
summary = "외부 Edge 패키지 등록",
description = "외부 서버로 Edge 패키지 정보를 파일과 함께 전송하여 등록합니다.",
security = @SecurityRequirement(name = "bearerAuth") // 이 컨트롤러만 Bearer 적용
description = "VO 정보와 파일을 업로드하여 외부 Edge 패키지를 등록합니다.",
security = {@SecurityRequirement(name = "bearerAuth")}
)
@PostMapping(value = "/add", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> addEdgePackage(
@Parameter(description = "로그인 시 발급받은 Bearer 토큰")
@RequestHeader("Authorization") String bearerToken,
@Parameter(description = "Edge 패키지 등록 요청 데이터(JSON 형식)")
@RequestPart(value = "edgePkgInfoVO", required = true) EdgePkgInfoRequest edgePkgInfoRequest,
@Parameter(description = "업로드할 패키지 파일")
@RequestPart(value = "file", required = false) MultipartFile file
@RequestPart("sw_id") String sw_id,
@RequestPart("sw_name") String sw_name,
@RequestPart("sw_version") String sw_version,
@RequestPart("creation_datetime") String creation_datetime,
@RequestPart("auth_id") String auth_id,
@RequestPart(value = "files", required = false) MultipartFile file, // ✅ 수정: file → files
@RequestHeader("Authorization") String bearerToken
) {
try {
// VO 생성
EdgeSWVO edgeSWVO = new EdgeSWVO();
edgeSWVO.setSw_id(sw_id);
edgeSWVO.setSw_name(sw_name);
edgeSWVO.setSw_version(sw_version);
edgeSWVO.setCreation_datetime(creation_datetime);
edgeSWVO.setAuth_id(auth_id);
edgeSWVO.setFile(file); // ✅ 반드시 추가해야 WebClient에서 파일 전송 가능
// 토큰 정제
String token = bearerToken.startsWith("Bearer ") ? bearerToken.substring(7) : bearerToken;
// 서비스 호출
Object response = externalAuthService.uploadEdgePackage(bearerToken, edgePkgInfoRequest, file);
return ResponseEntity.ok(response);
Map<String, Object> result = externalAuthService.addEdgePackage(token, edgeSWVO);
} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body(
Map.of("success", false, "message", "잘못된 요청: " + e.getMessage())
);
return ResponseEntity.ok(result);
} catch (Exception e) {
return ResponseEntity.internalServerError().body(
Map.of("success", false, "message", "파일 업로드 실패: " + e.getMessage())
);
return ResponseEntity.badRequest().body(Map.of(
"success", false,
"message", e.getMessage()
));
}
}
// DTO: 요청
public static record SigninRequest(String id, String password) { }

@ -1,51 +0,0 @@
package kr.re.etri.autoflow.payload.request;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.Date;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "Edge 패키지 등록 요청 객체")
public class EdgePkgInfoRequest {
@Schema(description = "Edge 패키지 시리얼 번호", example = "1")
private int ed_pkg_serial;
@Schema(description = "설치 위치", example = "/opt/edge/package")
private String download_location;
@Schema(description = "패키지 ID", example = "pkg_001")
private String sw_id;
@Schema(description = "소프트웨어 버전", example = "v1.0.0")
private String sw_version;
@Schema(description = "소프트웨어 이름", example = "Edge Analytics")
private String sw_name;
@Schema(description = "등록 사용자 ID", example = "admin")
private String user_id;
@Schema(description = "인증 ID", example = "auth_12345")
private String auth_id;
@Schema(description = "설치 OS", example = "Linux")
private String install_os;
@Schema(description = "등록 일시", example = "2025-10-15T14:30:00")
private Date archive_type;
@Schema(description = "실행 여부 (0/1)", example = "1")
private String exec_yn;
@Schema(description = "등록인만 접근 여부 (0/1)", example = "1")
private String secret_at;
}

@ -0,0 +1,19 @@
package kr.re.etri.autoflow.payload.request;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
@Data
public class EdgeSWVO {
private String sw_id;
private String sw_name;
private String sw_version;
private String creation_datetime;
private String auth_id;
// 파일 업로드용
private MultipartFile file;
}

@ -2,13 +2,15 @@ package kr.re.etri.autoflow.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import kr.re.etri.autoflow.payload.request.EdgePkgInfoRequest;
import kr.re.etri.autoflow.payload.request.EdgeSWVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.multipart.MultipartFile;
@ -41,14 +43,22 @@ public class ExternalAuthService {
this.restTemplate = createUnsafeRestTemplate();
}
/** SSL 무시용 RestTemplate 생성 */
/**
* SSL RestTemplate
*/
private RestTemplate createUnsafeRestTemplate() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
@ -66,7 +76,9 @@ public class ExternalAuthService {
}
}
/** Bearer 토큰 발급 */
/**
* Bearer
*/
public Map<String, Object> getUserInfo(String id, String password) {
// 요청 본문
Map<String, String> body = Map.of("id", id, "password", password);
@ -145,36 +157,60 @@ public class ExternalAuthService {
}
}
public Object uploadEdgePackage(String bearerToken, EdgePkgInfoRequest edgePkgInfoRequest, MultipartFile file) throws IOException {
public Map<String, Object> addEdgePackage(String token, EdgeSWVO edgeSWVO) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("Authorization", bearerToken.startsWith("Bearer ") ? bearerToken : "Bearer " + bearerToken);
// Object를 JSON 문자열로 변환
ObjectMapper objectMapper = new ObjectMapper();
String edgePkgInfoJson = objectMapper.writeValueAsString(edgePkgInfoRequest);
headers.setBearerAuth(token);
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("edgePkgInfoVO", edgePkgInfoJson);
if (file != null && !file.isEmpty()) {
body.add("file", new ByteArrayResource(file.getBytes()) {
// 문자열 필드들
body.add("sw_id", edgeSWVO.getSw_id());
body.add("sw_name", edgeSWVO.getSw_name());
body.add("sw_version", edgeSWVO.getSw_version());
body.add("creation_datetime", edgeSWVO.getCreation_datetime());
body.add("auth_id", edgeSWVO.getAuth_id());
// 파일 필드
if (edgeSWVO.getFile() != null && !edgeSWVO.getFile().isEmpty()) {
MultipartFile file = edgeSWVO.getFile();
// Content-Type 지정 + 파일명 유지
ByteArrayResource fileResource = new ByteArrayResource(file.getBytes()) {
@Override
public String getFilename() {
return file.getOriginalFilename();
}
});
@Override
public long contentLength() {
return file.getSize();
}
};
HttpHeaders fileHeaders = new HttpHeaders();
fileHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
HttpEntity<ByteArrayResource> fileEntity = new HttpEntity<>(fileResource, fileHeaders);
body.add("files", fileEntity); // ✅ 반드시 "files"
}
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(body, headers);
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
ResponseEntity<Object> response = restTemplate.exchange(
edgeAddUrl,
HttpMethod.POST,
request,
Object.class
);
try {
ResponseEntity<Map> response = restTemplate.postForEntity(edgeAddUrl, requestEntity, Map.class);
return response.getBody();
if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
return response.getBody();
} else {
throw new RuntimeException("외부 Edge 패키지 등록 실패 (응답 코드: " + response.getStatusCode() + ")");
}
} catch (HttpClientErrorException | HttpServerErrorException e) {
throw new RuntimeException(
e.getStatusCode().value() + " on POST request for \"" + edgeAddUrl + "\": \"" + e.getResponseBodyAsString() + "\""
);
}
}
}

Loading…
Cancel
Save