package de.mlessmann.certassist.web; import de.mlessmann.certassist.models.Certificate; import de.mlessmann.certassist.models.CertificateInfo; import de.mlessmann.certassist.models.CertificateInfoSubject; import de.mlessmann.certassist.repositories.CertificateRepository; import de.mlessmann.certassist.service.CertificateCreationService; import de.mlessmann.certassist.web.dto.PrivateKey; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.util.MimeTypeUtils; import org.springframework.web.bind.annotation.*; import java.nio.charset.StandardCharsets; @RestController @RequestMapping("/api") @RequiredArgsConstructor(onConstructor_ = @Autowired) public class CertificatesEndpoint { public static final String MIME_PEM_FILE = "application/x-pem-file"; private final CertificateRepository certificateRepository; private final CertificateCreationService certificateCreationService; @GetMapping("/certificates") @Operation(description = "Fetches certificates", responses = { @ApiResponse(responseCode = "200", description = "Contains the returned certificates of the requested page.") }) public ResponseEntity> getCertificates(@ParameterObject Pageable pageable) { var certificates = certificateRepository.findAll(pageable); return ResponseEntity.ok(DocumentedPage.of(certificates)); } @GetMapping("/certificates/{fingerprint}") @Operation( description = "Fetches a single certificate by the provided fingerprint", responses = { @ApiResponse(responseCode = "200") } ) public ResponseEntity getCertificate(@PathVariable String fingerprint) { var certificate = certificateRepository.findByFingerprintIs(fingerprint); return ResponseEntity.ok(certificate); } @PostMapping("/certificates") @Operation(description = "Requests a new certificate", responses = { @ApiResponse(responseCode = "400", description = "One of the provided parameters is invalid."), @ApiResponse(responseCode = "200", description = "Returns the newly created certificate.") }) public ResponseEntity createCertificate(@RequestBody CertificateInfo request) { var createdCertificate = certificateCreationService.createCertificate( CertificateInfo.builder() .type(CertificateInfo.RequestType.STANDALONE_CERTIFICATE) .issuer(CertificateInfoSubject.builder() .commonName("Test") ) .build() ); return ResponseEntity.ok(createdCertificate); } @GetMapping(value = "/certificates/{cert}/privateKey", produces = { MimeTypeUtils.APPLICATION_JSON_VALUE, MIME_PEM_FILE }) @Operation(description = "Fetches the private key corresponding to the provided certificate.", responses = { @ApiResponse(responseCode = "200", content = { @Content(mediaType = MimeTypeUtils.APPLICATION_JSON_VALUE, schema = @Schema(implementation = PrivateKey.class)), @Content(mediaType = MIME_PEM_FILE, schema = @Schema(type = "string", description = "PEM formatted private key content")) }) }) public ResponseEntity getCertificatePrivateKey( @RequestHeader("Accept") String acceptType, @PathVariable String cert ) { var requestedCert = certificateRepository.findByFingerprintIs(cert); if (MimeTypeUtils.APPLICATION_JSON_VALUE.equals(acceptType)) { String pemContent = new String(requestedCert.getPrivateKey(), StandardCharsets.UTF_8); var pKey = new PrivateKey(pemContent); return ResponseEntity.ok(pKey); } else if (MIME_PEM_FILE.equals(acceptType)) { String pemContent = new String(requestedCert.getPrivateKey(), StandardCharsets.UTF_8); return ResponseEntity.ok(pemContent); } else { return ResponseEntity.badRequest().build(); } } }