Skip to content
Snippets Groups Projects
Commit fee78971 authored by nahyun's avatar nahyun
Browse files

feat: certificate 인증서 발급

parent 2fedb7ce
No related branches found
No related tags found
1 merge request!15Feat/certificate
......@@ -25,6 +25,7 @@ public class CertificateController {
public ResponseEntity<Object> create(@RequestParam String projectId,
@RequestBody CertificateDTO dto,
HttpServletRequest request) {
System.out.println("1");
certificateService.createCertificate(
projectId,
dto,
......@@ -89,5 +90,6 @@ public class CertificateController {
);
return ResponseEntity.ok().build();
}
/*인증서 검색*/
}
package com.aolda.itda.dto.certificate;
import com.aolda.itda.entity.certificate.Challenge;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.*;
......@@ -12,10 +13,15 @@ import java.time.LocalDateTime;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CertificateDTO {
private Long certificateId;
private String projectId;
private String domain;
private LocalDateTime expiredAt; // 필요 시
private Boolean isDeleted;
private String description; // 추가 설명
private Long certificateId; // 인증서 고유 ID
private String projectId; // 프로젝트 식별자
private String domain; // SSL 인증받을 도메인 주소
private String email; // 도메인 소유자의 이메일
private LocalDateTime expiredAt; // 인증서 만료일
private Challenge challenge; // 챌린지 방식 (HTTP, DNS_CLOUDFLARE)
private Boolean isDeleted; // 삭제 여부 (soft delete)
private String description; // 설명 (필요시 자유롭게 작성)
}
/* 이메일, 챌린지 방식, http인지 dns인지... "*/
//도메인, 소유자 이메일, 챌린지 방식 확실하게 들어가야함!!
/*erd 보고 만들기*/
......@@ -23,10 +23,6 @@ public class Certificate extends BaseTimeEntity {
@Column(nullable = false)
private Long certificateId;
@ManyToOne
@JoinColumn(nullable = false, name = "user_id")
private User user;
@Column(length = 64)
private String projectId;
......@@ -57,5 +53,6 @@ public class Certificate extends BaseTimeEntity {
}
public void setDescription(String description) {
}
}
......@@ -3,6 +3,7 @@ package com.aolda.itda.service.certificate;
import com.aolda.itda.dto.PageResp;
import com.aolda.itda.dto.certificate.CertificateDTO;
import com.aolda.itda.entity.certificate.Certificate;
import com.aolda.itda.entity.certificate.Challenge;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.repository.certificate.CertificateRepository;
......@@ -14,6 +15,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
......@@ -52,10 +54,12 @@ public class CertificateService {
}
/* 인증서 생성 */
public CertificateDTO createCertificate(String projectId, CertificateDTO dto, List<String> projects) {
/*public CertificateDTO createCertificate(String projectId,
CertificateDTO dto,
List<String> projects) {
// 프로젝트 권한 검증
authService.validateProjectAuth(projects, projectId);
System.out.println("2");
// DTO 유효성 검사
validateDTO(dto);
......@@ -67,9 +71,52 @@ public class CertificateService {
.build();
certificateRepository.save(certificate);
System.out.println("3");
// 생성 로직 (certbot 호출 등) 필요 시 추가
return toDTO(certificate);
}*/
/* 인증서 생성 + lego 호출 */
public CertificateDTO createCertificate(String projectId, CertificateDTO dto, List<String> projects) {
// 1) 권한 체크
authService.validateProjectAuth(projects, projectId);
// 2) DTO 검증
validateDTO(dto);
// 3) lego 명령어 구성
ProcessBuilder pb = buildLegoProcess(dto);
// 4) lego 실행
int exitCode;
try {
Process process = pb.start();
exitCode = process.waitFor();
if (exitCode != 0) {
String err = new String(process.getErrorStream().readAllBytes());
log.error("[lego-error] {}", err);
throw new CustomException(ErrorCode.FAIL_CREATE_CONF,
"lego 오류: " + err);
}
} catch (Exception e) {
log.error("[lego-exec] {}", e.getMessage());
throw new CustomException(ErrorCode.FAIL_CREATE_CONF,
"lego 실행 실패");
}
// 5) 엔티티 저장
Certificate certificate = Certificate.builder()
.projectId(projectId)
.domain(dto.getDomain())
.email(dto.getEmail())
.challenge(dto.getChallenge())
.expiredAt(dto.getExpiredAt()) // 필요 시 lego 출력 파싱
.isDeleted(false)
.description(dto.getDescription())
.build();
certificateRepository.save(certificate);
return toDTO(certificate);
}
......@@ -134,4 +181,39 @@ public class CertificateService {
.expiredAt(certificate.getExpiredAt())
.build();
}
/* lego ProcessBuilder 생성 */
private ProcessBuilder buildLegoProcess(CertificateDTO dto) {
String basePath = "/data/lego"; // 인증서 저장 루트(볼륨)
List<String> cmd = new ArrayList<>();
cmd.add("/usr/local/bin/lego");
cmd.add("--accept-tos");
cmd.add("--email"); cmd.add(dto.getEmail());
cmd.add("--path"); cmd.add(basePath);
if (dto.getChallenge() == Challenge.HTTP) {
cmd.add("--http");
cmd.add("--http.webroot");
cmd.add("/data/letsencrypt-acme-challenge");
} else if (dto.getChallenge() == Challenge.DNS_CLOUDFLARE) {
cmd.add("--dns");
cmd.add("cloudflare");
// CLOUDFLARE_API_TOKEN 환경변수를 컨테이너에 세팅했다고 가정
}
cmd.add("--domains"); cmd.add(dto.getDomain());
cmd.add("run"); // 최초 발급(run) / renew(갱신)
return new ProcessBuilder(cmd)
.redirectErrorStream(true);
}
}
// 여기서 매소드를 create로 해서 lego --accept-tos --email "email@example.com" --http --http.webroot data/letsencrypt-acme-challenge --path /data/lego --domains www.example.com run
// 이거 이메일 . 도메인 으로 넣어서 실제 인증서 연동하기!!!
// 그리고 Dto에 관리자 이메일, 인증서 완료일, 챌린지 방식 추가하기
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment