From 9b281a3af1f26ce3d91d71e3be3cc9c4abe90ac1 Mon Sep 17 00:00:00 2001 From: Torge Hamann <37174525+torge-hmn@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:14:39 +0100 Subject: [PATCH 1/4] Add basic certificate models and repositories --- build.gradle.kts | 1 + .../certassist/models/Certificate.java | 47 +++++++++++++ .../models/CertificateExtension.java | 19 ++++++ .../models/CertificateSubjectPreset.java | 26 ++++++++ .../certassist/models/CertificateType.java | 7 ++ .../CertificateExtensionRepository.java | 8 +++ .../repositories/CertificateRepository.java | 10 +++ .../CertificateSubjectPresetRepository.java | 8 +++ .../repositories/UserRepository.java | 5 +- .../CertificateExtensionRepositoryTest.java | 27 ++++++++ .../CertificateRepositoryTest.java | 66 +++++++++++++++++++ ...ertificateSubjectPresetRepositoryTest.java | 26 ++++++++ .../repositories/UserRepositoryTest.java | 8 ++- 13 files changed, 251 insertions(+), 7 deletions(-) create mode 100644 src/main/java/de/mlessmann/certassist/models/Certificate.java create mode 100644 src/main/java/de/mlessmann/certassist/models/CertificateExtension.java create mode 100644 src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java create mode 100644 src/main/java/de/mlessmann/certassist/models/CertificateType.java create mode 100644 src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java create mode 100644 src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java create mode 100644 src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java create mode 100644 src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java create mode 100644 src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java create mode 100644 src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java diff --git a/build.gradle.kts b/build.gradle.kts index 4290980..f6c7c81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,6 +36,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-jdbc") implementation("org.xerial:sqlite-jdbc") implementation("org.springframework.boot:spring-boot-starter-data-jpa") + implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.hibernate.orm:hibernate-community-dialects") implementation("org.springframework.boot:spring-boot-starter-security") diff --git a/src/main/java/de/mlessmann/certassist/models/Certificate.java b/src/main/java/de/mlessmann/certassist/models/Certificate.java new file mode 100644 index 0000000..1cf9644 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/Certificate.java @@ -0,0 +1,47 @@ +package de.mlessmann.certassist.models; + +import jakarta.persistence.*; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +@Entity +@Data +public class Certificate { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; + + @NotNull + private String oid; + + @NotNull + private CertificateType type; + + @NotNull + private String commonName; + + private String trustingAuthority; + + @Min(1) + private int requestedKeyLength; + + @Min(1) + private int requestedValidityDays; + + private String subjectEmailAddress; + private String subjectOrganization; + private String subjectOrganizationalUnit; + private String subjectCountry; + private String subjectState; + private String subjectLocality; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + private List certificateExtension = new ArrayList<>(); +} diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateExtension.java b/src/main/java/de/mlessmann/certassist/models/CertificateExtension.java new file mode 100644 index 0000000..f9e6ca0 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/CertificateExtension.java @@ -0,0 +1,19 @@ +package de.mlessmann.certassist.models; + +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +@Entity +@Data +public class CertificateExtension { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; + + private String identifier; + private String value; +} diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java b/src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java new file mode 100644 index 0000000..ba8a033 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/CertificateSubjectPreset.java @@ -0,0 +1,26 @@ +package de.mlessmann.certassist.models; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; + +@Entity +@Data +public class CertificateSubjectPreset { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; + + private String emailAddress; + private String organization; + private String organizationalUnit; + private String country; + private String state; + private String locality; +} diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateType.java b/src/main/java/de/mlessmann/certassist/models/CertificateType.java new file mode 100644 index 0000000..6353710 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/models/CertificateType.java @@ -0,0 +1,7 @@ +package de.mlessmann.certassist.models; + +public enum CertificateType { + ROOT_AUTHORITY, + STANDALONE_CERTIFICATE, + NORMAL_CERTIFICATE, +} diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java new file mode 100644 index 0000000..262c999 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateExtensionRepository.java @@ -0,0 +1,8 @@ +package de.mlessmann.certassist.repositories; + +import de.mlessmann.certassist.models.CertificateExtension; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CertificateExtensionRepository extends CrudRepository {} diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java new file mode 100644 index 0000000..ba15b30 --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java @@ -0,0 +1,10 @@ +package de.mlessmann.certassist.repositories; + +import de.mlessmann.certassist.models.Certificate; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CertificateRepository extends CrudRepository { + Certificate findByOid(String oid); +} diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java new file mode 100644 index 0000000..c74e86d --- /dev/null +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepository.java @@ -0,0 +1,8 @@ +package de.mlessmann.certassist.repositories; + +import de.mlessmann.certassist.models.CertificateSubjectPreset; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CertificateSubjectPresetRepository extends CrudRepository {} diff --git a/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java b/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java index 4f12c8b..6459e0a 100644 --- a/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java +++ b/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java @@ -5,7 +5,4 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository -public interface UserRepository extends CrudRepository { - - User findUserById(long id); -} +public interface UserRepository extends CrudRepository {} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java new file mode 100644 index 0000000..c5431db --- /dev/null +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java @@ -0,0 +1,27 @@ +package de.mlessmann.certassist.repositories; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import de.mlessmann.certassist.models.CertificateExtension; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertificateExtensionRepositoryTest { + + @Autowired + private CertificateExtensionRepository repository; + + @Test + @Transactional + void findCertificate() { + CertificateExtension certificateExtension = new CertificateExtension(); + certificateExtension.setValue("test-value"); + repository.save(certificateExtension); + + assertThat(repository.findById(certificateExtension.getId()).orElseThrow().getValue()).isEqualTo("test-value"); + } +} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java new file mode 100644 index 0000000..2db68dc --- /dev/null +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java @@ -0,0 +1,66 @@ +package de.mlessmann.certassist.repositories; + +import static org.assertj.core.api.Assertions.assertThat; + +import de.mlessmann.certassist.models.Certificate; +import de.mlessmann.certassist.models.CertificateExtension; +import de.mlessmann.certassist.models.CertificateType; +import jakarta.transaction.Transactional; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertificateRepositoryTest { + + @Autowired + private CertificateRepository repository; + + @Autowired + private CertificateExtensionRepository extensionRepository; + + private Certificate getCertificate() { + final Certificate certificate = new Certificate(); + certificate.setOid("test"); + certificate.setCommonName("test-cn"); + certificate.setType(CertificateType.NORMAL_CERTIFICATE); + certificate.setRequestedKeyLength(1); + certificate.setRequestedValidityDays(1); + + return certificate; + } + + @Test + @Transactional + void findCertificate() { + final Certificate certificate = getCertificate(); + repository.save(certificate); + + assertThat(repository.findById(certificate.getId()).orElseThrow().getOid()).isEqualTo("test"); + } + + @Test + @Transactional + void findCertificateByOid() { + final Certificate certificate = getCertificate(); + repository.save(certificate); + + assertThat(repository.findByOid("test").getCommonName()).isEqualTo("test-cn"); + } + + @Test + @Transactional + void findCertificateWithExtension() { + final Certificate certificate = getCertificate(); + CertificateExtension extension = new CertificateExtension(); + extension.setValue("test-ext-value"); + certificate.setCertificateExtension(List.of(extension)); + repository.save(certificate); + + assertThat(repository.findById(certificate.getId()).orElseThrow().getCertificateExtension()).hasSize(1); + assertThat(extensionRepository.findAll()) + .singleElement() + .satisfies(ce -> assertThat(ce.getValue()).isEqualTo("test-ext-value")); + } +} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java new file mode 100644 index 0000000..2c73ba6 --- /dev/null +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateSubjectPresetRepositoryTest.java @@ -0,0 +1,26 @@ +package de.mlessmann.certassist.repositories; + +import static org.assertj.core.api.Assertions.assertThat; + +import de.mlessmann.certassist.models.CertificateSubjectPreset; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CertificateSubjectPresetRepositoryTest { + + @Autowired + private CertificateSubjectPresetRepository repository; + + @Test + @Transactional + void findCertificateSubjectPreset() { + final CertificateSubjectPreset certificateSubjectPreset = new CertificateSubjectPreset(); + certificateSubjectPreset.setCountry("DE"); + repository.save(certificateSubjectPreset); + + assertThat(repository.findById(certificateSubjectPreset.getId()).orElseThrow().getCountry()).isEqualTo("DE"); + } +} diff --git a/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java index 0e6f342..da2468f 100644 --- a/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java +++ b/src/test/java/de/mlessmann/certassist/repositories/UserRepositoryTest.java @@ -1,12 +1,13 @@ package de.mlessmann.certassist.repositories; +import static org.assertj.core.api.Assertions.assertThat; + import de.mlessmann.certassist.models.User; +import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import static org.assertj.core.api.Assertions.assertThat; - @SpringBootTest class UserRepositoryTest { @@ -14,11 +15,12 @@ class UserRepositoryTest { private UserRepository userRepository; @Test + @Transactional void findUserById() { final User user = new User(); user.setUsername("test"); userRepository.save(user); - assertThat(userRepository.findUserById(user.getId()).getUsername()).isEqualTo("test"); + assertThat(userRepository.findById(user.getId()).orElseThrow().getUsername()).isEqualTo("test"); } } -- 2.45.3 From 5e30337086b78fb13dc801f7f480a4c38d10dfb5 Mon Sep 17 00:00:00 2001 From: Torge Hamann <37174525+torge-hmn@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:27:39 +0100 Subject: [PATCH 2/4] Review comments --- .../mlessmann/certassist/models/Certificate.java | 4 +--- .../java/de/mlessmann/certassist/models/User.java | 6 ++++-- .../certassist/openssl/CertificateRequest.java | 1 + .../repositories/CertificateRepository.java | 4 +--- .../certassist/repositories/UserRepository.java | 2 +- .../CertificateExtensionRepositoryTest.java | 1 - .../repositories/CertificateRepositoryTest.java | 14 +++----------- 7 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/main/java/de/mlessmann/certassist/models/Certificate.java b/src/main/java/de/mlessmann/certassist/models/Certificate.java index 1cf9644..f7a5997 100644 --- a/src/main/java/de/mlessmann/certassist/models/Certificate.java +++ b/src/main/java/de/mlessmann/certassist/models/Certificate.java @@ -19,9 +19,7 @@ public class Certificate { private String id; @NotNull - private String oid; - - @NotNull + @Enumerated(EnumType.STRING) private CertificateType type; @NotNull diff --git a/src/main/java/de/mlessmann/certassist/models/User.java b/src/main/java/de/mlessmann/certassist/models/User.java index 78f77a4..42a221e 100644 --- a/src/main/java/de/mlessmann/certassist/models/User.java +++ b/src/main/java/de/mlessmann/certassist/models/User.java @@ -4,6 +4,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -12,8 +13,9 @@ import lombok.Setter; public class User { @Id - @GeneratedValue(strategy = GenerationType.SEQUENCE) - private Long id; + @GeneratedValue(strategy = GenerationType.UUID) + @Setter(AccessLevel.NONE) + private String id; @Setter private String username; diff --git a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java index 4d6ab9d..54befcd 100644 --- a/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java +++ b/src/main/java/de/mlessmann/certassist/openssl/CertificateRequest.java @@ -9,6 +9,7 @@ import lombok.Data; public class CertificateRequest { @Builder.Default + @Deprecated private String oid = UUID.randomUUID().toString(); private RequestType type; diff --git a/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java b/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java index ba15b30..fed956f 100644 --- a/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java +++ b/src/main/java/de/mlessmann/certassist/repositories/CertificateRepository.java @@ -5,6 +5,4 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository -public interface CertificateRepository extends CrudRepository { - Certificate findByOid(String oid); -} +public interface CertificateRepository extends CrudRepository {} diff --git a/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java b/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java index 6459e0a..6839491 100644 --- a/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java +++ b/src/main/java/de/mlessmann/certassist/repositories/UserRepository.java @@ -5,4 +5,4 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; @Repository -public interface UserRepository extends CrudRepository {} +public interface UserRepository extends CrudRepository {} diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java index c5431db..8f40ca4 100644 --- a/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateExtensionRepositoryTest.java @@ -1,7 +1,6 @@ package de.mlessmann.certassist.repositories; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; import de.mlessmann.certassist.models.CertificateExtension; import jakarta.transaction.Transactional; diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java index 2db68dc..e7008fc 100644 --- a/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java @@ -22,7 +22,6 @@ class CertificateRepositoryTest { private Certificate getCertificate() { final Certificate certificate = new Certificate(); - certificate.setOid("test"); certificate.setCommonName("test-cn"); certificate.setType(CertificateType.NORMAL_CERTIFICATE); certificate.setRequestedKeyLength(1); @@ -37,16 +36,9 @@ class CertificateRepositoryTest { final Certificate certificate = getCertificate(); repository.save(certificate); - assertThat(repository.findById(certificate.getId()).orElseThrow().getOid()).isEqualTo("test"); - } - - @Test - @Transactional - void findCertificateByOid() { - final Certificate certificate = getCertificate(); - repository.save(certificate); - - assertThat(repository.findByOid("test").getCommonName()).isEqualTo("test-cn"); + Certificate foundCertificate = repository.findById(certificate.getId()).orElseThrow(); + assertThat(foundCertificate.getCommonName()).isEqualTo("test-cn"); + assertThat(foundCertificate.getType()).isEqualTo(CertificateType.NORMAL_CERTIFICATE); } @Test -- 2.45.3 From a2ced3533a41dea8b8aa92d0ee61be0af4176a0a Mon Sep 17 00:00:00 2001 From: Torge Hamann <37174525+torge-hmn@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:31:15 +0100 Subject: [PATCH 3/4] Adjust cert enum --- .../de/mlessmann/certassist/models/CertificateType.java | 7 ++++--- .../certassist/repositories/CertificateRepositoryTest.java | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateType.java b/src/main/java/de/mlessmann/certassist/models/CertificateType.java index 6353710..5c6ea66 100644 --- a/src/main/java/de/mlessmann/certassist/models/CertificateType.java +++ b/src/main/java/de/mlessmann/certassist/models/CertificateType.java @@ -1,7 +1,8 @@ package de.mlessmann.certassist.models; public enum CertificateType { - ROOT_AUTHORITY, - STANDALONE_CERTIFICATE, - NORMAL_CERTIFICATE, + ROOT_CA, + STANDALONE_CERT, + SIGNED_CERT, + CLIENT_CERT } diff --git a/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java index e7008fc..f107461 100644 --- a/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java +++ b/src/test/java/de/mlessmann/certassist/repositories/CertificateRepositoryTest.java @@ -23,7 +23,7 @@ class CertificateRepositoryTest { private Certificate getCertificate() { final Certificate certificate = new Certificate(); certificate.setCommonName("test-cn"); - certificate.setType(CertificateType.NORMAL_CERTIFICATE); + certificate.setType(CertificateType.SIGNED_CERT); certificate.setRequestedKeyLength(1); certificate.setRequestedValidityDays(1); @@ -38,7 +38,7 @@ class CertificateRepositoryTest { Certificate foundCertificate = repository.findById(certificate.getId()).orElseThrow(); assertThat(foundCertificate.getCommonName()).isEqualTo("test-cn"); - assertThat(foundCertificate.getType()).isEqualTo(CertificateType.NORMAL_CERTIFICATE); + assertThat(foundCertificate.getType()).isEqualTo(CertificateType.SIGNED_CERT); } @Test -- 2.45.3 From 1fd859bb4580dd659e45738ab5af5b74bdb55056 Mon Sep 17 00:00:00 2001 From: Torge Hamann <37174525+torge-hmn@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:33:12 +0100 Subject: [PATCH 4/4] Formatting --- .../java/de/mlessmann/certassist/models/CertificateType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/mlessmann/certassist/models/CertificateType.java b/src/main/java/de/mlessmann/certassist/models/CertificateType.java index 5c6ea66..3b44140 100644 --- a/src/main/java/de/mlessmann/certassist/models/CertificateType.java +++ b/src/main/java/de/mlessmann/certassist/models/CertificateType.java @@ -4,5 +4,5 @@ public enum CertificateType { ROOT_CA, STANDALONE_CERT, SIGNED_CERT, - CLIENT_CERT + CLIENT_CERT, } -- 2.45.3