return type.
12 | * @param the input parameter (key size or curve name)
13 | */
14 | public abstract class BaseJsonWebKeyImportRequestConverter
15 | implements Converter {
16 |
17 | public abstract P getKeyParameter(JsonWebKeyImportRequest request);
18 |
19 | protected BigInteger asInt(final byte[] inBytes) {
20 | return new BigInteger(1, inBytes);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/template/backup/TimeHelperSource.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.template.backup;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | import java.time.OffsetDateTime;
6 | import java.time.ZoneOffset;
7 | import java.time.temporal.ChronoUnit;
8 |
9 | @Component
10 | @SuppressWarnings("java:S6829") //cannot add autowired to the default constructor
11 | public class TimeHelperSource {
12 |
13 | private final OffsetDateTime now;
14 |
15 | public TimeHelperSource() {
16 | this(OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS));
17 | }
18 |
19 | TimeHelperSource(final OffsetDateTime now) {
20 | this.now = now;
21 | }
22 |
23 | public CharSequence now(final int offset) {
24 | return String.valueOf(now.plusSeconds(offset).toEpochSecond());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gradle/verification-metadata-clean.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | true
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/request/ImportKeyRequest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key.request;
2 |
3 |
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.BasePropertiesUpdateModel;
6 | import jakarta.validation.Valid;
7 | import jakarta.validation.constraints.NotNull;
8 | import lombok.Data;
9 |
10 | import java.util.Map;
11 |
12 | @SuppressWarnings("checkstyle:MagicNumber")
13 | @Data
14 | public class ImportKeyRequest {
15 |
16 | @NotNull
17 | @Valid
18 | @JsonProperty("key")
19 | private JsonWebKeyImportRequest key;
20 |
21 | @JsonProperty("attributes")
22 | private BasePropertiesUpdateModel properties;
23 |
24 | @JsonProperty("Hsm")
25 | private Boolean hsm;
26 |
27 | @JsonProperty("tags")
28 | private Map tags;
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/secret/KeyVaultSecretModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.secret;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.Data;
6 |
7 | import java.util.Map;
8 |
9 | @Data
10 | @JsonInclude(JsonInclude.Include.NON_NULL)
11 | public class KeyVaultSecretModel {
12 |
13 | @JsonProperty("id")
14 | private String id;
15 | @JsonProperty("kid")
16 | private String kid;
17 | @JsonProperty("value")
18 | private String value;
19 | @JsonProperty("contentType")
20 | private String contentType;
21 | @JsonProperty("attributes")
22 | private SecretPropertiesModel attributes;
23 | @JsonProperty("tags")
24 | private Map tags;
25 | @JsonProperty("managed")
26 | private Boolean managed;
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/certificate/ReadOnlyLifetimeActionPolicy.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.certificate;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.certificate.id.CertificateEntityId;
4 |
5 | import java.time.OffsetDateTime;
6 | import java.util.List;
7 | import java.util.Map;
8 | import java.util.function.UnaryOperator;
9 |
10 | public interface ReadOnlyLifetimeActionPolicy {
11 |
12 | CertificateEntityId getId();
13 |
14 | OffsetDateTime getCreatedOn();
15 |
16 | OffsetDateTime getUpdatedOn();
17 |
18 | Map getLifetimeActions();
19 |
20 | boolean isAutoRenew();
21 |
22 | void validate(int validityMonths);
23 |
24 | List missedRenewalDays(OffsetDateTime validityStart, UnaryOperator createdToExpiryFunction);
25 | }
26 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/test/java/com/github/nagyesta/lowkeyvault/http/ContentLengthHeaderRemoverTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http;
2 |
3 | import org.apache.http.HttpRequest;
4 | import org.apache.http.protocol.HTTP;
5 | import org.apache.http.protocol.HttpContext;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import static org.mockito.Mockito.*;
9 |
10 | class ContentLengthHeaderRemoverTest {
11 |
12 | @Test
13 | void testProcessShouldRemoveContentLengthWhenCalled() {
14 | //given
15 | final var underTest = new ContentLengthHeaderRemover();
16 | final var request = mock(HttpRequest.class);
17 | final var context = mock(HttpContext.class);
18 |
19 | //when
20 | underTest.process(request, context);
21 |
22 | //then
23 | verify(request).removeHeaders(HTTP.CONTENT_LEN);
24 | verifyNoMoreInteractions(request, context);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/secret/id/VersionedSecretEntityId.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.secret.id;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.BaseEntityId;
4 | import org.springframework.lang.NonNull;
5 | import org.springframework.util.Assert;
6 |
7 | import java.net.URI;
8 |
9 | public class VersionedSecretEntityId
10 | extends SecretEntityId {
11 |
12 | public VersionedSecretEntityId(
13 | @NonNull final URI vault,
14 | @NonNull final String id) {
15 | this(vault, id, BaseEntityId.generateVersion());
16 | }
17 |
18 | public VersionedSecretEntityId(
19 | @NonNull final URI vault,
20 | @NonNull final String id,
21 | @NonNull final String version) {
22 | super(vault, id, version);
23 | Assert.notNull(version, "Version must not be null.");
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupOct-128-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503106,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503106
10 | },
11 | "entityId": "jsonBackupOct-128-72",
12 | "entityVersion": "730490a0df9b4ac78ed675902077a18f",
13 | "keyMaterial": {
14 | "k": "sx32Vta2Zx1BsdQBY2l5iQ",
15 | "key_ops": [
16 | "encrypt",
17 | "wrapKey"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupOct-128-72.localhost:8443/keys/jsonBackupOct-128-72/730490a0df9b4ac78ed675902077a18f",
20 | "kty": "oct-HSM"
21 | },
22 | "managed": false,
23 | "tags": {},
24 | "vaultBaseUri": "https://keys-backup-jsonBackupOct-128-72.localhost:8443"
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/CertificateLifetimeActionSerializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.certificate.CertificateLifetimeActionActivity;
4 | import tools.jackson.core.JsonGenerator;
5 | import tools.jackson.databind.SerializationContext;
6 | import tools.jackson.databind.ValueSerializer;
7 |
8 | public class CertificateLifetimeActionSerializer
9 | extends ValueSerializer {
10 |
11 | @Override
12 | public void serialize(
13 | final CertificateLifetimeActionActivity value,
14 | final JsonGenerator generator,
15 | final SerializationContext provider) {
16 | generator.writeStartObject();
17 | generator.writeStringProperty("action_type", value.getValue());
18 | generator.writeEndObject();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupOct-192-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503106,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503106
10 | },
11 | "entityId": "jsonBackupOct-192-72",
12 | "entityVersion": "55ccab8f94b244ab97d82899340c22dd",
13 | "keyMaterial": {
14 | "k": "fp2J-nnMUBZVxCDFdKDxjDJX0F_BIM8P",
15 | "key_ops": [
16 | "encrypt",
17 | "wrapKey"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupOct-192-72.localhost:8443/keys/jsonBackupOct-192-72/55ccab8f94b244ab97d82899340c22dd",
20 | "kty": "oct-HSM"
21 | },
22 | "managed": false,
23 | "tags": {},
24 | "vaultBaseUri": "https://keys-backup-jsonBackupOct-192-72.localhost:8443"
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/HashUtil.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.HashAlgorithm;
4 |
5 | import java.security.MessageDigest;
6 | import java.security.NoSuchAlgorithmException;
7 |
8 | public final class HashUtil {
9 |
10 | private HashUtil() {
11 | }
12 |
13 | public static byte[] hash(final byte[] data, final HashAlgorithm algorithm) {
14 | try {
15 | return hash(data, algorithm.getAlgorithmName());
16 | } catch (final NoSuchAlgorithmException e) {
17 | throw new IllegalArgumentException(e);
18 | }
19 | }
20 |
21 | private static byte[] hash(final byte[] data, final String algorithm) throws NoSuchAlgorithmException {
22 | final var md = MessageDigest.getInstance(algorithm);
23 | md.update(data);
24 | return md.digest();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupOct-256-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503106,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503106
10 | },
11 | "entityId": "jsonBackupOct-256-72",
12 | "entityVersion": "19c6d13acb844fda8ccb14751252433a",
13 | "keyMaterial": {
14 | "k": "nmgrv95gVLVdVQ2xe-RpUf-Eog7y0lT22W3EoBU4-cc",
15 | "key_ops": [
16 | "encrypt",
17 | "wrapKey"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupOct-256-72.localhost:8443/keys/jsonBackupOct-256-72/19c6d13acb844fda8ccb14751252433a",
20 | "kty": "oct-HSM"
21 | },
22 | "managed": false,
23 | "tags": {},
24 | "vaultBaseUri": "https://keys-backup-jsonBackupOct-256-72.localhost:8443"
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/backup/KeyBackupListItem.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common.backup;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.BaseBackupListItem;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.KeyPropertiesModel;
6 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.request.JsonWebKeyImportRequest;
7 | import jakarta.validation.Valid;
8 | import jakarta.validation.constraints.NotNull;
9 | import lombok.Data;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.ToString;
12 |
13 | @Data
14 | @EqualsAndHashCode(callSuper = true)
15 | @ToString(callSuper = true)
16 | public class KeyBackupListItem
17 | extends BaseBackupListItem {
18 | @Valid
19 | @NotNull
20 | @JsonProperty("keyMaterial")
21 | private JsonWebKeyImportRequest keyMaterial;
22 | }
23 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/Base64ZipSecretDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.common.backup.SecretBackupList;
4 | import tools.jackson.databind.ObjectMapper;
5 |
6 | public class Base64ZipSecretDeserializer
7 | extends AbstractBase64ZipDeserializer {
8 |
9 | @SuppressWarnings("unused") //used from annotations
10 | public Base64ZipSecretDeserializer() {
11 | this(new Base64Deserializer(), new ObjectMapper());
12 | }
13 |
14 | protected Base64ZipSecretDeserializer(
15 | final Base64Deserializer base64Deserializer,
16 | final ObjectMapper objectMapper) {
17 | super(base64Deserializer, objectMapper);
18 | }
19 |
20 | @Override
21 | protected Class getType() {
22 | return SecretBackupList.class;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/vault/VaultService.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.vault;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.constants.RecoveryLevel;
4 |
5 | import java.net.URI;
6 | import java.util.List;
7 | import java.util.Set;
8 |
9 | public interface VaultService {
10 |
11 | VaultFake findByUri(URI uri);
12 |
13 | VaultFake findByUriIncludeDeleted(URI uri);
14 |
15 | VaultFake create(URI uri);
16 |
17 | VaultFake create(URI baseUri, RecoveryLevel recoveryLevel, Integer recoverableDays, Set aliases);
18 |
19 | List list();
20 |
21 | List listDeleted();
22 |
23 | boolean delete(URI uri);
24 |
25 | void recover(URI uri);
26 |
27 | boolean purge(URI uri);
28 |
29 | void timeShift(int offsetSeconds, boolean regenerateCertificates);
30 |
31 | VaultFake updateAlias(URI baseUri, URI add, URI remove);
32 | }
33 |
--------------------------------------------------------------------------------
/.lift.toml:
--------------------------------------------------------------------------------
1 | # Lift configuration
2 | # Reference https://help.sonatype.com/lift/configuration-reference
3 |
4 | # setup =
5 | # build = ENV= [target]
6 | build = "./gradlew build -x test -x dockerBuild -x dockerRun -x dockerStop"
7 |
8 | # importantRules =
9 | # ignoreRules =
10 | # ignoreFiles =
11 |
12 | ## tools =
13 | tools = ["infer", "findsecbugs"]
14 |
15 | # disableTools =
16 | disableTools = ["errorprone"]
17 |
18 | # customTools =
19 | # allow =
20 | # jdkVersion =
21 | jdkVersion = "17"
22 |
23 | # summaryComments = {
17 |
18 | @Valid
19 | @NotNull
20 | @Size(min = 1)
21 | @JsonProperty("versions")
22 | private List versions = List.of();
23 |
24 | public void setVersions(final List versions) {
25 | this.versions = List.copyOf(versions);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/EpochSecondsDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import tools.jackson.core.JsonParser;
4 | import tools.jackson.databind.DeserializationContext;
5 | import tools.jackson.databind.ValueDeserializer;
6 |
7 | import java.time.Instant;
8 | import java.time.OffsetDateTime;
9 | import java.time.ZoneOffset;
10 | import java.util.Optional;
11 |
12 | public class EpochSecondsDeserializer
13 | extends ValueDeserializer {
14 |
15 | @Override
16 | public OffsetDateTime deserialize(
17 | final JsonParser parser,
18 | final DeserializationContext context) {
19 | return Optional.ofNullable(parser.readValueAs(Long.class))
20 | .map(Instant::ofEpochSecond)
21 | .map((Instant instant) -> OffsetDateTime.ofInstant(instant, ZoneOffset.UTC))
22 | .orElse(null);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/Base64ZipCertificateDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.common.backup.CertificateBackupList;
4 | import tools.jackson.databind.ObjectMapper;
5 |
6 | public class Base64ZipCertificateDeserializer extends AbstractBase64ZipDeserializer {
7 |
8 | @SuppressWarnings("unused") //used from annotations
9 | public Base64ZipCertificateDeserializer() {
10 | this(new Base64Deserializer(), new ObjectMapper());
11 | }
12 |
13 | protected Base64ZipCertificateDeserializer(
14 | final Base64Deserializer base64Deserializer,
15 | final ObjectMapper objectMapper) {
16 | super(base64Deserializer, objectMapper);
17 | }
18 |
19 | @Override
20 | protected Class getType() {
21 | return CertificateBackupList.class;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/IssuerParameterModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.service.certificate.impl.CertAuthorityType;
6 | import lombok.Data;
7 |
8 | import java.util.Optional;
9 |
10 | @Data
11 | public class IssuerParameterModel {
12 |
13 | @JsonProperty("cert_transparency")
14 | private boolean certTransparency;
15 | @JsonProperty("cty")
16 | private String certType;
17 | @JsonProperty("name")
18 | private String issuer;
19 |
20 | @JsonCreator
21 | public IssuerParameterModel() {
22 | }
23 |
24 | public IssuerParameterModel(final CertAuthorityType issuer) {
25 | this();
26 | this.issuer = Optional.ofNullable(issuer).map(CertAuthorityType::getValue).orElse(null);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/KeyVaultItemListModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import lombok.Data;
6 | import lombok.NonNull;
7 | import org.springframework.lang.Nullable;
8 |
9 | import java.net.URI;
10 | import java.util.List;
11 | import java.util.Optional;
12 |
13 | @Data
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | public class KeyVaultItemListModel {
16 |
17 | @JsonProperty("nextLink")
18 | private String nextLink;
19 |
20 | @JsonProperty("value")
21 | private List value;
22 |
23 | public KeyVaultItemListModel(
24 | @NonNull final List value,
25 | @Nullable final URI nextLinkUri) {
26 | this.value = List.copyOf(value);
27 | this.nextLink = Optional.ofNullable(nextLinkUri).map(URI::toString).orElse(null);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/certs/ec521-ec-localhost.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MGkCAQAwEAYHKoZIzj0CAQYFK4EEACMEUjBQAgEBBEIBJ/Bcajc4nI1IyhE8A6ny
3 | JePp5s/K0LJydfNdlthqsvzIr1zQmjgfQCpCJgD6VHr6o5J1uQRnT5Cpi/swvQoX
4 | 8OmgBwYFK4EEACM=
5 | -----END PRIVATE KEY-----
6 | -----BEGIN CERTIFICATE-----
7 | MIIBzTCCASygAwIBAgIEKaADaTAMBggqhkjOPQQDBAUAMBcxFTATBgNVBAMTDGVj
8 | LmxvY2FsaG9zdDAeFw0yMjA5MTAxOTU1MzJaFw0yMzA5MTAxOTU1MzJaMBcxFTAT
9 | BgNVBAMTDGVjLmxvY2FsaG9zdDCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAUaq
10 | /pHrWi9EktVrW41A4oYXPLsV3e4yhqZvck1Txr6ElvAOIWVHinZ8vmrnfTGJ7YH/
11 | DpnLGwYC+V+W/CCk/s4KAA3fnWyu/kIlPxt5IXdJ6KLVhLzAxv+VY8IYb/W+cgIO
12 | trKfip6SbNKx6hG0jP+IDRweXNU0ZyvKMh5sSp/b8UVmoyEwHzAdBgNVHQ4EFgQU
13 | JEQMvw7eWMDjtnMv78XSs2VnVDkwDAYIKoZIzj0EAwQFAAOBjAAwgYgCQgGvTXL6
14 | ZsnnKCZKHTWjtZZf+gw9Osyh8+a6Lb5VzHu0UybDYolsOUQHfb0gjHdQj9wlct88
15 | EDyqjQEmrgEONtPnGwJCALwoLMw/OF5UVak9hvzYcOrOqE43gbidJ9wGbAOShIDC
16 | klY0quWX6jfgPaqDuU5mkfqTMMx66ALotBk1bK4hpF5l
17 | -----END CERTIFICATE-----
18 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_3/certificate/CertificateEntityToV73IssuancePolicyModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_3.certificate;
2 |
3 | import com.github.nagyesta.lowkeyvault.mapper.common.registry.CertificateConverterRegistry;
4 | import com.github.nagyesta.lowkeyvault.service.certificate.ReadOnlyKeyVaultCertificateEntity;
5 | import lombok.NonNull;
6 |
7 | public class CertificateEntityToV73IssuancePolicyModelConverter extends BaseCertificateEntityToV73PolicyModelConverter {
8 |
9 | private final CertificateConverterRegistry registry;
10 |
11 | public CertificateEntityToV73IssuancePolicyModelConverter(@NonNull final CertificateConverterRegistry registry) {
12 | super(ReadOnlyKeyVaultCertificateEntity::getIssuancePolicy);
13 | this.registry = registry;
14 | }
15 |
16 | @Override
17 | public void afterPropertiesSet() {
18 | registry.registerIssuancePolicyConverter(this);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/key/impl/EcKeyCreationInput.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.key.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyCurveName;
4 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyType;
5 | import lombok.EqualsAndHashCode;
6 | import lombok.Getter;
7 | import lombok.ToString;
8 | import org.springframework.lang.NonNull;
9 | import org.springframework.util.Assert;
10 |
11 | @Getter
12 | @EqualsAndHashCode(callSuper = true)
13 | @ToString(callSuper = true)
14 | public class EcKeyCreationInput
15 | extends KeyCreationInput {
16 |
17 | public EcKeyCreationInput(
18 | @NonNull final KeyType keyType,
19 | final KeyCurveName keyParameter) {
20 | super(keyType, keyParameter);
21 | Assert.isTrue(keyType.isEc(), "KeyType must be EC.");
22 | Assert.notNull(keyParameter, "KeyCurveName must not be null.");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/common/RecoveryAwareConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.common;
2 |
3 | import com.github.nagyesta.lowkeyvault.context.ApiVersionAware;
4 | import org.springframework.beans.factory.InitializingBean;
5 | import org.springframework.lang.NonNull;
6 | import org.springframework.lang.Nullable;
7 |
8 | import java.net.URI;
9 |
10 | /**
11 | * Converter interface supporting both active and deleted entities.
12 | *
13 | * @param The source type.
14 | * @param The active target type.
15 | * @param The deleted target type.
16 | */
17 | @SuppressWarnings("java:S119") //It is easier to ensure that the types are consistent this way
18 | public interface RecoveryAwareConverter
19 | extends ApiVersionAware, InitializingBean {
20 |
21 | @Nullable
22 | T convert(S source, @NonNull URI vaultUri);
23 |
24 | @NonNull
25 | DT convertDeleted(@NonNull S source, @NonNull URI vaultUri);
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/common/VersionedEntityMultiMap.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.common;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.EntityId;
4 | import lombok.NonNull;
5 |
6 | import java.util.function.Consumer;
7 | import java.util.function.UnaryOperator;
8 |
9 | @SuppressWarnings("java:S119") //It is easier to ensure that the types are consistent this way
10 | public interface VersionedEntityMultiMap, ME extends RE>
11 | extends ReadOnlyVersionedEntityMultiMap {
12 |
13 | ME getEntity(V entityId);
14 |
15 | void put(V entityId, ME entity);
16 |
17 | boolean isDeleted();
18 |
19 | void moveTo(K entityId, VersionedEntityMultiMap destination, UnaryOperator applyToAll);
20 |
21 | void purgeExpired();
22 |
23 | void purgeDeleted(K entityId);
24 |
25 | void forEachEntity(@NonNull Consumer entityConsumer);
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/X509CertificateModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.service.certificate.impl.KeyUsageEnum;
5 | import jakarta.validation.Valid;
6 | import jakarta.validation.constraints.NotBlank;
7 | import jakarta.validation.constraints.NotNull;
8 | import lombok.Data;
9 |
10 | import java.util.Set;
11 |
12 | @Data
13 | public class X509CertificateModel {
14 |
15 | @NotNull
16 | @NotBlank
17 | @JsonProperty("subject")
18 | private String subject;
19 | @JsonProperty("ekus")
20 | private Set extendedKeyUsage;
21 | @JsonProperty("key_usage")
22 | private Set keyUsage;
23 | @JsonProperty("validity_months")
24 | private Integer validityMonths;
25 | @JsonProperty("sans")
26 | @Valid
27 | private SubjectAlternativeNames subjectAlternativeNames;
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/RandomBytesResponse.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64Deserializer;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64Serializer;
7 | import lombok.Data;
8 | import tools.jackson.databind.annotation.JsonDeserialize;
9 | import tools.jackson.databind.annotation.JsonSerialize;
10 |
11 | @Data
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | public class RandomBytesResponse {
14 |
15 | @JsonProperty("value")
16 | @JsonSerialize(using = Base64Serializer.class)
17 | @JsonDeserialize(using = Base64Deserializer.class)
18 | private byte[] value;
19 |
20 | public RandomBytesResponse() {
21 | }
22 |
23 | public RandomBytesResponse(final byte[] value) {
24 | this();
25 | this.value = value;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/key/impl/RsaKeyCreationInput.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.key.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyType;
4 | import lombok.EqualsAndHashCode;
5 | import lombok.Getter;
6 | import lombok.ToString;
7 | import org.springframework.lang.NonNull;
8 | import org.springframework.util.Assert;
9 |
10 | import java.math.BigInteger;
11 |
12 | @Getter
13 | @EqualsAndHashCode(callSuper = true)
14 | @ToString(callSuper = true)
15 | public class RsaKeyCreationInput
16 | extends KeyCreationInput {
17 |
18 | private final BigInteger publicExponent;
19 |
20 | public RsaKeyCreationInput(
21 | @NonNull final KeyType keyType,
22 | final Integer keyParameter,
23 | final BigInteger publicExponent) {
24 | super(keyType, keyParameter);
25 | Assert.isTrue(keyType.isRsa(), "KeyType must be RSA.");
26 | this.publicExponent = publicExponent;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/KeyVaultCertificateItemModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64Deserializer;
5 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64Serializer;
6 | import lombok.Data;
7 | import tools.jackson.databind.annotation.JsonDeserialize;
8 | import tools.jackson.databind.annotation.JsonSerialize;
9 |
10 | import java.util.Map;
11 |
12 | @Data
13 | public class KeyVaultCertificateItemModel {
14 |
15 | @JsonProperty("id")
16 | private String certificateId;
17 | @JsonSerialize(using = Base64Serializer.class)
18 | @JsonDeserialize(using = Base64Deserializer.class)
19 | @JsonProperty("x5t")
20 | private byte[] thumbprint;
21 | @JsonProperty("attributes")
22 | private CertificatePropertiesModel attributes;
23 | @JsonProperty("tags")
24 | private Map tags;
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/IssuerParameterModelTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static com.github.nagyesta.lowkeyvault.service.certificate.impl.CertAuthorityType.SELF_SIGNED;
7 |
8 | class IssuerParameterModelTest {
9 |
10 | @Test
11 | void testControllerShouldSetIssuerWhenCalledWithCertificateAuthority() {
12 | //given
13 |
14 | //when
15 | final var actual = new IssuerParameterModel(SELF_SIGNED);
16 |
17 | //then
18 | Assertions.assertEquals(SELF_SIGNED.getValue(), actual.getIssuer());
19 | }
20 |
21 | @Test
22 | void testControllerShouldNotSetIssuerWhenCalledWithoutCertificateAuthority() {
23 | //given
24 |
25 | //when
26 | final var actual = new IssuerParameterModel(null);
27 |
28 | //then
29 | Assertions.assertNull(actual.getIssuer());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/key/id/KeyEntityId.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.key.id;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.BaseEntityId;
4 | import com.github.nagyesta.lowkeyvault.service.EntityId;
5 | import lombok.NonNull;
6 |
7 | import java.net.URI;
8 |
9 | public class KeyEntityId
10 | extends BaseEntityId implements EntityId {
11 |
12 | private static final String URI_ROTATIONPOLICY_FORMAT = "%s/%s/%s/rotationpolicy";
13 |
14 | public KeyEntityId(final URI vault, final String id) {
15 | this(vault, id, null);
16 | }
17 |
18 | public KeyEntityId(
19 | @NonNull final URI vault,
20 | @NonNull final String id,
21 | final String version) {
22 | super(vault, id, version, "key");
23 | }
24 |
25 | public URI asRotationPolicyUri(@NonNull final URI vaultUri) {
26 | return URI.create(URI_ROTATIONPOLICY_FORMAT
27 | .formatted(vaultUri, entityPathSegment(), id()));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/main/java/com/github/nagyesta/lowkeyvault/http/management/EpochSecondsDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http.management;
2 |
3 | import com.fasterxml.jackson.core.JsonParser;
4 | import com.fasterxml.jackson.databind.DeserializationContext;
5 | import com.fasterxml.jackson.databind.JsonDeserializer;
6 |
7 | import java.io.IOException;
8 | import java.time.Instant;
9 | import java.time.OffsetDateTime;
10 | import java.time.ZoneOffset;
11 | import java.util.Optional;
12 |
13 | public class EpochSecondsDeserializer
14 | extends JsonDeserializer {
15 |
16 | @Override
17 | public OffsetDateTime deserialize(
18 | final JsonParser parser,
19 | final DeserializationContext context) throws IOException {
20 | return Optional.ofNullable(parser.readValueAs(Long.class))
21 | .map(Instant::ofEpochSecond)
22 | .map((Instant instant) -> OffsetDateTime.ofInstant(instant, ZoneOffset.UTC))
23 | .orElse(null);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/EpochSecondsSerializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import tools.jackson.core.JsonGenerator;
4 | import tools.jackson.databind.SerializationContext;
5 | import tools.jackson.databind.ValueSerializer;
6 |
7 | import java.time.OffsetDateTime;
8 | import java.util.Optional;
9 |
10 | public class EpochSecondsSerializer
11 | extends ValueSerializer {
12 |
13 | @Override
14 | public void serialize(
15 | final OffsetDateTime value,
16 | final JsonGenerator generator,
17 | final SerializationContext provider) {
18 | final var optional = Optional.ofNullable(value);
19 | final var optionalEpochSeconds = optional
20 | .map(OffsetDateTime::toEpochSecond);
21 | if (optionalEpochSeconds.isPresent()) {
22 | generator.writeNumber(optionalEpochSeconds.get());
23 | } else {
24 | generator.writeNull();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/context/ApiVersionAware.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.context;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.common.ApiConstants;
4 |
5 | import java.util.Collections;
6 | import java.util.Set;
7 | import java.util.SortedSet;
8 | import java.util.TreeSet;
9 |
10 | public interface ApiVersionAware {
11 |
12 | /**
13 | * Supported API version collection containing all 7.3+ versions.
14 | */
15 | SortedSet V7_3_AND_LATER = Collections.unmodifiableSortedSet(
16 | new TreeSet<>(Set.of(ApiConstants.V_7_3, ApiConstants.V_7_4, ApiConstants.V_7_5, ApiConstants.V_7_6)));
17 | /**
18 | * Supported API version collection containing all versions (7.2, 7.3, 7.4, 7.5 and 7.6).
19 | */
20 | SortedSet ALL_VERSIONS = Collections.unmodifiableSortedSet(
21 | new TreeSet<>(Set.of(ApiConstants.V_7_2, ApiConstants.V_7_3, ApiConstants.V_7_4, ApiConstants.V_7_5, ApiConstants.V_7_6)));
22 |
23 | SortedSet supportedVersions();
24 | }
25 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_3/certificate/CertificateEntityToV73PolicyModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_3.certificate;
2 |
3 | import com.github.nagyesta.lowkeyvault.mapper.common.registry.CertificateConverterRegistry;
4 | import com.github.nagyesta.lowkeyvault.service.certificate.ReadOnlyKeyVaultCertificateEntity;
5 | import lombok.NonNull;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 |
8 | public class CertificateEntityToV73PolicyModelConverter extends BaseCertificateEntityToV73PolicyModelConverter {
9 |
10 | private final CertificateConverterRegistry registry;
11 |
12 | @Autowired
13 | public CertificateEntityToV73PolicyModelConverter(@NonNull final CertificateConverterRegistry registry) {
14 | super(ReadOnlyKeyVaultCertificateEntity::getOriginalCertificatePolicy);
15 | this.registry = registry;
16 | }
17 |
18 | @Override
19 | public void afterPropertiesSet() {
20 | registry.registerPolicyConverter(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/common/BaseBackupModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.common;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.github.nagyesta.lowkeyvault.model.v7_2.BasePropertiesModel;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.BackupListContainer;
6 | import jakarta.validation.Valid;
7 | import jakarta.validation.constraints.NotNull;
8 | import lombok.Data;
9 |
10 | /**
11 | * Base class of backup models.
12 | *
13 | * @param The type of the properties model.
14 | * @param The type of the backup list items.
15 | * @param The wrapper type of the backup list.
16 | */
17 | @Data
18 | @JsonInclude(JsonInclude.Include.NON_NULL)
19 | @SuppressWarnings("java:S119") //It is easier to ensure that the types are consistent this way
20 | public class BaseBackupModel, BL extends BackupListContainer> {
21 |
22 | @Valid
23 | @NotNull
24 | private BL value;
25 | }
26 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupEc-256-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503879,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503879
10 | },
11 | "entityId": "jsonBackupEc-256-72",
12 | "entityVersion": "f16a91376c13478996195a0c2cee39cb",
13 | "keyMaterial": {
14 | "crv": "P-256",
15 | "d": "IvdJQWa59MJflXPF25Cc4UlOREHZVL5_6sD27nyz1J8",
16 | "key_ops": [
17 | "sign"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupEc-256-72.localhost:8443/keys/jsonBackupEc-256-72/f16a91376c13478996195a0c2cee39cb",
20 | "kty": "EC",
21 | "x": "XBlNkVS33eZqrVgbpeoNerx5XKMixFxFrYl5FJKQ5vQ",
22 | "y": "KKoHw5q3QM1lehkqggvNViaX1KBM2ePvmXE2IQbWiLE"
23 | },
24 | "managed": false,
25 | "tags": {},
26 | "vaultBaseUri": "https://keys-backup-jsonBackupEc-256-72.localhost:8443"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/constants/LifetimeActionType.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key.constants;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonValue;
5 |
6 | import java.util.Arrays;
7 |
8 | public enum LifetimeActionType {
9 | /**
10 | * Notification triggers.
11 | */
12 | NOTIFY("notify"),
13 | /**
14 | * Automatic rotation trigger.
15 | */
16 | ROTATE("rotate");
17 |
18 | private final String value;
19 |
20 | LifetimeActionType(final String value) {
21 | this.value = value;
22 | }
23 |
24 | @JsonCreator
25 | public static LifetimeActionType forValue(final String name) {
26 | return Arrays.stream(values())
27 | .filter(actionType -> actionType.getValue().equals(name))
28 | .findFirst()
29 | .orElse(null);
30 | }
31 |
32 | @JsonValue
33 | public String getValue() {
34 | return value;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupEc-256k-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503879,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503879
10 | },
11 | "entityId": "jsonBackupEc-256k-72",
12 | "entityVersion": "5425a5872c1f4a9fa96db8f40e6c5d07",
13 | "keyMaterial": {
14 | "crv": "P-256K",
15 | "d": "AONvayGgRSTtrfA6lkCRC-qYccs_pQh35ZSXssCulkrJ",
16 | "key_ops": [
17 | "sign"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupEc-256k-72.localhost:8443/keys/jsonBackupEc-256k-72/5425a5872c1f4a9fa96db8f40e6c5d07",
20 | "kty": "EC",
21 | "x": "5IeF3ibB0c0QP5J2FOcxqxRi4TAs9aktvys3H41X04c",
22 | "y": "DJivtzkKcvFCNe9ZmzCzflbG_CSQrbuDBauJDneZ6Xc"
23 | },
24 | "managed": false,
25 | "tags": {},
26 | "vaultBaseUri": "https://keys-backup-jsonBackupEc-256k-72.localhost:8443"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/main/java/com/github/nagyesta/lowkeyvault/http/management/EpochSecondsSerializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http.management;
2 |
3 | import com.fasterxml.jackson.core.JsonGenerator;
4 | import com.fasterxml.jackson.databind.JsonSerializer;
5 | import com.fasterxml.jackson.databind.SerializerProvider;
6 |
7 | import java.io.IOException;
8 | import java.time.OffsetDateTime;
9 | import java.util.Optional;
10 |
11 | public class EpochSecondsSerializer
12 | extends JsonSerializer {
13 |
14 | @Override
15 | public void serialize(
16 | final OffsetDateTime value,
17 | final JsonGenerator generator,
18 | final SerializerProvider provider) throws IOException {
19 | final var optionalEpochSeconds = Optional.ofNullable(value)
20 | .map(OffsetDateTime::toEpochSecond);
21 | if (optionalEpochSeconds.isPresent()) {
22 | generator.writeNumber(optionalEpochSeconds.get());
23 | } else {
24 | generator.writeNull();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/KeyLifetimeActionTypeModelTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.constants.LifetimeActionType;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | class KeyLifetimeActionTypeModelTest {
8 |
9 | @SuppressWarnings("ConstantConditions")
10 | @Test
11 | void testConstructorShouldThrowExceptionWhenCalledWithNull() {
12 | //given
13 |
14 | //when
15 | Assertions.assertThrows(IllegalArgumentException.class, () -> new KeyLifetimeActionTypeModel(null));
16 |
17 | //then + exception
18 | }
19 |
20 | @Test
21 | void testConstructorShouldSetActionTypeWhenCalledWithValidValue() {
22 | //given
23 | final var expected = LifetimeActionType.NOTIFY;
24 |
25 | //when
26 | final var actual = new KeyLifetimeActionTypeModel(expected);
27 |
28 | //then
29 | Assertions.assertEquals(expected, actual.getType());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Something didn't go as expected? Please report a bug to help us improve!
4 | title: Bug report
5 | labels: bug
6 | assignees: ""
7 | ---
8 |
9 | #### Describe the bug
10 |
11 | A clear and concise description of what the bug is.
12 |
13 | #### To reproduce
14 |
15 | Steps to reproduce the behavior:
16 |
17 | 1. Use the app
18 | 2. Do these steps
19 |
20 | #### Expected behavior
21 |
22 | A clear and concise description of what you expected to happen.
23 |
24 | #### Actual behavior
25 |
26 | What happened in your case? e.g. At step 2 there is an error with this message...
27 |
28 | #### The command you used
29 |
30 | If applicable, add screenshots to help explain your problem.
31 |
32 | #### A minimal project that can be used to reproduce the issue
33 |
34 | If applicable. Please do NOT share sensitive information.
35 |
36 | #### Environment
37 |
38 | - OS: [e.g. Windows/Unix]
39 | - Version: [e.g. 1.0.0]
40 | - Java version [e.g. 11.0.2 Open JDK]
41 |
42 | #### Additional context
43 |
44 | Add any other context about the problem here.
45 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/backup/CertificateBackupList.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common.backup;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.BackupListContainer;
5 | import jakarta.validation.Valid;
6 | import jakarta.validation.constraints.NotNull;
7 | import jakarta.validation.constraints.Size;
8 | import lombok.EqualsAndHashCode;
9 |
10 | import java.util.List;
11 |
12 | @EqualsAndHashCode
13 | public class CertificateBackupList
14 | implements BackupListContainer {
15 |
16 | @Valid
17 | @NotNull
18 | @Size(min = 1)
19 | @JsonProperty("versions")
20 | private List versions = List.of();
21 |
22 | @Override
23 | public List getVersions() {
24 | return versions;
25 | }
26 |
27 | @Override
28 | public void setVersions(final List versions) {
29 | this.versions = List.copyOf(versions);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/certificate/CertificateLifetimeActionActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.certificate;
2 |
3 | import lombok.Getter;
4 | import lombok.NonNull;
5 |
6 | import java.util.Arrays;
7 |
8 | @Getter
9 | public enum CertificateLifetimeActionActivity {
10 | /**
11 | * Noop, simulates email notification actions.
12 | */
13 | EMAIL_CONTACTS("EmailContacts"),
14 | /**
15 | * Performs automatic renewal of the certificate.
16 | */
17 | AUTO_RENEW("AutoRenew");
18 |
19 | private final String value;
20 |
21 | CertificateLifetimeActionActivity(final String value) {
22 | this.value = value;
23 | }
24 |
25 | public static CertificateLifetimeActionActivity byValue(@NonNull final String value) {
26 | return Arrays.stream(CertificateLifetimeActionActivity.values())
27 | .filter(v -> v.value.equals(value))
28 | .findFirst()
29 | .orElseThrow(() -> new IllegalArgumentException("Unknown lifetime action activity: " + value));
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/com/github/nagyesta/lowkeyvault/keys/RandomData.feature:
--------------------------------------------------------------------------------
1 | Feature: Random data
2 |
3 | @RandomData
4 | Scenario Outline: RANDOM_DATA_01 The vault is used for getting random bytes
5 | Given key API version is used
6 | And a key client is created with the vault named default
7 | When the vault is called for bytes of random data
8 | Then the length of the random data is bytes
9 |
10 | Examples:
11 | | api | count |
12 | | 7.3 | 1 |
13 | | 7.3 | 2 |
14 | | 7.3 | 3 |
15 | | 7.3 | 5 |
16 | | 7.3 | 10 |
17 | | 7.3 | 32 |
18 | | 7.3 | 63 |
19 | | 7.3 | 64 |
20 | | 7.3 | 128 |
21 | | 7.3 | 1024 |
22 | | 7.3 | 2048 |
23 | | 7.3 | 15000 |
24 | | 7.3 | 24000 |
25 | | 7.4 | 1 |
26 | | 7.4 | 42 |
27 | | 7.5 | 1 |
28 | | 7.5 | 42 |
29 | | 7.6 | 1 |
30 | | 7.6 | 42 |
31 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupEc-384-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503879,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503879
10 | },
11 | "entityId": "jsonBackupEc-384-72",
12 | "entityVersion": "7f4c0a2ef5454e07a533e597434984a8",
13 | "keyMaterial": {
14 | "crv": "P-384",
15 | "d": "bd2taaXwxvA_DRUZ1wMT28l8TnaMDz1mn2Z2x_pJT_nkZ11BNS1FFxJvjYHIvoU4",
16 | "key_ops": [
17 | "sign"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupEc-384-72.localhost:8443/keys/jsonBackupEc-384-72/7f4c0a2ef5454e07a533e597434984a8",
20 | "kty": "EC",
21 | "x": "KzD2vTm-aSjXN_RFlY7P78R6hpfdJcSHTC9WM7QXmf0VJro3cXdFOZk6vrx5WDjE",
22 | "y": "pjLyFfCNzQ7yZUFc6iVS8eSWoRXY84sg3pzcSlkgn5LPYf9Vx7QSgAXfbRtmHGt_"
23 | },
24 | "managed": false,
25 | "tags": {},
26 | "vaultBaseUri": "https://keys-backup-jsonBackupEc-384-72.localhost:8443"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/common/BaseVaultFake.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.common;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.EntityId;
4 |
5 | import java.time.OffsetDateTime;
6 | import java.util.Map;
7 |
8 | /**
9 | * The base interface of the vault fakes.
10 | *
11 | * @param The type of the key (not versioned).
12 | * @param The versioned key type.
13 | * @param The entity type.
14 | */
15 | public interface BaseVaultFake>
16 | extends TimeAware {
17 |
18 | ReadOnlyVersionedEntityMultiMap getEntities();
19 |
20 | ReadOnlyVersionedEntityMultiMap getDeletedEntities();
21 |
22 | void clearTags(V entityId);
23 |
24 | void addTags(V entityId, Map tags);
25 |
26 | void setEnabled(V entityId, boolean enabled);
27 |
28 | void setExpiry(V entityId, OffsetDateTime notBefore, OffsetDateTime expiry);
29 |
30 | void delete(K entityId);
31 |
32 | void recover(K entityId);
33 |
34 | void purge(K entityId);
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/resources/cert/invalid-ec.pem:
--------------------------------------------------------------------------------
1 | Bag Attributes
2 | friendlyName: d2590dcf-8ec9-4bef-8c2d-8e51a43b29b6
3 | localKeyID: 54 69 6D 65 20 31 36 36 33 30 31 34 35 33 34 36 38 30
4 | Key Attributes:
5 | -----BEGIN PRIVATE KEY-----
6 | MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCAFlIRPFr7jjJA+9DAf
7 | pWb/gTypdclusJCFTTBK0qc8Nw==
8 | -----END PRIVATE KEY-----
9 | Bag Attributes
10 | friendlyName: d2590dcf-8ec9-4bef-8c2d-8e51a43b29b6
11 | localKeyID: 54 69 6D 65 20 31 36 36 33 30 31 34 35 33 34 36 38 30
12 | subject=CN = ec.localhost
13 |
14 | issuer=CN = ec.localhost
15 |
16 | -----BEGIN CERTIFICATE-----
17 | MIIBRDCB6aADAgECAgR3UZEbMAwGCCqGSM49BAMCBQAwFzEVMBMGA1UEAxMMZWMu
18 | bG9jYWxob3N0MB4XDTIyMDkxMDE5MDA1NVoXDTIzMDkxMDE5MDA1NVowFzEVMBMG
19 | A1UEAxMMZWMubG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9QeN
20 | Y5gGwMQnCSUrFfJ1CQp8ngrTJn9ZzTusUY8Gh5JWennjFdzLIqJ4yhpSzGAl+/jn
21 | Gv3n+fBjt7mUZu2I76MhMB8wHQYDVR0OBBYEFA2YDS/W2/Dv5qJrmtbE7w+HUtL0
22 | MAwGCCqGSM49BAMCBQADSAAwRQIgMQAYrmTDkcxQgS33oHbw+H/7YEO43ZDqSOTr
23 | tn7PQa8CIQCf8JCfvoC0W67JsBRFPDNJEKBuNHVMOWuKjwrXaqynuQ==
24 | -----END CERTIFICATE-----
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | build/
3 | !gradle/wrapper/gradle-wrapper.jar
4 | !**/src/main/**
5 | !**/src/test/**
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea/**
18 | !.idea/icon.png
19 | !.idea/codeStyles
20 | !.idea/codeStyles/**
21 | !.idea/inspectionProfiles
22 | !.idea/inspectionProfiles/**
23 | *.iws
24 | *.iml
25 | *.ipr
26 | out/
27 |
28 | ### NetBeans ###
29 | /nbproject/private/
30 | /nbbuild/
31 | /dist/
32 | /nbdist/
33 | /.nb-gradle/
34 |
35 | ### VS Code ###
36 | .vscode/
37 |
38 | ## For subprojects
39 | */.gradle
40 | */build/
41 | !*/gradle/wrapper/gradle-wrapper.jar
42 | !*/**/src/main/**
43 | !*/**/src/test/**
44 |
45 | ### STS ###
46 | */.apt_generated
47 | */.classpath
48 | */.factorypath
49 | */.project
50 | */.settings
51 | */.springBeans
52 | */.sts4-cache
53 |
54 | ### IntelliJ IDEA ###
55 | */.idea
56 | */*.iws
57 | */*.iml
58 | */*.ipr
59 | */out/
60 |
61 | ### NetBeans ###
62 | /*/nbproject/private/
63 | /*/nbbuild/
64 | /*/dist/
65 | /*/nbdist/
66 | /*/.nb-gradle/
67 |
68 | ### VS Code ###
69 | */.vscode/
70 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/certificate/id/CertificateEntityId.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.certificate.id;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.BaseEntityId;
4 | import com.github.nagyesta.lowkeyvault.service.EntityId;
5 | import lombok.NonNull;
6 |
7 | import java.net.URI;
8 |
9 | public class CertificateEntityId
10 | extends BaseEntityId implements EntityId {
11 |
12 | public CertificateEntityId(
13 | final URI vault,
14 | final String id) {
15 | this(vault, id, null);
16 | }
17 |
18 | public CertificateEntityId(
19 | @NonNull final URI vault,
20 | @NonNull final String id,
21 | final String version) {
22 | super(vault, id, version, "certificate");
23 | }
24 |
25 | public URI asPolicyUri(@NonNull final URI vaultUri) {
26 | return URI.create(asUri(vaultUri).toString() + "/policy");
27 | }
28 |
29 | public URI asPendingOperationUri(@NonNull final URI vaultUri) {
30 | return URI.create(asUriNoVersion(vaultUri).toString() + "/pending");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_2/key/KeyEntityToV72KeyVersionItemModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_2.key;
2 |
3 | import com.github.nagyesta.lowkeyvault.mapper.common.registry.KeyConverterRegistry;
4 | import com.github.nagyesta.lowkeyvault.service.key.ReadOnlyKeyVaultKeyEntity;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.lang.NonNull;
7 |
8 | import java.net.URI;
9 |
10 | public class KeyEntityToV72KeyVersionItemModelConverter extends KeyEntityToV72KeyItemModelConverter {
11 |
12 | @Autowired
13 | public KeyEntityToV72KeyVersionItemModelConverter(@NonNull final KeyConverterRegistry registry) {
14 | super(registry);
15 | }
16 |
17 | @Override
18 | protected void register(final KeyConverterRegistry registry) {
19 | registry.registerVersionedItemConverter(this);
20 | }
21 |
22 | @Override
23 | protected String convertKeyId(
24 | final ReadOnlyKeyVaultKeyEntity source,
25 | final URI vaultUri) {
26 | return source.getId().asUri(vaultUri).toString();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-present Istvan Zoltan Nagy (a.k.a Esta Nagy)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/common/BasePropertiesModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.common;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.BasePropertiesModel;
4 | import com.github.nagyesta.lowkeyvault.service.EntityId;
5 | import com.github.nagyesta.lowkeyvault.service.common.BaseVaultEntity;
6 |
7 | public abstract class BasePropertiesModelConverter, M extends BasePropertiesModel>
9 | implements AliasAwareConverter {
10 |
11 | protected M mapCommonFields(
12 | final E entity,
13 | final M attributes) {
14 | attributes.setCreatedOn(entity.getCreated());
15 | attributes.setUpdatedOn(entity.getUpdated());
16 | attributes.setEnabled(entity.isEnabled());
17 | entity.getExpiry().ifPresent(attributes::setExpiresOn);
18 | entity.getNotBefore().ifPresent(attributes::setNotBefore);
19 | attributes.setRecoveryLevel(entity.getRecoveryLevel());
20 | attributes.setRecoverableDays(entity.getRecoverableDays());
21 | return attributes;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/KeyLifetimeActionTypeModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key;
2 |
3 | import com.fasterxml.jackson.annotation.JsonCreator;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 | import com.fasterxml.jackson.annotation.JsonProperty;
6 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.constants.LifetimeActionType;
7 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.validator.Restore;
8 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.validator.Update;
9 | import jakarta.validation.constraints.NotNull;
10 | import lombok.Data;
11 | import lombok.NonNull;
12 |
13 | @Data
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | public class KeyLifetimeActionTypeModel {
16 |
17 | @NotNull(groups = {Restore.class, Update.class})
18 | @JsonProperty("type")
19 | private LifetimeActionType type;
20 |
21 | @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
22 | public KeyLifetimeActionTypeModel() {
23 | }
24 |
25 | public KeyLifetimeActionTypeModel(@NonNull final LifetimeActionType type) {
26 | this();
27 | this.type = type;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/management/VaultBackupModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.management;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.common.backup.CertificateBackupList;
6 | import com.github.nagyesta.lowkeyvault.model.common.backup.KeyBackupList;
7 | import com.github.nagyesta.lowkeyvault.model.common.backup.SecretBackupList;
8 | import jakarta.validation.Valid;
9 | import jakarta.validation.constraints.NotNull;
10 | import lombok.Data;
11 |
12 | import java.util.Map;
13 |
14 | @Data
15 | @JsonInclude(JsonInclude.Include.NON_NULL)
16 | public class VaultBackupModel {
17 |
18 | @Valid
19 | @NotNull
20 | @JsonProperty("attributes")
21 | private VaultModel attributes;
22 | @Valid
23 | @JsonProperty("keys")
24 | private Map keys;
25 | @Valid
26 | @JsonProperty("secrets")
27 | private Map secrets;
28 | @Valid
29 | @JsonProperty("certificates")
30 | private Map certificates;
31 | }
32 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/CertificateKeyModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyCurveName;
6 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyType;
7 | import jakarta.validation.constraints.Max;
8 | import jakarta.validation.constraints.Min;
9 | import jakarta.validation.constraints.NotNull;
10 | import lombok.Data;
11 |
12 | @Data
13 | public class CertificateKeyModel {
14 |
15 | @JsonProperty("exportable")
16 | private boolean exportable;
17 | @JsonProperty("crv")
18 | @JsonInclude(JsonInclude.Include.NON_NULL)
19 | private KeyCurveName keyCurveName;
20 | @NotNull
21 | @JsonProperty("kty")
22 | private KeyType keyType;
23 | @Min(1024)
24 | @Max(4096)
25 | @JsonInclude(JsonInclude.Include.NON_NULL)
26 | @JsonProperty("key_size")
27 | private Integer keySize = null;
28 | @JsonProperty("reuse_key")
29 | private boolean reuseKey;
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/BasePropertiesUpdateModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsDeserializer;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsSerializer;
7 | import lombok.Data;
8 | import tools.jackson.databind.annotation.JsonDeserialize;
9 | import tools.jackson.databind.annotation.JsonSerialize;
10 |
11 | import java.time.OffsetDateTime;
12 |
13 | @Data
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | public class BasePropertiesUpdateModel {
16 |
17 | @JsonProperty("enabled")
18 | private Boolean enabled;
19 | @JsonProperty("exp")
20 | @JsonSerialize(using = EpochSecondsSerializer.class)
21 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
22 | private OffsetDateTime expiresOn;
23 | @JsonProperty("nbf")
24 | @JsonSerialize(using = EpochSecondsSerializer.class)
25 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
26 | private OffsetDateTime notBefore;
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/validator/ExpiryPeriodValidator.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key.validator;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.key.constants.LifetimeActionTriggerType;
4 | import com.github.nagyesta.lowkeyvault.service.key.util.PeriodUtil;
5 | import jakarta.validation.ConstraintValidator;
6 | import jakarta.validation.ConstraintValidatorContext;
7 |
8 | import java.time.Period;
9 | import java.util.Optional;
10 |
11 | public class ExpiryPeriodValidator
12 | implements ConstraintValidator {
13 |
14 | @Override
15 | public void initialize(final ExpiryPeriod constraintAnnotation) {
16 | ConstraintValidator.super.initialize(constraintAnnotation);
17 | }
18 |
19 | @Override
20 | public boolean isValid(
21 | final Period value,
22 | final ConstraintValidatorContext context) {
23 | return Optional.ofNullable(value)
24 | .map(PeriodUtil::asDays)
25 | .map(totalDays -> totalDays >= LifetimeActionTriggerType.MINIMUM_EXPIRY_PERIOD_IN_DAYS)
26 | .orElse(true);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/json/backups/jsonBackupEc-521-72.json:
--------------------------------------------------------------------------------
1 | {
2 | "versions": [
3 | {
4 | "attributes": {
5 | "created": 1649503879,
6 | "enabled": true,
7 | "recoverableDays": 90,
8 | "recoveryLevel": "Recoverable+Purgeable",
9 | "updated": 1649503879
10 | },
11 | "entityId": "jsonBackupEc-521-72",
12 | "entityVersion": "9301e31d18a540e08c68ad5230e60e21",
13 | "keyMaterial": {
14 | "crv": "P-521",
15 | "d": "AWNmGqYqot0Zq_6uqnqv2lkA40ke1uTJhehp692dS_r2C7oPmJ0qcPgc31jOOFzc-v69chbMawkR-wyKXFf2O4mh",
16 | "key_ops": [
17 | "sign"
18 | ],
19 | "kid": "https://keys-backup-jsonBackupEc-521-72.localhost:8443/keys/jsonBackupEc-521-72/9301e31d18a540e08c68ad5230e60e21",
20 | "kty": "EC",
21 | "x": "AbDYVOxj0e-tUTgqybst45IXon0axFo_sXlHyJQgYvFDxMNrxa5d4rV7X5H487zh3p_aR_dnVEnbWz9od42mlldE",
22 | "y": "ANk3zxFnwHSgsJr2AZvCHe06Zv7LOQdifHIVaZqx72NOf87DQQoEEMXNp3lTMYANkAqlerz80kjGpoBAe1ZyEtsH"
23 | },
24 | "managed": false,
25 | "tags": {},
26 | "vaultBaseUri": "https://keys-backup-jsonBackupEc-521-72.localhost:8443"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/.github/workflows/gradle-oss-index-scan.yml:
--------------------------------------------------------------------------------
1 | name: "OSS-Index-Scan"
2 |
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | # * is a special character in YAML, so we have to quote this string
7 | - cron: "0 7 * * 2,4,6"
8 |
9 | permissions: read-all
10 |
11 | jobs:
12 | analyze:
13 | name: Analyze
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - name: Checkout repository
18 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
19 | - name: Validate Gradle wrapper
20 | uses: gradle/actions/wrapper-validation@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
21 | - name: Set up JDK 25
22 | uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0
23 | with:
24 | distribution: temurin
25 | java-version: 25
26 | - name: Setup Gradle
27 | uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # v5.0.0
28 | with:
29 | cache-disabled: true
30 | - name: Check dependencies with Gradle
31 | run: ./gradlew ossIndexAudit -PossIndexUsername=${{ secrets.OSS_INDEX_USER }} -PossIndexPassword=${{ secrets.OSS_INDEX_PASSWORD }} --info
32 |
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/request/KeySignParameters.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key.request;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 | import com.fasterxml.jackson.annotation.JsonProperty;
6 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.SignatureAlgorithm;
7 | import jakarta.validation.constraints.NotBlank;
8 | import jakarta.validation.constraints.NotNull;
9 | import lombok.Data;
10 |
11 | import java.util.Base64;
12 | import java.util.Optional;
13 |
14 | @Data
15 | @JsonInclude(JsonInclude.Include.NON_NULL)
16 | public class KeySignParameters {
17 |
18 | private static final Base64.Decoder DECODER = Base64.getUrlDecoder();
19 |
20 | @NotNull
21 | @JsonProperty("alg")
22 | private SignatureAlgorithm algorithm;
23 |
24 | @NotNull
25 | @NotBlank
26 | @JsonProperty("value")
27 | private String value;
28 |
29 | @JsonIgnore
30 | public byte[] getValueAsBase64DecodedBytes() {
31 | return Optional.ofNullable(value)
32 | .map(DECODER::decode)
33 | .orElse(null);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_2/secret/SecretEntityToV72SecretVersionItemModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_2.secret;
2 |
3 | import com.github.nagyesta.lowkeyvault.mapper.common.registry.SecretConverterRegistry;
4 | import com.github.nagyesta.lowkeyvault.service.secret.ReadOnlyKeyVaultSecretEntity;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.lang.NonNull;
7 |
8 | import java.net.URI;
9 |
10 | public class SecretEntityToV72SecretVersionItemModelConverter
11 | extends SecretEntityToV72SecretItemModelConverter {
12 |
13 | @Autowired
14 | public SecretEntityToV72SecretVersionItemModelConverter(@NonNull final SecretConverterRegistry registry) {
15 | super(registry);
16 | }
17 |
18 | @Override
19 | protected void register(final SecretConverterRegistry registry) {
20 | registry.registerVersionedItemConverter(this);
21 | }
22 |
23 | @Override
24 | protected String convertSecretId(
25 | final ReadOnlyKeyVaultSecretEntity source,
26 | final URI vaultUri) {
27 | return source.getId().asUri(vaultUri).toString();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/CertificateLifetimeActionModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.CertificateLifetimeActionDeserializer;
5 | import com.github.nagyesta.lowkeyvault.model.json.util.CertificateLifetimeActionSerializer;
6 | import com.github.nagyesta.lowkeyvault.service.certificate.CertificateLifetimeActionActivity;
7 | import jakarta.validation.Valid;
8 | import jakarta.validation.constraints.NotNull;
9 | import lombok.Data;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | @Data
14 | public class CertificateLifetimeActionModel {
15 |
16 | @Valid
17 | @NotNull
18 | @JsonProperty("trigger")
19 | private CertificateLifetimeActionTriggerModel trigger;
20 | @Valid
21 | @NotNull
22 | @JsonProperty("action")
23 | @JsonSerialize(using = CertificateLifetimeActionSerializer.class)
24 | @JsonDeserialize(using = CertificateLifetimeActionDeserializer.class)
25 | private CertificateLifetimeActionActivity action;
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/java/com/github/nagyesta/lowkeyvault/sequential/RunSequentialCucumberTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.sequential;
2 |
3 | import io.cucumber.picocontainer.PicoFactory;
4 | import io.cucumber.testng.AbstractTestNGCucumberTests;
5 | import io.cucumber.testng.CucumberOptions;
6 | import org.testng.annotations.DataProvider;
7 | import org.testng.annotations.Test;
8 |
9 | @CucumberOptions(
10 | glue = {"com.github.nagyesta.lowkeyvault.sequential",
11 | "com.github.nagyesta.lowkeyvault.hook",
12 | "com.github.nagyesta.lowkeyvault.steps",
13 | "com.github.nagyesta.lowkeyvault.context"},
14 | features = {"classpath:/com/github/nagyesta/lowkeyvault/management"},
15 | plugin = {"com.github.nagyesta.abortmission.booster.cucumber.AbortMissionPlugin",
16 | "html:build/reports/cucumber/cucumber-sequential-report.html"},
17 | objectFactory = PicoFactory.class)
18 | @Test(dependsOnGroups = "parallel")
19 | public class RunSequentialCucumberTest extends AbstractTestNGCucumberTests {
20 |
21 | @DataProvider
22 | @Override
23 | public Object[][] scenarios() {
24 | return super.scenarios();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/CertificateImportRequest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64CertDeserializer;
5 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64CertSerializer;
6 | import jakarta.validation.Valid;
7 | import jakarta.validation.constraints.NotNull;
8 | import lombok.Data;
9 | import tools.jackson.databind.annotation.JsonDeserialize;
10 | import tools.jackson.databind.annotation.JsonSerialize;
11 |
12 | import java.util.Map;
13 |
14 | @Data
15 | public class CertificateImportRequest {
16 |
17 | @JsonProperty("pwd")
18 | private String password;
19 | @NotNull
20 | @JsonSerialize(using = Base64CertSerializer.class)
21 | @JsonDeserialize(using = Base64CertDeserializer.class)
22 | @JsonProperty("value")
23 | private byte[] certificate;
24 | @Valid
25 | @JsonProperty("attributes")
26 | private CertificatePropertiesModel attributes;
27 | @JsonProperty("policy")
28 | private CertificatePolicyModel policy;
29 | @JsonProperty("tags")
30 | private Map tags;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/certificate/impl/CertAuthorityType.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.certificate.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.certificate.CertificateLifetimeActionActivity;
4 | import lombok.Getter;
5 |
6 | import java.util.Arrays;
7 |
8 | @Getter
9 | public enum CertAuthorityType {
10 |
11 | /**
12 | * Self-signed certificate.
13 | */
14 | SELF_SIGNED("Self", CertificateLifetimeActionActivity.AUTO_RENEW),
15 | /**
16 | * Unknown, imported certificate.
17 | */
18 | UNKNOWN("Unknown", CertificateLifetimeActionActivity.EMAIL_CONTACTS);
19 |
20 | private final String value;
21 | private final CertificateLifetimeActionActivity defaultAction;
22 |
23 | CertAuthorityType(
24 | final String value,
25 | final CertificateLifetimeActionActivity action) {
26 | this.value = value;
27 | this.defaultAction = action;
28 | }
29 |
30 | public static CertAuthorityType byValue(final String value) {
31 | return Arrays.stream(values())
32 | .filter(c -> c.getValue().equals(value))
33 | .findFirst()
34 | .orElse(UNKNOWN);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/backup/KeyBackupModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common.backup;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64ZipKeyDeserializer;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64ZipKeySerializer;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.BaseBackupModel;
6 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.KeyPropertiesModel;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.ToString;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | @Data
14 | @EqualsAndHashCode(callSuper = true)
15 | @ToString(callSuper = true)
16 | public class KeyBackupModel
17 | extends BaseBackupModel {
18 |
19 | @JsonSerialize(using = Base64ZipKeySerializer.class)
20 | @Override
21 | public KeyBackupList getValue() {
22 | return super.getValue();
23 | }
24 |
25 | @JsonDeserialize(using = Base64ZipKeyDeserializer.class)
26 | @Override
27 | public void setValue(final KeyBackupList value) {
28 | super.setValue(value);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/key/impl/DefaultKeyRotationPolicy.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.key.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.constants.LifetimeActionType;
4 | import com.github.nagyesta.lowkeyvault.service.key.KeyLifetimeAction;
5 | import com.github.nagyesta.lowkeyvault.service.key.constants.LifetimeActionTriggerType;
6 | import com.github.nagyesta.lowkeyvault.service.key.id.KeyEntityId;
7 |
8 | import java.time.Period;
9 | import java.util.Map;
10 |
11 | public class DefaultKeyRotationPolicy
12 | extends KeyRotationPolicy {
13 |
14 | private static final KeyLifetimeActionTrigger TRIGGER_30_DAYS_BEFORE_EXPIRY =
15 | new KeyLifetimeActionTrigger(Period.ofDays(30), LifetimeActionTriggerType.TIME_BEFORE_EXPIRY);
16 | private static final KeyLifetimeAction NOTIFY_30_DAYS_BEFORE_EXPIRY
17 | = new KeyLifetimeAction(LifetimeActionType.NOTIFY, TRIGGER_30_DAYS_BEFORE_EXPIRY);
18 | private static final Period PERIOD_1_YEAR = Period.ofYears(1);
19 |
20 | public DefaultKeyRotationPolicy(final KeyEntityId keyEntityId) {
21 | super(keyEntityId, PERIOD_1_YEAR, Map.of(LifetimeActionType.NOTIFY, NOTIFY_30_DAYS_BEFORE_EXPIRY));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/template/backup/BackupTemplateProcessor.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.template.backup;
2 |
3 | import com.github.jknack.handlebars.Handlebars;
4 | import com.github.nagyesta.lowkeyvault.template.HandlebarsTemplateProcessor;
5 | import lombok.NonNull;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.io.IOException;
10 |
11 | @Component
12 | public class BackupTemplateProcessor
13 | implements HandlebarsTemplateProcessor {
14 |
15 | private final TimeHelperSource timeHelperSource;
16 |
17 | @Autowired
18 | public BackupTemplateProcessor(final TimeHelperSource timeHelperSource) {
19 | this.timeHelperSource = timeHelperSource;
20 | }
21 |
22 | @Override
23 | public String processTemplate(
24 | @NonNull final String templateAsString,
25 | @NonNull final BackupContext context) throws IOException {
26 | final var handlebars = new Handlebars();
27 | handlebars.registerHelpers(timeHelperSource);
28 | final var template = handlebars.compileInline(templateAsString);
29 | return template.apply(context);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/KeyVaultPendingCertificateModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64CertDeserializer;
5 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64CertSerializer;
6 | import lombok.Data;
7 | import tools.jackson.databind.annotation.JsonDeserialize;
8 | import tools.jackson.databind.annotation.JsonSerialize;
9 |
10 | @Data
11 | public class KeyVaultPendingCertificateModel {
12 |
13 | @JsonProperty("cancellation_requested")
14 | private boolean cancellationRequested;
15 | @JsonProperty("csr")
16 | @JsonDeserialize(using = Base64CertDeserializer.class)
17 | @JsonSerialize(using = Base64CertSerializer.class)
18 | private byte[] csr;
19 | @JsonProperty("id")
20 | private String id;
21 | @JsonProperty("issuer")
22 | private IssuerParameterModel issuer;
23 | @JsonProperty("request_id")
24 | private String requestId;
25 | @JsonProperty("status")
26 | private String status;
27 | @JsonProperty("status_details")
28 | private String statusDetails;
29 | @JsonProperty("target")
30 | private String target;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/test/java/com/github/nagyesta/lowkeyvault/http/management/RecoveryLevelTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http.management;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.params.ParameterizedTest;
5 | import org.junit.jupiter.params.provider.Arguments;
6 | import org.junit.jupiter.params.provider.MethodSource;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.stream.Collectors;
11 | import java.util.stream.Stream;
12 |
13 | class RecoveryLevelTest {
14 |
15 | public static Stream validProvider() {
16 | final var list = Arrays.stream(RecoveryLevel.values())
17 | .map(r -> Arguments.of(r.getValue(), r))
18 | .collect(Collectors.toCollection(ArrayList::new));
19 | list.add(Arguments.of(null, RecoveryLevel.PURGEABLE));
20 | return list.stream();
21 | }
22 |
23 | @ParameterizedTest
24 | @MethodSource("validProvider")
25 | void testForValueShouldReturnExpectedValueWhenCalled(final String input, final RecoveryLevel expected) {
26 | //given
27 |
28 | //when
29 | final var actual = RecoveryLevel.forValue(input);
30 |
31 | //then
32 | Assertions.assertEquals(expected, actual);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_3/certificate/CertificateEntityToV73CertificateVersionItemModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_3.certificate;
2 |
3 | import com.github.nagyesta.lowkeyvault.mapper.common.registry.CertificateConverterRegistry;
4 | import com.github.nagyesta.lowkeyvault.service.certificate.ReadOnlyKeyVaultCertificateEntity;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.lang.NonNull;
7 |
8 | import java.net.URI;
9 |
10 | public class CertificateEntityToV73CertificateVersionItemModelConverter
11 | extends CertificateEntityToV73CertificateItemModelConverter {
12 |
13 | @Autowired
14 | public CertificateEntityToV73CertificateVersionItemModelConverter(@NonNull final CertificateConverterRegistry registry) {
15 | super(registry);
16 | }
17 |
18 | @Override
19 | protected String convertCertificateId(
20 | final ReadOnlyKeyVaultCertificateEntity source,
21 | final URI vaultUri) {
22 | return source.getId().asUri(vaultUri).toString();
23 | }
24 |
25 | @Override
26 | protected void register(final CertificateConverterRegistry registry) {
27 | registry.registerVersionedItemConverter(this);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/backup/SecretBackupModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common.backup;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64ZipSecretDeserializer;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64ZipSecretSerializer;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.BaseBackupModel;
6 | import com.github.nagyesta.lowkeyvault.model.v7_2.secret.SecretPropertiesModel;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.ToString;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | @Data
14 | @EqualsAndHashCode(callSuper = true)
15 | @ToString(callSuper = true)
16 | public class SecretBackupModel
17 | extends BaseBackupModel {
18 |
19 | @JsonSerialize(using = Base64ZipSecretSerializer.class)
20 | @Override
21 | public SecretBackupList getValue() {
22 | return super.getValue();
23 | }
24 |
25 | @JsonDeserialize(using = Base64ZipSecretDeserializer.class)
26 | @Override
27 | public void setValue(final SecretBackupList value) {
28 | super.setValue(value);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/constants/EncryptionAlgorithmTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key.constants;
2 |
3 | import com.github.nagyesta.lowkeyvault.TestConstants;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.params.ParameterizedTest;
6 | import org.junit.jupiter.params.provider.Arguments;
7 | import org.junit.jupiter.params.provider.MethodSource;
8 |
9 | import java.util.Arrays;
10 | import java.util.stream.Stream;
11 |
12 | class EncryptionAlgorithmTest {
13 |
14 | public static Stream valueProvider() {
15 | final var builder = Stream.builder()
16 | .add(Arguments.of(null, null))
17 | .add(Arguments.of(TestConstants.EMPTY, null));
18 | Arrays.stream(EncryptionAlgorithm.values()).forEach(a -> builder.add(Arguments.of(a.getValue(), a)));
19 | return builder.build();
20 | }
21 |
22 | @ParameterizedTest
23 | @MethodSource("valueProvider")
24 | void forValue(final String inout, final EncryptionAlgorithm expected) {
25 | //given
26 |
27 | //when
28 | final var actual = EncryptionAlgorithm.forValue(inout);
29 |
30 | //then
31 | Assertions.assertEquals(expected, actual);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/common/ReadOnlyVersionedEntityMultiMap.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.common;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.constants.RecoveryLevel;
4 | import com.github.nagyesta.lowkeyvault.service.EntityId;
5 |
6 | import java.util.Deque;
7 | import java.util.List;
8 | import java.util.Optional;
9 | import java.util.function.Predicate;
10 |
11 | @SuppressWarnings("java:S119") //It is easier to ensure that the types are consistent this way
12 | public interface ReadOnlyVersionedEntityMultiMap> {
13 |
14 | List listLatestEntities();
15 |
16 | List listLatestNonManagedEntities();
17 |
18 | Deque getVersions(K entityId);
19 |
20 | boolean containsName(String name);
21 |
22 | boolean containsEntityMatching(String name, Predicate predicate);
23 |
24 | boolean containsEntity(K entityId);
25 |
26 | void assertContainsEntity(V entityId);
27 |
28 | V getLatestVersionOfEntity(K entityId);
29 |
30 | R getEntity(V entityId, Class type);
31 |
32 | RE getReadOnlyEntity(V entityId);
33 |
34 | RecoveryLevel getRecoveryLevel();
35 |
36 | Optional getRecoverableDays();
37 | }
38 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_2/key/AesJsonWebKeyImportRequestConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_2.key;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.request.JsonWebKeyImportRequest;
4 | import com.github.nagyesta.lowkeyvault.service.exception.CryptoException;
5 | import org.springframework.lang.NonNull;
6 |
7 | import javax.crypto.SecretKey;
8 | import javax.crypto.spec.SecretKeySpec;
9 |
10 | /**
11 | * Converts import requests to AES key pairs.
12 | */
13 | public class AesJsonWebKeyImportRequestConverter
14 | extends BaseJsonWebKeyImportRequestConverter {
15 |
16 | private static final int AES_BYTES_TO_KEY_SIZE_BITS_MULTIPLIER = 8;
17 |
18 | @NonNull
19 | @Override
20 | public SecretKey convert(@NonNull final JsonWebKeyImportRequest source) {
21 | try {
22 | return new SecretKeySpec(source.getK(), source.getKeyType().getAlgorithmName());
23 | } catch (final Exception e) {
24 | throw new CryptoException(e.getMessage(), e);
25 | }
26 | }
27 |
28 | @Override
29 | public Integer getKeyParameter(@NonNull final JsonWebKeyImportRequest source) {
30 | return source.getK().length * AES_BYTES_TO_KEY_SIZE_BITS_MULTIPLIER;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/main/java/com/github/nagyesta/lowkeyvault/http/management/VaultModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http.management;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
5 | import com.fasterxml.jackson.databind.annotation.JsonSerialize;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import java.net.URI;
11 | import java.time.OffsetDateTime;
12 | import java.util.Set;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | public class VaultModel {
18 |
19 | @JsonProperty("baseUri")
20 | private URI baseUri;
21 | @JsonProperty("aliases")
22 | private Set aliases;
23 | @JsonProperty("recoveryLevel")
24 | private RecoveryLevel recoveryLevel;
25 | @JsonProperty("recoverableDays")
26 | private Integer recoverableDays;
27 | @JsonProperty("created")
28 | @JsonSerialize(using = EpochSecondsSerializer.class)
29 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
30 | private OffsetDateTime createdOn;
31 | @JsonProperty("deleted")
32 | @JsonSerialize(using = EpochSecondsSerializer.class)
33 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
34 | private OffsetDateTime deletedOn;
35 | }
36 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/template/backup/VaultImporterProperties.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.template.backup;
2 |
3 | import lombok.Data;
4 | import org.springframework.beans.factory.annotation.Value;
5 | import org.springframework.stereotype.Component;
6 |
7 | import java.io.File;
8 |
9 | @Data
10 | @Component
11 | public class VaultImporterProperties {
12 |
13 | private final File importFile;
14 | private final String importTemplateHost;
15 | private final int importTemplatePort;
16 |
17 | public VaultImporterProperties(
18 | @Value("${LOWKEY_IMPORT_LOCATION}") final File importFile,
19 | @Value("${LOWKEY_IMPORT_TEMPLATE_HOST:localhost}") final String importTemplateHost,
20 | @Value("${LOWKEY_IMPORT_TEMPLATE_PORT:${server.port}}") final int importTemplatePort) {
21 | this.importFile = importFile;
22 | this.importTemplateHost = importTemplateHost;
23 | this.importTemplatePort = importTemplatePort;
24 | }
25 |
26 | public BackupContext context() {
27 | return new BackupContext(importTemplateHost, importTemplatePort);
28 | }
29 |
30 | public boolean importFileExists() {
31 | return importFile != null && importFile.exists() && importFile.isFile() && importFile.canRead();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/key/impl/KeyLifetimeActionTrigger.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.key.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.key.LifetimeActionTrigger;
4 | import com.github.nagyesta.lowkeyvault.service.key.constants.LifetimeActionTriggerType;
5 | import com.github.nagyesta.lowkeyvault.service.key.util.PeriodUtil;
6 | import lombok.NonNull;
7 |
8 | import java.time.OffsetDateTime;
9 | import java.time.Period;
10 |
11 | public record KeyLifetimeActionTrigger(
12 | @NonNull Period timePeriod,
13 | @NonNull LifetimeActionTriggerType triggerType) implements LifetimeActionTrigger {
14 |
15 | @Override
16 | public boolean shouldTrigger(
17 | final OffsetDateTime created,
18 | final OffsetDateTime expiry) {
19 | return triggerType.shouldTrigger(created, expiry, timePeriod);
20 | }
21 |
22 | @Override
23 | public long rotateAfterDays(@NonNull final Period expiryPeriod) {
24 | final long days;
25 | if (triggerType == LifetimeActionTriggerType.TIME_AFTER_CREATE) {
26 | days = PeriodUtil.asDays(timePeriod);
27 | } else {
28 | days = PeriodUtil.asDays(expiryPeriod) - PeriodUtil.asDays(timePeriod);
29 | }
30 | return days;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/constants/KeyCurveNameTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key.constants;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.params.ParameterizedTest;
5 | import org.junit.jupiter.params.provider.Arguments;
6 | import org.junit.jupiter.params.provider.MethodSource;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.List;
11 | import java.util.Optional;
12 | import java.util.stream.Stream;
13 |
14 | class KeyCurveNameTest {
15 |
16 | public static Stream valueProvider() {
17 | final List list = new ArrayList<>();
18 | list.add(null);
19 | list.addAll(Arrays.asList(KeyCurveName.values()));
20 | return list.stream()
21 | .map(value -> Arguments.of(Optional.ofNullable(value).map(KeyCurveName::getValue).orElse(null), value));
22 | }
23 |
24 | @ParameterizedTest
25 | @MethodSource("valueProvider")
26 | void testForValueShouldReturnEnumWhenValueStringMatches(final String input, final KeyCurveName expected) {
27 | //given
28 |
29 | //when
30 | final var actual = KeyCurveName.forValue(input);
31 |
32 | //then
33 | Assertions.assertEquals(expected, actual);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/constants/KeyOperationTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key.constants;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.params.ParameterizedTest;
5 | import org.junit.jupiter.params.provider.Arguments;
6 | import org.junit.jupiter.params.provider.MethodSource;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.List;
11 | import java.util.Optional;
12 | import java.util.stream.Stream;
13 |
14 | class KeyOperationTest {
15 |
16 | public static Stream valueProvider() {
17 | final List list = new ArrayList<>();
18 | list.add(null);
19 | list.addAll(Arrays.asList(KeyOperation.values()));
20 | return list.stream()
21 | .map(value -> Arguments.of(Optional.ofNullable(value).map(KeyOperation::getValue).orElse(null), value));
22 | }
23 |
24 | @ParameterizedTest
25 | @MethodSource("valueProvider")
26 | void testForValueShouldReturnEnumWhenValueStringMatches(final String input, final KeyOperation expected) {
27 | //given
28 |
29 | //when
30 | final var actual = KeyOperation.forValue(input);
31 |
32 | //then
33 | Assertions.assertEquals(expected, actual);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/backup/KeyBackupList.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common.backup;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.BackupListContainer;
6 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.KeyRotationPolicyModel;
7 | import jakarta.validation.Valid;
8 | import jakarta.validation.constraints.NotNull;
9 | import jakarta.validation.constraints.Size;
10 | import lombok.EqualsAndHashCode;
11 | import lombok.Getter;
12 | import lombok.Setter;
13 | import lombok.ToString;
14 |
15 | import java.util.List;
16 |
17 | @Getter
18 | @EqualsAndHashCode
19 | @ToString
20 | public class KeyBackupList
21 | implements BackupListContainer {
22 |
23 | @Valid
24 | @NotNull
25 | @Size(min = 1)
26 | @JsonProperty("versions")
27 | private List versions = List.of();
28 |
29 | @Setter
30 | @Valid
31 | @JsonProperty("rotationPolicy")
32 | @JsonInclude(JsonInclude.Include.NON_NULL)
33 | private KeyRotationPolicyModel keyRotationPolicy;
34 |
35 | public void setVersions(final List versions) {
36 | this.versions = List.copyOf(versions);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/common/BaseBackupListItem.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.common;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.BasePropertiesModel;
6 | import jakarta.validation.Valid;
7 | import jakarta.validation.constraints.NotBlank;
8 | import jakarta.validation.constraints.NotNull;
9 | import lombok.Data;
10 |
11 | import java.net.URI;
12 | import java.util.Map;
13 |
14 | /**
15 | * Base list item of backup models.
16 | *
17 | * @param The type of the properties model.
18 | */
19 | @Data
20 | @JsonInclude(JsonInclude.Include.NON_NULL)
21 | public class BaseBackupListItem
{
22 |
23 | @NotNull
24 | @JsonProperty("vaultBaseUri")
25 | private URI vaultBaseUri;
26 | @NotNull
27 | @NotBlank
28 | @JsonProperty("entityId")
29 | private String id;
30 | @NotNull
31 | @NotBlank
32 | @JsonProperty("entityVersion")
33 | private String version;
34 | @Valid
35 | @NotNull
36 | @JsonProperty("attributes")
37 | private P attributes;
38 | @JsonProperty("tags")
39 | private Map tags;
40 | @JsonProperty("managed")
41 | private boolean managed;
42 | }
43 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/common/backup/CertificateBackupModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.common.backup;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64ZipCertificateDeserializer;
4 | import com.github.nagyesta.lowkeyvault.model.json.util.Base64ZipCertificateSerializer;
5 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.BaseBackupModel;
6 | import com.github.nagyesta.lowkeyvault.model.v7_3.certificate.CertificatePropertiesModel;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.ToString;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | @Data
14 | @EqualsAndHashCode(callSuper = true)
15 | @ToString(callSuper = true)
16 | public class CertificateBackupModel
17 | extends BaseBackupModel {
18 |
19 | @JsonSerialize(using = Base64ZipCertificateSerializer.class)
20 | @Override
21 | public CertificateBackupList getValue() {
22 | return super.getValue();
23 | }
24 |
25 | @JsonDeserialize(using = Base64ZipCertificateDeserializer.class)
26 | @Override
27 | public void setValue(final CertificateBackupList value) {
28 | super.setValue(value);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/vault/VaultFake.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.vault;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.common.constants.RecoveryLevel;
4 | import com.github.nagyesta.lowkeyvault.service.certificate.CertificateVaultFake;
5 | import com.github.nagyesta.lowkeyvault.service.key.KeyVaultFake;
6 | import com.github.nagyesta.lowkeyvault.service.secret.SecretVaultFake;
7 |
8 | import java.net.URI;
9 | import java.time.OffsetDateTime;
10 | import java.util.Set;
11 | import java.util.function.UnaryOperator;
12 |
13 | public interface VaultFake {
14 |
15 | boolean matches(URI vaultUri, UnaryOperator uriMapper);
16 |
17 | URI baseUri();
18 |
19 | Set aliases();
20 |
21 | void setAliases(Set aliases);
22 | KeyVaultFake keyVaultFake();
23 |
24 | SecretVaultFake secretVaultFake();
25 |
26 | CertificateVaultFake certificateVaultFake();
27 |
28 | RecoveryLevel getRecoveryLevel();
29 |
30 | Integer getRecoverableDays();
31 |
32 | OffsetDateTime getCreatedOn();
33 |
34 | OffsetDateTime getDeletedOn();
35 |
36 | boolean isDeleted();
37 |
38 | boolean isActive();
39 |
40 | boolean isExpired();
41 |
42 | void delete();
43 |
44 | void recover();
45 |
46 | void timeShift(int offsetSeconds, boolean regenerateCertificates);
47 | }
48 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/main/java/com/github/nagyesta/lowkeyvault/http/management/LowkeyVaultManagementClient.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http.management;
2 |
3 | import lombok.NonNull;
4 |
5 | import java.io.IOException;
6 | import java.net.URI;
7 | import java.util.List;
8 | import java.util.function.Supplier;
9 |
10 | public interface LowkeyVaultManagementClient {
11 |
12 | void verifyConnectivity(
13 | int retries,
14 | int waitMillis, Supplier exceptionProvider) throws T, InterruptedException;
15 |
16 | VaultModel createVault(
17 | @NonNull URI baseUri,
18 | @NonNull RecoveryLevel recoveryLevel,
19 | @NonNull Integer recoverableDays);
20 |
21 | List listVaults();
22 |
23 | List listDeletedVaults();
24 |
25 | boolean delete(@NonNull URI baseUri);
26 |
27 | VaultModel recover(@NonNull URI baseUri);
28 |
29 | VaultModel addAlias(@NonNull URI baseUri, @NonNull URI alias);
30 |
31 | VaultModel removeAlias(@NonNull URI baseUri, @NonNull URI alias);
32 |
33 | boolean purge(@NonNull URI baseUri);
34 |
35 | void timeShift(@NonNull TimeShiftContext context);
36 |
37 | String exportActive();
38 |
39 | String unpackBackup(byte[] backup) throws IOException;
40 |
41 | byte[] compressBackup(String backup) throws IOException;
42 | }
43 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/com/github/nagyesta/lowkeyvault/secrets/ListSecrets.feature:
--------------------------------------------------------------------------------
1 | Feature: Secret list
2 |
3 | @Secret @SecretCreate @SecretList @CreateVault
4 | Scenario Outline: SECRET_LIST_01 Secrets are created with the secret client then all are listed
5 | Given secret API version is used
6 | And a vault is created with name secrets-list-
7 | And a secret client is created with the vault named secrets-list-
8 | And secrets with - prefix are created valued abc123
9 | When the secret properties are listed
10 | Then the listed secrets are matching the ones created
11 | And the list of secrets should contain 0 managed items
12 |
13 | Examples:
14 | | api | index | count | secretName |
15 | | 7.2 | 01 | 1 | listSecret |
16 | | 7.3 | 02 | 1 | listSecret |
17 | | 7.3 | 03 | 2 | list-secret-name |
18 | | 7.3 | 04 | 3 | listSecret |
19 | | 7.3 | 05 | 5 | list-secret-name |
20 | | 7.3 | 06 | 25 | listSecret |
21 | | 7.3 | 07 | 42 | list-secret-name |
22 | | 7.4 | 08 | 5 | list-secret-name |
23 | | 7.5 | 09 | 5 | list-secret-name |
24 | | 7.6 | 10 | 5 | list-secret-name |
25 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/common/VaultFakeToVaultModelConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.common;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.management.VaultModel;
4 | import com.github.nagyesta.lowkeyvault.service.vault.VaultFake;
5 | import org.springframework.core.convert.converter.Converter;
6 | import org.springframework.lang.NonNull;
7 | import org.springframework.lang.Nullable;
8 | import org.springframework.stereotype.Component;
9 |
10 | import java.util.Optional;
11 |
12 | @Component
13 | public class VaultFakeToVaultModelConverter
14 | implements Converter {
15 |
16 | @Override
17 | public VaultModel convert(@Nullable final VaultFake source) {
18 | return Optional.ofNullable(source)
19 | .map(this::convertNonNull)
20 | .orElse(null);
21 | }
22 |
23 | @NonNull
24 | public VaultModel convertNonNull(@NonNull final VaultFake fake) {
25 | final var model = new VaultModel();
26 | model.setBaseUri(fake.baseUri());
27 | model.setAliases(fake.aliases());
28 | model.setRecoveryLevel(fake.getRecoveryLevel());
29 | model.setRecoverableDays(fake.getRecoverableDays());
30 | model.setCreatedOn(fake.getCreatedOn());
31 | model.setDeletedOn(fake.getDeletedOn());
32 | return model;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/CertificatePolicyModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import jakarta.validation.Valid;
6 | import jakarta.validation.constraints.NotNull;
7 | import jakarta.validation.constraints.Size;
8 | import lombok.Data;
9 |
10 | import java.util.List;
11 |
12 | @Data
13 | public class CertificatePolicyModel {
14 |
15 | @JsonProperty("id")
16 | private String id;
17 | @Valid
18 | @NotNull
19 | @JsonProperty("key_props")
20 | private CertificateKeyModel keyProperties;
21 | @Valid
22 | @NotNull
23 | @JsonProperty("secret_props")
24 | private CertificateSecretModel secretProperties;
25 | @Valid
26 | @NotNull
27 | @JsonProperty("x509_props")
28 | private X509CertificateModel x509Properties;
29 | @Valid
30 | @NotNull
31 | @JsonProperty("issuer")
32 | private IssuerParameterModel issuer;
33 | @Valid
34 | @JsonProperty("attributes")
35 | private CertificatePropertiesModel attributes;
36 | @Valid
37 | @Size(max = 1) //only one can be set on the UI
38 | @JsonProperty("lifetime_actions")
39 | @JsonInclude(JsonInclude.Include.NON_NULL)
40 | private List lifetimeActions;
41 | }
42 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/service/certificate/impl/CertificateAlgorithm.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.service.certificate.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyType;
4 | import lombok.Getter;
5 | import lombok.NonNull;
6 |
7 | import java.util.Arrays;
8 | import java.util.Set;
9 |
10 | public enum CertificateAlgorithm {
11 |
12 | /**
13 | * Certificate signed using RSA algorithm.
14 | */
15 | RSA("SHA256withRSA", Set.of(KeyType.RSA, KeyType.RSA_HSM)),
16 | /**
17 | * Certificate signed using EC algorithm.
18 | */
19 | EC("SHA256withECDSA", Set.of(KeyType.EC, KeyType.EC_HSM));
20 |
21 | @Getter
22 | private final String algorithm;
23 | private final Set keyTypes;
24 |
25 | CertificateAlgorithm(
26 | final String algorithm,
27 | final Set keyTypes) {
28 | this.algorithm = algorithm;
29 | this.keyTypes = keyTypes;
30 | }
31 |
32 | public static CertificateAlgorithm forKeyType(@NonNull final KeyType keyType) {
33 | final var value = Arrays.stream(CertificateAlgorithm.values())
34 | .filter(v -> v.keyTypes.contains(keyType))
35 | .findFirst();
36 | return value.orElseThrow(() -> new IllegalArgumentException("Unable to find certificate algorithm for key type: " + keyType));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/DeletedKeyVaultKeyModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.common.DeletedModel;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsDeserializer;
7 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsSerializer;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | import java.time.OffsetDateTime;
14 |
15 | @Data
16 | @EqualsAndHashCode(callSuper = true)
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | public class DeletedKeyVaultKeyModel
19 | extends KeyVaultKeyModel implements DeletedModel {
20 |
21 | @JsonProperty("recoveryId")
22 | private String recoveryId;
23 | @JsonProperty("deletedDate")
24 | @JsonSerialize(using = EpochSecondsSerializer.class)
25 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
26 | private OffsetDateTime deletedDate;
27 | @JsonProperty("scheduledPurgeDate")
28 | @JsonSerialize(using = EpochSecondsSerializer.class)
29 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
30 | private OffsetDateTime scheduledPurgeDate;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/constants/LifetimeActionTypeTest.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key.constants;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 | import org.junit.jupiter.params.ParameterizedTest;
5 | import org.junit.jupiter.params.provider.Arguments;
6 | import org.junit.jupiter.params.provider.MethodSource;
7 |
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.List;
11 | import java.util.Optional;
12 | import java.util.stream.Stream;
13 |
14 | class LifetimeActionTypeTest {
15 |
16 | public static Stream valueProvider() {
17 | final List list = new ArrayList<>();
18 | list.add(null);
19 | list.addAll(Arrays.asList(LifetimeActionType.values()));
20 | return list.stream()
21 | .map(value -> Arguments.of(
22 | Optional.ofNullable(value).map(LifetimeActionType::getValue).orElse("unknown"),
23 | value));
24 | }
25 |
26 | @ParameterizedTest
27 | @MethodSource("valueProvider")
28 | void testForValueShouldReturnEnumWhenValueStringMatches(final String input, final LifetimeActionType expected) {
29 | //given
30 |
31 | //when
32 | final var actual = LifetimeActionType.forValue(input);
33 |
34 | //then
35 | Assertions.assertEquals(expected, actual);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lowkey-vault-client/src/main/java/com/github/nagyesta/lowkeyvault/http/management/impl/UriUtil.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.http.management.impl;
2 |
3 | import com.github.nagyesta.lowkeyvault.http.management.LowkeyVaultException;
4 | import lombok.NonNull;
5 | import org.apache.http.client.utils.URIBuilder;
6 |
7 | import java.net.URI;
8 | import java.net.URISyntaxException;
9 | import java.util.Collections;
10 | import java.util.Map;
11 | import java.util.Objects;
12 |
13 | public final class UriUtil {
14 |
15 | private UriUtil() {
16 | throw new IllegalCallerException("Utility cannot be instantiated.");
17 | }
18 |
19 | public static URI uriBuilderForPath(
20 | final String baseUrl,
21 | final String path) {
22 | return uriBuilderForPath(baseUrl, path, Map.of());
23 | }
24 |
25 | public static URI uriBuilderForPath(
26 | @NonNull final String baseUrl,
27 | @NonNull final String path,
28 | final Map parameters) {
29 | try {
30 | final var builder = new URIBuilder(baseUrl).setPath(path);
31 | Objects.requireNonNullElse(parameters, Collections.emptyMap()).forEach(builder::addParameter);
32 | return builder.build();
33 | } catch (final URISyntaxException e) {
34 | throw new LowkeyVaultException("Unable to parse baseUrl.", e);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/CertificateLifetimeActionDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import com.github.nagyesta.lowkeyvault.service.certificate.CertificateLifetimeActionActivity;
4 | import org.springframework.util.Assert;
5 | import tools.jackson.core.JsonParser;
6 | import tools.jackson.databind.DeserializationContext;
7 | import tools.jackson.databind.ValueDeserializer;
8 |
9 | public class CertificateLifetimeActionDeserializer
10 | extends ValueDeserializer {
11 |
12 | private static final String INNER_NODE_NAME = "action_type";
13 |
14 | @Override
15 | public CertificateLifetimeActionActivity deserialize(
16 | final JsonParser parser,
17 | final DeserializationContext context) {
18 | final var node = parser.readValueAsTree();
19 | Assert.isTrue(node.isObject(), "The \"action\" node must represent an object.");
20 | final var actionType = node.path(INNER_NODE_NAME);
21 | Assert.isTrue(actionType.isValueNode(),
22 | "The \"action\" node must have an \"" + INNER_NODE_NAME + "\" child containing the value.");
23 | try (var textField = actionType.traverse(context)) {
24 | final var value = textField.nextStringValue();
25 | return CertificateLifetimeActionActivity.byValue(value);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/key/DeletedKeyVaultKeyItemModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.key;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.common.DeletedModel;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsDeserializer;
7 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsSerializer;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | import java.time.OffsetDateTime;
14 |
15 | @Data
16 | @EqualsAndHashCode(callSuper = true)
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | public class DeletedKeyVaultKeyItemModel
19 | extends KeyVaultKeyItemModel implements DeletedModel {
20 |
21 | @JsonProperty("recoveryId")
22 | private String recoveryId;
23 | @JsonProperty("deletedDate")
24 | @JsonSerialize(using = EpochSecondsSerializer.class)
25 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
26 | private OffsetDateTime deletedDate;
27 | @JsonProperty("scheduledPurgeDate")
28 | @JsonSerialize(using = EpochSecondsSerializer.class)
29 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
30 | private OffsetDateTime scheduledPurgeDate;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/secret/DeletedKeyVaultSecretModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.secret;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.common.DeletedModel;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsDeserializer;
7 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsSerializer;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | import java.time.OffsetDateTime;
14 |
15 | @Data
16 | @EqualsAndHashCode(callSuper = true)
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | public class DeletedKeyVaultSecretModel
19 | extends KeyVaultSecretModel implements DeletedModel {
20 |
21 | @JsonProperty("recoveryId")
22 | private String recoveryId;
23 | @JsonProperty("deletedDate")
24 | @JsonSerialize(using = EpochSecondsSerializer.class)
25 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
26 | private OffsetDateTime deletedDate;
27 | @JsonProperty("scheduledPurgeDate")
28 | @JsonSerialize(using = EpochSecondsSerializer.class)
29 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
30 | private OffsetDateTime scheduledPurgeDate;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/resources/key/import/rsa-import-missing-d.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": {
3 | "kty": "RSA",
4 | "n": "nKAwarTrOpzd1hhH4cQNdVTgRF-b0ubPD8ZNVf0UXjb62QuAk3Dn68ESThcF7SoDYRx2QVcfoMC9WCcuQUQDieJF-lvJTSer1TwH72NBovwKlHvrXqEI0a6_uVYY5n-soGt7qFZNbwQLdWWA6PrbqTLIkv6r01dcuhTiQQAn6OWEa0JbFvWfF1kILQIaSBBBaaQ4R7hZs7-VQTHGD7J1xGteof4gw2VTiwNdcE8p5UG5b6S9KQwAeET4yB4KFPwQ3TDdzxJQ89mwYVi_sgAIggN54hTq4oEKYJHBOMtFGIN0_HQ60ZSUnpOi87xNC-8VFqnv4rfTQ7nkK6XMvjMVfw",
5 | "e": "AQAB",
6 | "dp": "ZGnmWx-Nca71z9a9vvT4g02iv3S-3kSgmhl8JST09YQwK8tfiK7nXnNMtXJi2K4dLKKnLicGtCzB6W3mXdLcP2SUOWDOeStoBt8HEBT4MrI1psCKqnBum78WkHju90rBFj99amkP6UeQy5EASAzgmKQu2nUaUnRV0lYP8LHMCkE",
7 | "dq": "dtpke0foFs04hPS6XYLA5lc7-1MAHfZKN4CkMAofwDqPmRQzCxpDJUk0gMWGJEdU_Lqfbg22Py44cci0dczH36NW3UU5BL86T2_SPPDOuyX7kDscrIJCdowxQCGJHGRBEozM_uTL46wu6UnUIv7m7cuGgodJyZBcdwpo6ziFink",
8 | "qi": "Y9KD5GaHkAYmAqpOfAQUMr71QuAAaBb0APzMuUvoEYw39PD3_vJeh9HZ15QmJ8zCX10-nlzUB-bWwvK-rGcJXbK4pArilr5MiaYv7e8h5eW2zs2_itDJ6Oebi-wVbMhg7DvUTBbkCvPhhIedE4UlDQmMYP7RhzVVs7SfmkGs_DQ",
9 | "p": "v1jeCPnuJQM2PW2690Q9KJk0Ulok8VFGjkcHUHVi3orKdy7y_TCIWM6ZGvgFzI6abinzYbTEPKV4wFdMAwvOWmawXj5YrsoeB44_HXJ0ak_5_iP6XXR8MLGXbd0ZqsxvAZyzMj9vyle7EN2cBod6aenI2QZoRDucPvjPwZsZotk",
10 | "q": "0Yv-Dj6qnvx_LL70lUnKA6MgHE_bUC4drl5ZNDDsUdUUYfxIK4G1rGU45kHGtp-Qg-Uyf9s52ywLylhcVE3jfbjOgEozlSwKyhqfXkLpMLWHqOKj9fcfYd4PWKPOgpzWsqjA6fJbBUMYo0CU2G9cWCtVodO7sBJVSIZunWrAlBc"
11 | },
12 | "tags": {
13 | "purpose": "unit test"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/test/resources/key/import/rsa-import-missing-n.json:
--------------------------------------------------------------------------------
1 | {
2 | "key": {
3 | "kty": "RSA",
4 | "e": "AQAB",
5 | "d": "GeT1_D5LAZa7qlC7WZ0DKJnOth8kcPrN0urTEFtWCbmHQWkAad_px_VUpGp0BWDDzENbXbQcu4QCCdf4crve5eXt8dVI86OSah-RpEdBq8OFsETIhg2Tmq8MbYTJexoynRcIC62xAaCmkFMmu931gQSvWnYWTEuOPgmD2oE_F-bP9TFlGRc69a6MSbtcSRyFTsd5KsUr40QS4zf2W4kZCOWejyLuxk88SXgUqcJx86Ulc1Ol1KkTBLadvReAZCyCMwKBlNRGw46BU_iK0vK7rTD9fmEd639Gjti6eLpnyQYpnVe8uGgwVU1fHBkAKyapWoEG6VMhMntcrvgukKLIsQ",
6 | "dp": "ZGnmWx-Nca71z9a9vvT4g02iv3S-3kSgmhl8JST09YQwK8tfiK7nXnNMtXJi2K4dLKKnLicGtCzB6W3mXdLcP2SUOWDOeStoBt8HEBT4MrI1psCKqnBum78WkHju90rBFj99amkP6UeQy5EASAzgmKQu2nUaUnRV0lYP8LHMCkE",
7 | "dq": "dtpke0foFs04hPS6XYLA5lc7-1MAHfZKN4CkMAofwDqPmRQzCxpDJUk0gMWGJEdU_Lqfbg22Py44cci0dczH36NW3UU5BL86T2_SPPDOuyX7kDscrIJCdowxQCGJHGRBEozM_uTL46wu6UnUIv7m7cuGgodJyZBcdwpo6ziFink",
8 | "qi": "Y9KD5GaHkAYmAqpOfAQUMr71QuAAaBb0APzMuUvoEYw39PD3_vJeh9HZ15QmJ8zCX10-nlzUB-bWwvK-rGcJXbK4pArilr5MiaYv7e8h5eW2zs2_itDJ6Oebi-wVbMhg7DvUTBbkCvPhhIedE4UlDQmMYP7RhzVVs7SfmkGs_DQ",
9 | "p": "v1jeCPnuJQM2PW2690Q9KJk0Ulok8VFGjkcHUHVi3orKdy7y_TCIWM6ZGvgFzI6abinzYbTEPKV4wFdMAwvOWmawXj5YrsoeB44_HXJ0ak_5_iP6XXR8MLGXbd0ZqsxvAZyzMj9vyle7EN2cBod6aenI2QZoRDucPvjPwZsZotk",
10 | "q": "0Yv-Dj6qnvx_LL70lUnKA6MgHE_bUC4drl5ZNDDsUdUUYfxIK4G1rGU45kHGtp-Qg-Uyf9s52ywLylhcVE3jfbjOgEozlSwKyhqfXkLpMLWHqOKj9fcfYd4PWKPOgpzWsqjA6fJbBUMYo0CU2G9cWCtVodO7sBJVSIZunWrAlBc"
11 | },
12 | "tags": {
13 | "purpose": "unit test"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_2/secret/DeletedKeyVaultSecretItemModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_2.secret;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.common.DeletedModel;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsDeserializer;
7 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsSerializer;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | import java.time.OffsetDateTime;
14 |
15 | @Data
16 | @EqualsAndHashCode(callSuper = true)
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | public class DeletedKeyVaultSecretItemModel
19 | extends KeyVaultSecretItemModel implements DeletedModel {
20 |
21 | @JsonProperty("recoveryId")
22 | private String recoveryId;
23 | @JsonProperty("deletedDate")
24 | @JsonSerialize(using = EpochSecondsSerializer.class)
25 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
26 | private OffsetDateTime deletedDate;
27 | @JsonProperty("scheduledPurgeDate")
28 | @JsonSerialize(using = EpochSecondsSerializer.class)
29 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
30 | private OffsetDateTime scheduledPurgeDate;
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/key/KeyRotationPolicyModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.key;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.fasterxml.jackson.annotation.JsonPropertyOrder;
6 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.validator.Restore;
7 | import com.github.nagyesta.lowkeyvault.model.v7_3.key.validator.Update;
8 | import com.github.nagyesta.lowkeyvault.service.key.id.KeyEntityId;
9 | import jakarta.validation.Valid;
10 | import jakarta.validation.constraints.NotNull;
11 | import jakarta.validation.constraints.Size;
12 | import lombok.Data;
13 |
14 | import java.net.URI;
15 | import java.util.List;
16 |
17 | @Data
18 | @JsonPropertyOrder({"attributes", "id", "lifetimeActions"})
19 | public class KeyRotationPolicyModel {
20 |
21 | @NotNull(groups = {Restore.class})
22 | @JsonProperty("id")
23 | private URI id;
24 | @Valid
25 | @NotNull(groups = {Restore.class, Update.class})
26 | @JsonProperty("attributes")
27 | private KeyRotationPolicyAttributes attributes;
28 | @Valid
29 | @NotNull(groups = {Restore.class, Update.class})
30 | @Size(min = 1, max = 2, groups = {Restore.class, Update.class})
31 | @JsonProperty("lifetimeActions")
32 | private List lifetimeActions;
33 | @JsonIgnore
34 | private KeyEntityId keyEntityId;
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/json/util/Base64Serializer.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.json.util;
2 |
3 | import tools.jackson.core.JsonGenerator;
4 | import tools.jackson.databind.SerializationContext;
5 | import tools.jackson.databind.ValueSerializer;
6 |
7 | import java.util.Base64;
8 | import java.util.Optional;
9 |
10 | public class Base64Serializer extends ValueSerializer {
11 |
12 | private static final Base64.Encoder DEFAULT_ENCODER = Base64.getUrlEncoder().withoutPadding();
13 | private final Base64.Encoder encoder;
14 |
15 | public Base64Serializer() {
16 | this(DEFAULT_ENCODER);
17 | }
18 |
19 | protected Base64Serializer(final Base64.Encoder encoder) {
20 | this.encoder = encoder;
21 | }
22 |
23 | @Override
24 | public void serialize(
25 | final byte[] value,
26 | final JsonGenerator generator,
27 | final SerializationContext provider) {
28 | final var text = base64Encode(value);
29 | if (text != null) {
30 | generator.writeString(text);
31 | } else {
32 | generator.writeNull();
33 | }
34 | }
35 |
36 | protected String base64Encode(final byte[] value) {
37 | final var optional = Optional.ofNullable(value);
38 | return optional.filter(v -> v.length > 0)
39 | .map(encoder::encodeToString)
40 | .orElse(null);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lowkey-vault-docker/src/test/resources/com/github/nagyesta/lowkeyvault/secrets/ListDeletedSecrets.feature:
--------------------------------------------------------------------------------
1 | Feature: Secret list deleted
2 |
3 | @Secret @SecretCreate @SecretListDeleted @CreateVault
4 | Scenario Outline: SECRET_LIST_DELETED_01 Secrets are created and deleted with the secret client then all are listed as deleted secrets
5 | Given secret API version is used
6 | And a vault is created with name secrets-del-
7 | And a secret client is created with the vault named secrets-del-
8 | And secrets with - prefix are created valued abc123
9 | And secrets with - prefix are deleted
10 | When the deleted secret properties are listed
11 | Then the listed deleted secrets are matching the ones deleted before
12 |
13 | Examples:
14 | | api | index | count | secretName |
15 | | 7.2 | 01 | 1 | listSecret |
16 | | 7.3 | 02 | 1 | listSecret |
17 | | 7.3 | 03 | 2 | list-secret-name |
18 | | 7.3 | 04 | 3 | listSecret |
19 | | 7.3 | 05 | 5 | list-secret-name |
20 | | 7.3 | 06 | 25 | listSecret |
21 | | 7.3 | 07 | 42 | list-secret-name |
22 | | 7.4 | 08 | 5 | list-secret-name |
23 | | 7.5 | 09 | 5 | list-secret-name |
24 | | 7.6 | 10 | 5 | list-secret-name |
25 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/mapper/v7_3/key/RsaPrivateKeyToJsonWebKeyImportRequestConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.mapper.v7_3.key;
2 |
3 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.constants.KeyType;
4 | import com.github.nagyesta.lowkeyvault.model.v7_2.key.request.JsonWebKeyImportRequest;
5 | import lombok.NonNull;
6 | import org.springframework.core.convert.converter.Converter;
7 |
8 | import java.security.interfaces.RSAPrivateCrtKey;
9 |
10 | public class RsaPrivateKeyToJsonWebKeyImportRequestConverter
11 | implements Converter {
12 |
13 | @Override
14 | public JsonWebKeyImportRequest convert(final @NonNull RSAPrivateCrtKey source) {
15 | final var importRequest = new JsonWebKeyImportRequest();
16 | importRequest.setKeyType(KeyType.RSA);
17 | importRequest.setN(source.getModulus().toByteArray());
18 | importRequest.setE(source.getPublicExponent().toByteArray());
19 | importRequest.setD(source.getPrivateExponent().toByteArray());
20 | importRequest.setP(source.getPrimeP().toByteArray());
21 | importRequest.setQ(source.getPrimeQ().toByteArray());
22 | importRequest.setDq(source.getPrimeExponentQ().toByteArray());
23 | importRequest.setDp(source.getPrimeExponentP().toByteArray());
24 | importRequest.setQi(source.getCrtCoefficient().toByteArray());
25 | return importRequest;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lowkey-vault-app/src/main/java/com/github/nagyesta/lowkeyvault/model/v7_3/certificate/DeletedKeyVaultCertificateModel.java:
--------------------------------------------------------------------------------
1 | package com.github.nagyesta.lowkeyvault.model.v7_3.certificate;
2 |
3 | import com.fasterxml.jackson.annotation.JsonInclude;
4 | import com.fasterxml.jackson.annotation.JsonProperty;
5 | import com.github.nagyesta.lowkeyvault.model.common.DeletedModel;
6 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsDeserializer;
7 | import com.github.nagyesta.lowkeyvault.model.json.util.EpochSecondsSerializer;
8 | import lombok.Data;
9 | import lombok.EqualsAndHashCode;
10 | import tools.jackson.databind.annotation.JsonDeserialize;
11 | import tools.jackson.databind.annotation.JsonSerialize;
12 |
13 | import java.time.OffsetDateTime;
14 |
15 | @Data
16 | @EqualsAndHashCode(callSuper = true)
17 | @JsonInclude(JsonInclude.Include.NON_NULL)
18 | public class DeletedKeyVaultCertificateModel
19 | extends KeyVaultCertificateModel implements DeletedModel {
20 |
21 | @JsonProperty("recoveryId")
22 | private String recoveryId;
23 | @JsonProperty("deletedDate")
24 | @JsonSerialize(using = EpochSecondsSerializer.class)
25 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
26 | private OffsetDateTime deletedDate;
27 | @JsonProperty("scheduledPurgeDate")
28 | @JsonSerialize(using = EpochSecondsSerializer.class)
29 | @JsonDeserialize(using = EpochSecondsDeserializer.class)
30 | private OffsetDateTime scheduledPurgeDate;
31 |
32 | }
33 |
--------------------------------------------------------------------------------