Skip to content

Commit

Permalink
Add format selectable versions of getters for CA & CRL
Browse files Browse the repository at this point in the history
  • Loading branch information
kdubb committed Sep 8, 2021
1 parent d1e9534 commit 1ed5458
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import java.time.OffsetDateTime;
import java.util.List;

import io.quarkus.vault.pki.CRLData;
import io.quarkus.vault.pki.CertificateData;
import io.quarkus.vault.pki.ConfigCRLOptions;
import io.quarkus.vault.pki.ConfigURLsOptions;
import io.quarkus.vault.pki.DataFormat;
import io.quarkus.vault.pki.GenerateCertificateOptions;
import io.quarkus.vault.pki.GenerateIntermediateCSROptions;
import io.quarkus.vault.pki.GenerateRootOptions;
Expand All @@ -32,6 +34,14 @@ public interface VaultPKISecretEngine {
*/
CertificateData.PEM getCertificateAuthority();

/**
* Retrieves the engine's CA certificate.
*
* @param format Format of the returned certificate data.
* @return Certificate authority certificate.
*/
CertificateData getCertificateAuthority(DataFormat format);

/**
* Configures the engine's CA.
*
Expand Down Expand Up @@ -79,7 +89,15 @@ public interface VaultPKISecretEngine {
*
* @return Certificate revocation list.
*/
String getCertificateRevocationList();
CRLData.PEM getCertificateRevocationList();

/**
* Retrieves the engine's CRL.
*
* @param format Format of the returned crl data.
* @return Certificate revocation list.
*/
CRLData getCertificateRevocationList(DataFormat format);

/**
* Forces a rotation of the associated CRL.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package io.quarkus.vault.pki;

public interface CRLData {

/**
* Format of {@link #getData()} property.
*/
DataFormat getFormat();

/**
* Data in {@link DataFormat#PEM} or {@link DataFormat#DER} format.
*
* @see #getFormat()
*/
Object getData();

/**
* {@link DataFormat#DER} implementation of {@link CRLData}
*/
class DER implements CRLData {

private final byte[] derData;

public DER(byte[] derData) {
this.derData = derData;
}

@Override
public DataFormat getFormat() {
return DataFormat.DER;
}

@Override
public byte[] getData() {
return derData;
}
}

/**
* {@link DataFormat#PEM} implementation of {@link CRLData}
*/
class PEM implements CRLData {

private final String pemData;

public PEM(String pemData) {
this.pemData = pemData;
}

@Override
public DataFormat getFormat() {
return DataFormat.PEM;
}

@Override
public String getData() {
return pemData;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toList;

import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Base64;
Expand All @@ -17,6 +18,7 @@

import io.quarkus.vault.VaultException;
import io.quarkus.vault.VaultPKISecretEngine;
import io.quarkus.vault.pki.CRLData;
import io.quarkus.vault.pki.CSRData;
import io.quarkus.vault.pki.CertificateData;
import io.quarkus.vault.pki.CertificateExtendedKeyUsage;
Expand Down Expand Up @@ -69,6 +71,7 @@
import io.quarkus.vault.runtime.client.dto.pki.VaultPKISignIntermediateCABody;
import io.quarkus.vault.runtime.client.dto.pki.VaultPKITidyBody;
import io.quarkus.vault.runtime.client.secretengine.VaultInternalPKISecretEngine;
import io.vertx.mutiny.core.buffer.Buffer;

@ApplicationScoped
public class VaultPKIManager implements VaultPKISecretEngine {
Expand Down Expand Up @@ -99,10 +102,19 @@ private String getToken() {

@Override
public CertificateData.PEM getCertificateAuthority() {
VaultPKICertificateResult internalResult = vaultInternalPKISecretEngine.getCertificate(getToken(), mount, "ca");
checkDataValid(internalResult);
return (CertificateData.PEM) getCertificateAuthority(DataFormat.PEM);
}

return new CertificateData.PEM(internalResult.data.certificate);
@Override
public CertificateData getCertificateAuthority(DataFormat format) {
String vaultFormat = format.name().toLowerCase(Locale.ROOT);
Buffer data = vaultInternalPKISecretEngine.getCertificateAuthority(getToken(), mount, vaultFormat);

switch (format) {
case PEM: return new CertificateData.PEM(data.toString(StandardCharsets.UTF_8));
case DER: return new CertificateData.DER(data.getBytes());
default: throw new VaultException("Unsupported Data Format");
}
}

@Override
Expand Down Expand Up @@ -160,18 +172,26 @@ public ConfigCRLOptions readCRLConfig() {

@Override
public String getCertificateAuthorityChain() {
VaultPKICertificateResult internalResult = vaultInternalPKISecretEngine.getCertificate(getToken(), mount, "ca_chain");
checkDataValid(internalResult);
Buffer data = vaultInternalPKISecretEngine.getCertificateAuthorityChain(getToken(), mount);

return internalResult.data.certificate;
return data.toString(StandardCharsets.UTF_8);
}

@Override
public String getCertificateRevocationList() {
VaultPKICertificateResult internalResult = vaultInternalPKISecretEngine.getCertificate(getToken(), mount, "crl");
checkDataValid(internalResult);
public CRLData.PEM getCertificateRevocationList() {
return (CRLData.PEM) getCertificateRevocationList(DataFormat.PEM);
}

return internalResult.data.certificate;
@Override
public CRLData getCertificateRevocationList(DataFormat format) {
String vaultFormat = format.name().toLowerCase(Locale.ROOT);
Buffer data = vaultInternalPKISecretEngine.getCertificateRevocationList(getToken(), mount, vaultFormat);

switch (format) {
case PEM: return new CRLData.PEM(data.toString(StandardCharsets.UTF_8));
case DER: return new CRLData.DER(data.getBytes());
default: throw new VaultException("Unsupported Data Format");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.Map;

import io.vertx.mutiny.core.buffer.Buffer;

public interface VaultClient {

String X_VAULT_TOKEN = "X-Vault-Token";
Expand Down Expand Up @@ -30,6 +32,8 @@ public interface VaultClient {

<T> T get(String path, Map<String, String> queryParams, Class<T> resultClass);

Buffer get(String path, String token);

int head(String path);

int head(String path, Map<String, String> queryParams);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,15 @@ public <T> T get(String path, Map<String, String> queryParams, Class<T> resultCl
return exec(request, resultClass);
}

public Buffer get(String path, String token) {
final HttpRequest<Buffer> request = builder(path, token).method(HttpMethod.GET);
final HttpResponse<Buffer> response = request.send().await().atMost(getRequestTimeout());
if (response.statusCode() != 200) {
throwVaultException(response);
}
return response.body();
}

public int head(String path) {
final HttpRequest<Buffer> request = builder(path).method(HttpMethod.HEAD);
return exec(request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.quarkus.vault.runtime.client.dto.pki.VaultPKISignCertificateRequestResult;
import io.quarkus.vault.runtime.client.dto.pki.VaultPKISignIntermediateCABody;
import io.quarkus.vault.runtime.client.dto.pki.VaultPKITidyBody;
import io.vertx.mutiny.core.buffer.Buffer;

@Singleton
public class VaultInternalPKISecretEngine extends VaultInternalBase {
Expand All @@ -35,6 +36,23 @@ private String getPath(String mount, String path) {
return mount + "/" + path;
}

public Buffer getCertificateAuthority(String token, String mount, String format) {
return getRaw(token, mount, "ca", format);
}

public Buffer getCertificateRevocationList(String token, String mount, String format) {
return getRaw(token, mount, "crl", format);
}

public Buffer getCertificateAuthorityChain(String token, String mount) {
return getRaw(token, mount, "ca_chain", null);
}

private Buffer getRaw(String token, String mount, String path, String format) {
String suffix = format != null ? "/" + format : "";
return vaultClient.get(getPath(mount, path + suffix), token);
}

public VaultPKICertificateResult getCertificate(String token, String mount, String serial) {
return vaultClient.get(getPath(mount, "cert/" + serial), token, VaultPKICertificateResult.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import javax.inject.Inject;

import io.quarkus.vault.pki.CRLData;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.AfterEach;
Expand Down Expand Up @@ -411,7 +412,7 @@ public void testSetSignedIntermediaCA() throws Exception {
// Set signed intermediate CA into "pki2"
pkiSecretEngine2.setSignedIntermediateCA((String) result.certificate.getData());

// Get CA cert and check subject
// Get CA cert and check subject (PEM)
X509CertificateHolder certificate = (X509CertificateHolder) new PEMParser(
new StringReader(pkiSecretEngine2.getCertificateAuthority().getData())).readObject();

Expand Down Expand Up @@ -886,9 +887,13 @@ public void testGetCRL() {
// Revoke cert
pkiSecretEngine.revokeCertificate(certSerialNumber);

// Test CRL get
String pemCRL = pkiSecretEngine.getCertificateRevocationList();
assertDoesNotThrow(() -> (X509CRLHolder) new PEMParser(new StringReader(pemCRL)).readObject());
// Test CRL get (PEM)
CRLData.PEM pemCRL = pkiSecretEngine.getCertificateRevocationList();
assertDoesNotThrow(() -> (X509CRLHolder) new PEMParser(new StringReader(pemCRL.getData())).readObject());

// Test CRL get (DER)
CRLData.DER derCRL = (CRLData.DER) pkiSecretEngine.getCertificateRevocationList(DataFormat.DER);
assertDoesNotThrow(() -> new X509CRLHolder(derCRL.getData()));
}

@Test
Expand Down Expand Up @@ -970,11 +975,13 @@ public void testConfigureCA() throws Exception {
.configCertificateAuthority(
generatedRootCertificate.certificate.getData() + "\n" + generatedRootCertificate.privateKey.getData());

// Get CA cert and check subject
X509CertificateHolder certificate = (X509CertificateHolder) new PEMParser(
new StringReader(pkiSecretEngine2.getCertificateAuthority().getData())).readObject();
// Get CA cert and check subject (PEM)
CertificateData.PEM pemCAData = pkiSecretEngine2.getCertificateAuthority();
assertEquals("CN=root.example.com", pemCAData.getCertificate().getSubjectX500Principal().toString());

assertEquals("CN=root.example.com", certificate.getSubject().toString());
// Get CA cert and check subject (DER)
CertificateData.DER derCAData = (CertificateData.DER) pkiSecretEngine2.getCertificateAuthority(DataFormat.DER);
assertEquals("CN=root.example.com", derCAData.getCertificate().getSubjectX500Principal().toString());
}

@Test
Expand Down

0 comments on commit 1ed5458

Please sign in to comment.