Skip to content

Commit

Permalink
Basic 7.5 API support (#875)
Browse files Browse the repository at this point in the history
- Adds new API version constant
- Adds 7.5 Controllers
- Adds new test cases
- Updates documentation

Resolves #873
{minor}

Signed-off-by: Esta Nagy <nagyesta@gmail.com>
  • Loading branch information
nagyesta committed Feb 27, 2024
1 parent cbd6533 commit 9cfe2fa
Show file tree
Hide file tree
Showing 56 changed files with 5,555 additions and 11 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Lowkey Vault is far from supporting all Azure Key Vault features. The list suppo

### Keys

- API version supported: ```7.2```, partially ```7.3```, ```7.4```
- API version supported: ```7.2```, partially ```7.3```, ```7.4```, ```7.5```
- Create key (```RSA```, ```EC```, ```OCT```)
- Including metadata
- Import key (```RSA```, ```EC```, ```OCT```)
Expand Down Expand Up @@ -128,7 +128,7 @@ Lowkey Vault is far from supporting all Azure Key Vault features. The list suppo

### Secrets

- API version supported: ```7.2```, ```7.3```, ```7.4```
- API version supported: ```7.2```, ```7.3```, ```7.4```, ```7.5```
- Set secret
- Including metadata
- Get available secret versions
Expand All @@ -147,7 +147,7 @@ Lowkey Vault is far from supporting all Azure Key Vault features. The list suppo

### Certificates

- API version supported: ```7.3```, ```7.4```
- API version supported: ```7.3```, ```7.4```, ```7.5```
- Create certificate
- Self-signed only
- Using `PKCS12` (`.pfx`) or `PEM` (`.pem`) formats
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public interface ApiVersionAware {
/**
* Supported API version collection containing all 7.3+ versions.
*/
SortedSet<String> V7_3_AND_LATER = new TreeSet<>(Set.of(ApiConstants.V_7_3, ApiConstants.V_7_4));
SortedSet<String> V7_3_AND_LATER = new TreeSet<>(Set.of(ApiConstants.V_7_3, ApiConstants.V_7_4, ApiConstants.V_7_5));
/**
* Supported API version collection containing all versions (7.2, 7.3 and 7.4).
* Supported API version collection containing all versions (7.2, 7.3, 7.4 and 7.5).
*/
SortedSet<String> ALL_VERSIONS = new TreeSet<>(Set.of(ApiConstants.V_7_2, ApiConstants.V_7_3, ApiConstants.V_7_4));
SortedSet<String> ALL_VERSIONS = new TreeSet<>(Set.of(ApiConstants.V_7_2, ApiConstants.V_7_3, ApiConstants.V_7_4, ApiConstants.V_7_5));

SortedSet<String> supportedVersions();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.github.nagyesta.lowkeyvault.controller.v7_5;

import com.github.nagyesta.lowkeyvault.controller.common.CommonCertificateBackupRestoreController;
import com.github.nagyesta.lowkeyvault.mapper.common.registry.CertificateConverterRegistry;
import com.github.nagyesta.lowkeyvault.model.common.ApiConstants;
import com.github.nagyesta.lowkeyvault.model.common.backup.CertificateBackupModel;
import com.github.nagyesta.lowkeyvault.model.v7_3.certificate.KeyVaultCertificateModel;
import com.github.nagyesta.lowkeyvault.service.vault.VaultService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

import static com.github.nagyesta.lowkeyvault.model.common.ApiConstants.API_VERSION_7_5;
import static com.github.nagyesta.lowkeyvault.model.common.ApiConstants.V_7_5;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@Slf4j
@RestController
@Validated
@DependsOn({"certificateBackupConverter", "certificateModelConverter"})
@Component("CertificateBackupRestoreControllerV75")
public class CertificateBackupRestoreController extends CommonCertificateBackupRestoreController {

@Autowired
public CertificateBackupRestoreController(
@NonNull final CertificateConverterRegistry registry, @NonNull final VaultService vaultService) {
super(registry, vaultService);
}

@Override
@PostMapping(value = {"/certificates/{certificateName}/backup", "/certificates/{certificateName}/backup/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<CertificateBackupModel> backup(@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.backup(certificateName, baseUri);
}

@Override
@PostMapping(value = {"/certificates/restore", "/certificates/restore/"},
params = API_VERSION_7_5,
consumes = APPLICATION_JSON_VALUE,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultCertificateModel> restore(@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@Valid @RequestBody final CertificateBackupModel certificateBackupModel) {
return super.restore(baseUri, certificateBackupModel);
}

@Override
protected String apiVersion() {
return V_7_5;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package com.github.nagyesta.lowkeyvault.controller.v7_5;

import com.github.nagyesta.lowkeyvault.controller.common.CommonCertificateController;
import com.github.nagyesta.lowkeyvault.mapper.common.registry.CertificateConverterRegistry;
import com.github.nagyesta.lowkeyvault.model.common.ApiConstants;
import com.github.nagyesta.lowkeyvault.model.common.KeyVaultItemListModel;
import com.github.nagyesta.lowkeyvault.model.v7_3.certificate.*;
import com.github.nagyesta.lowkeyvault.service.vault.VaultService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

import static com.github.nagyesta.lowkeyvault.model.common.ApiConstants.API_VERSION_7_5;
import static com.github.nagyesta.lowkeyvault.model.common.ApiConstants.V_7_5;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@Slf4j
@RestController
@Validated
@Component("CertificateControllerV75")
public class CertificateController extends CommonCertificateController {
@Autowired
public CertificateController(@NonNull final CertificateConverterRegistry registry, @NonNull final VaultService vaultService) {
super(registry, vaultService);
}

@Override
@PostMapping(
value = {"/certificates/{certificateName}/create", "/certificates/{certificateName}/create/"},
params = API_VERSION_7_5,
consumes = APPLICATION_JSON_VALUE,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultPendingCertificateModel> create(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@Valid @RequestBody final CreateCertificateRequest request) {
return super.create(certificateName, baseUri, request);
}

@Override
@PostMapping(
value = {"/certificates/{certificateName}/import", "/certificates/{certificateName}/import/"},
params = API_VERSION_7_5,
consumes = APPLICATION_JSON_VALUE,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultCertificateModel> importCertificate(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@Valid @RequestBody final CertificateImportRequest request) {
return super.importCertificate(certificateName, baseUri, request);
}

@Override
@GetMapping(
value = {"/certificates/{certificateName}", "/certificates/{certificateName}/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultCertificateModel> get(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.get(certificateName, baseUri);
}

@Override
@GetMapping(
value = {"/certificates/{certificateName}/{certificateVersion}", "/certificates/{certificateName}/{certificateVersion}/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultCertificateModel> getWithVersion(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@PathVariable @Valid @Pattern(regexp = VERSION_NAME_PATTERN) final String certificateVersion,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.getWithVersion(certificateName, certificateVersion, baseUri);
}

@Override
@DeleteMapping(
value = {"/certificates/{certificateName}", "/certificates/{certificateName}/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<DeletedKeyVaultCertificateModel> delete(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.delete(certificateName, baseUri);
}

@Override
@GetMapping(
value = {"/deletedcertificates/{certificateName}", "/deletedcertificates/{certificateName}/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<DeletedKeyVaultCertificateModel> getDeletedCertificate(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.getDeletedCertificate(certificateName, baseUri);
}

@Override
@PostMapping(
value = {"/deletedcertificates/{certificateName}/recover", "/deletedcertificates/{certificateName}/recover/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultCertificateModel> recoverDeletedCertificate(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.recoverDeletedCertificate(certificateName, baseUri);
}

@Override
@DeleteMapping(
value = {"/deletedcertificates/{certificateName}", "/deletedcertificates/{certificateName}/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<Void> purgeDeleted(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.purgeDeleted(certificateName, baseUri);
}

@Override
@GetMapping(
value = {"/certificates/{certificateName}/versions", "/certificates/{certificateName}/versions/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultItemListModel<KeyVaultCertificateItemModel>> versions(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@RequestParam(name = MAX_RESULTS_PARAM, required = false, defaultValue = DEFAULT_MAX) final int maxResults,
@RequestParam(name = SKIP_TOKEN_PARAM, required = false, defaultValue = SKIP_ZERO) final int skipToken) {
return super.versions(certificateName, baseUri, maxResults, skipToken);
}

@Override
@GetMapping(
value = {"/certificates", "/certificates/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultItemListModel<KeyVaultCertificateItemModel>> listCertificates(
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@RequestParam(name = MAX_RESULTS_PARAM, required = false, defaultValue = DEFAULT_MAX) final int maxResults,
@RequestParam(name = SKIP_TOKEN_PARAM, required = false, defaultValue = SKIP_ZERO) final int skipToken,
@RequestParam(name = INCLUDE_PENDING_PARAM, required = false, defaultValue = TRUE) final boolean includePending) {
return super.listCertificates(baseUri, maxResults, skipToken, includePending);
}

@Override
@GetMapping(
value = {"/deletedcertificates", "/deletedcertificates/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultItemListModel<DeletedKeyVaultCertificateItemModel>> listDeletedCertificates(
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@RequestParam(name = MAX_RESULTS_PARAM, required = false, defaultValue = DEFAULT_MAX) final int maxResults,
@RequestParam(name = SKIP_TOKEN_PARAM, required = false, defaultValue = SKIP_ZERO) final int skipToken,
@RequestParam(name = INCLUDE_PENDING_PARAM, required = false, defaultValue = TRUE) final boolean includePending) {
return super.listDeletedCertificates(baseUri, maxResults, skipToken, includePending);
}

@Override
@PatchMapping(
value = {"/certificates/{certificateName}/{certificateVersion}", "/certificates/{certificateName}/{certificateVersion}/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultCertificateModel> updateCertificateProperties(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@PathVariable @Valid @Pattern(regexp = VERSION_NAME_PATTERN) final String certificateVersion,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@Valid @RequestBody final UpdateCertificateRequest request) {
return super.updateCertificateProperties(certificateName, certificateVersion, baseUri, request);
}

@Override
protected String apiVersion() {
return V_7_5;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.github.nagyesta.lowkeyvault.controller.v7_5;

import com.github.nagyesta.lowkeyvault.controller.common.CommonCertificatePolicyController;
import com.github.nagyesta.lowkeyvault.mapper.common.registry.CertificateConverterRegistry;
import com.github.nagyesta.lowkeyvault.model.common.ApiConstants;
import com.github.nagyesta.lowkeyvault.model.v7_3.certificate.CertificatePolicyModel;
import com.github.nagyesta.lowkeyvault.model.v7_3.certificate.KeyVaultPendingCertificateModel;
import com.github.nagyesta.lowkeyvault.service.vault.VaultService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Pattern;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

import static com.github.nagyesta.lowkeyvault.model.common.ApiConstants.API_VERSION_7_5;
import static com.github.nagyesta.lowkeyvault.model.common.ApiConstants.V_7_5;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@Slf4j
@RestController
@Validated
@Component("CertificatePolicyControllerV75")
public class CertificatePolicyController extends CommonCertificatePolicyController {
@Autowired
public CertificatePolicyController(@NonNull final CertificateConverterRegistry registry, @NonNull final VaultService vaultService) {
super(registry, vaultService);
}

@Override
@GetMapping(value = {"/certificates/{certificateName}/pending", "/certificates/{certificateName}/pending/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultPendingCertificateModel> pendingCreate(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.pendingCreate(certificateName, baseUri);
}

@Override
@DeleteMapping(value = {"/certificates/{certificateName}/pending", "/certificates/{certificateName}/pending/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<KeyVaultPendingCertificateModel> pendingDelete(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.pendingDelete(certificateName, baseUri);
}

@Override
@GetMapping(value = {"/certificates/{certificateName}/policy", "/certificates/{certificateName}/policy/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<CertificatePolicyModel> getPolicy(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri) {
return super.getPolicy(certificateName, baseUri);
}

@Override
@PatchMapping(value = {"/certificates/{certificateName}/policy", "/certificates/{certificateName}/policy/"},
params = API_VERSION_7_5,
produces = APPLICATION_JSON_VALUE)
public ResponseEntity<CertificatePolicyModel> updatePolicy(
@PathVariable @Valid @Pattern(regexp = NAME_PATTERN) final String certificateName,
@RequestAttribute(name = ApiConstants.REQUEST_BASE_URI) final URI baseUri,
@Valid @RequestBody final CertificatePolicyModel request) {
return super.updatePolicy(certificateName, baseUri, request);
}

@Override
protected String apiVersion() {
return V_7_5;
}
}
Loading

0 comments on commit 9cfe2fa

Please sign in to comment.