summaryrefslogtreecommitdiffstats
path: root/node-admin
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorn.christian@seime.no>2018-03-21 11:37:21 +0100
committerGitHub <noreply@github.com>2018-03-21 11:37:21 +0100
commitde021c008d317b75b59e1d76624cbcb14fe18f27 (patch)
tree80e0003130e28500d2b7746aa165eeac548094cb /node-admin
parentdb9aff7fd0015b37b9cb034c6c798e90f231fa5f (diff)
parent8d38ad85f091a88abb8269bae8372ca0444dcabf (diff)
Merge pull request #5386 from vespa-engine/bjorncs/certificate-builder
Bjorncs/certificate builder
Diffstat (limited to 'node-admin')
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/SslConfigServerApiImpl.java4
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CertificateSerializedPayload.java13
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresher.java51
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CsrSerializedPayload.java21
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresherTest.java36
5 files changed, 39 insertions, 86 deletions
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/SslConfigServerApiImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/SslConfigServerApiImpl.java
index 110dbe9c9b3..bdd4a8c0b9d 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/SslConfigServerApiImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/SslConfigServerApiImpl.java
@@ -7,11 +7,9 @@ import com.yahoo.vespa.hosted.node.admin.component.Environment;
import com.yahoo.vespa.hosted.node.admin.configserver.certificate.ConfigServerKeyStoreRefresher;
import com.yahoo.vespa.hosted.node.admin.util.KeyStoreOptions;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
-import java.security.Security;
import java.util.Collections;
import java.util.Optional;
@@ -28,8 +26,6 @@ public class SslConfigServerApiImpl implements ConfigServerApi {
private final Optional<ConfigServerKeyStoreRefresher> keyStoreRefresher;
public SslConfigServerApiImpl(Environment environment) {
- Security.addProvider(new BouncyCastleProvider());
-
this.environment = environment;
// At this point we don't know the state of the keystore, it may not exist at all, or the keystore
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CertificateSerializedPayload.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CertificateSerializedPayload.java
index e7148754fde..94bff3c9633 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CertificateSerializedPayload.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CertificateSerializedPayload.java
@@ -7,13 +7,9 @@ import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import org.bouncycastle.cert.X509CertificateHolder;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.openssl.PEMParser;
+import com.yahoo.vespa.athenz.tls.X509CertificateUtils;
import java.io.IOException;
-import java.io.StringReader;
-import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
@@ -58,12 +54,7 @@ public class CertificateSerializedPayload {
@Override
public X509Certificate deserialize(
JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
- try (PEMParser pemParser = new PEMParser(new StringReader(jsonParser.getValueAsString()))) {
- X509CertificateHolder x509CertificateHolder = (X509CertificateHolder) pemParser.readObject();
- return new JcaX509CertificateConverter().getCertificate(x509CertificateHolder);
- } catch (CertificateException e) {
- throw new RuntimeException("Failed to deserialize X509Certificate", e);
- }
+ return X509CertificateUtils.fromPem(jsonParser.getValueAsString());
}
}
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresher.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresher.java
index a9db96c2a77..beb1acd9e5a 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresher.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresher.java
@@ -3,24 +3,19 @@ package com.yahoo.vespa.hosted.node.admin.configserver.certificate;
import com.yahoo.log.LogLevel;
import com.yahoo.net.HostName;
+import com.yahoo.vespa.athenz.tls.KeyAlgorithm;
import com.yahoo.vespa.athenz.tls.KeyStoreBuilder;
+import com.yahoo.vespa.athenz.tls.KeyUtils;
+import com.yahoo.vespa.athenz.tls.Pkcs10Csr;
+import com.yahoo.vespa.athenz.tls.Pkcs10CsrBuilder;
+import com.yahoo.vespa.athenz.tls.SignatureAlgorithm;
import com.yahoo.vespa.hosted.node.admin.configserver.ConfigServerApi;
import com.yahoo.vespa.hosted.node.admin.util.KeyStoreOptions;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.OperatorCreationException;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
-import org.bouncycastle.pkcs.PKCS10CertificationRequest;
-import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
-
-import java.io.IOException;
+
+import javax.security.auth.x500.X500Principal;
import java.security.KeyPair;
-import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Clock;
import java.util.concurrent.Executors;
@@ -40,7 +35,7 @@ public class ConfigServerKeyStoreRefresher {
private static final Logger logger = Logger.getLogger(ConfigServerKeyStoreRefresher.class.getName());
private static final String KEY_STORE_ALIAS = "alias";
static final long MINIMUM_SECONDS_BETWEEN_REFRESH_RETRY = 3600;
- static final String SIGNER_ALGORITHM = "SHA256withRSA";
+ static final SignatureAlgorithm SIGNER_ALGORITHM = SignatureAlgorithm.SHA256_WITH_RSA;
static final String CONFIG_SERVER_CERTIFICATE_SIGNING_PATH = "/athenz/v1/provider/sign";
private final ScheduledExecutorService executor;
@@ -101,12 +96,11 @@ public class ConfigServerKeyStoreRefresher {
} while (!executor.isTerminated());
}
- public boolean refreshKeyStoreIfNeeded() throws
- IOException, NoSuchAlgorithmException, OperatorCreationException, CertificateException, KeyStoreException, NoSuchProviderException {
+ public boolean refreshKeyStoreIfNeeded() {
if (!shouldRefreshCertificate()) return false;
KeyPair keyPair = generateKeyPair();
- PKCS10CertificationRequest csr = generateCsr(keyPair, hostname);
+ Pkcs10Csr csr = generateCsr(keyPair, hostname);
X509Certificate certificate = sendCsr(csr);
storeCertificate(keyPair, certificate);
@@ -141,8 +135,7 @@ public class ConfigServerKeyStoreRefresher {
* well before the certificate actually expires so that we have enough time to retry without
* overloading config server.
*/
- private long getSecondsUntilCertificateShouldBeRefreshed()
- throws NoSuchAlgorithmException, CertificateException, NoSuchProviderException, KeyStoreException, IOException {
+ private long getSecondsUntilCertificateShouldBeRefreshed() throws KeyStoreException{
X509Certificate cert = getConfigServerCertificate();
long notBefore = cert.getNotBefore().getTime() / 1000;
long notAfter = cert.getNotAfter().getTime() / 1000;
@@ -152,12 +145,11 @@ public class ConfigServerKeyStoreRefresher {
return Math.max(0, notBefore + thirdOfLifetime - now);
}
- X509Certificate getConfigServerCertificate() throws NoSuchAlgorithmException, CertificateException, NoSuchProviderException, KeyStoreException, IOException {
+ X509Certificate getConfigServerCertificate() throws KeyStoreException {
return (X509Certificate) keyStoreOptions.loadKeyStore().getCertificate(KEY_STORE_ALIAS);
}
- private void storeCertificate(KeyPair keyPair, X509Certificate certificate)
- throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, NoSuchProviderException {
+ private void storeCertificate(KeyPair keyPair, X509Certificate certificate) {
keyStoreOptions.path.getParent().toFile().mkdirs();
KeyStore keyStore = KeyStoreBuilder.withType(keyStoreOptions.keyStoreType)
@@ -167,7 +159,7 @@ public class ConfigServerKeyStoreRefresher {
keyStoreOptions.storeKeyStore(keyStore);
}
- private X509Certificate sendCsr(PKCS10CertificationRequest csr) {
+ private X509Certificate sendCsr(Pkcs10Csr csr) {
CertificateSerializedPayload certificateSerializedPayload = configServerApi.post(
CONFIG_SERVER_CERTIFICATE_SIGNING_PATH,
new CsrSerializedPayload(csr),
@@ -176,17 +168,12 @@ public class ConfigServerKeyStoreRefresher {
return certificateSerializedPayload.certificate;
}
- static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
- KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
- rsa.initialize(2048);
- return rsa.genKeyPair();
+ static KeyPair generateKeyPair() {
+ return KeyUtils.generateKeypair(KeyAlgorithm.RSA, 2048);
}
- private static PKCS10CertificationRequest generateCsr(KeyPair keyPair, String commonName)
- throws NoSuchAlgorithmException, OperatorCreationException {
- ContentSigner signer = new JcaContentSignerBuilder(SIGNER_ALGORITHM).build(keyPair.getPrivate());
-
- return new JcaPKCS10CertificationRequestBuilder(new X500Name("CN=" + commonName), keyPair.getPublic())
- .build(signer);
+ private static Pkcs10Csr generateCsr(KeyPair keyPair, String commonName) {
+ return Pkcs10CsrBuilder.fromKeypair(new X500Principal("CN=" + commonName), keyPair, SIGNER_ALGORITHM)
+ .build();
}
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CsrSerializedPayload.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CsrSerializedPayload.java
index aa83fdc9e22..34b190b546c 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CsrSerializedPayload.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/CsrSerializedPayload.java
@@ -7,12 +7,10 @@ import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
-import org.bouncycastle.pkcs.PKCS10CertificationRequest;
-import org.bouncycastle.util.io.pem.PemObject;
+import com.yahoo.vespa.athenz.tls.Pkcs10Csr;
+import com.yahoo.vespa.athenz.tls.Pkcs10CsrUtils;
import java.io.IOException;
-import java.io.StringWriter;
/**
* Contains PEM formatted Certificate Signing Request (CSR)
@@ -23,10 +21,10 @@ import java.io.StringWriter;
public class CsrSerializedPayload {
@JsonProperty("csr") @JsonSerialize(using = CertificateRequestSerializer.class)
- public final PKCS10CertificationRequest csr;
+ public final Pkcs10Csr csr;
@JsonCreator
- public CsrSerializedPayload(@JsonProperty("csr") PKCS10CertificationRequest csr) {
+ public CsrSerializedPayload(@JsonProperty("csr") Pkcs10Csr csr) {
this.csr = csr;
}
@@ -52,15 +50,10 @@ public class CsrSerializedPayload {
'}';
}
- public static class CertificateRequestSerializer extends JsonSerializer<PKCS10CertificationRequest> {
+ public static class CertificateRequestSerializer extends JsonSerializer<Pkcs10Csr> {
@Override
- public void serialize(
- PKCS10CertificationRequest csr, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- try (StringWriter stringWriter = new StringWriter(); JcaPEMWriter pemWriter = new JcaPEMWriter(stringWriter)) {
- pemWriter.writeObject(new PemObject("CERTIFICATE REQUEST", csr.getEncoded()));
- pemWriter.flush();
- gen.writeString(stringWriter.toString());
- }
+ public void serialize(Pkcs10Csr csr, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ gen.writeString(Pkcs10CsrUtils.toPem(csr));
}
}
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresherTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresherTest.java
index 85684ea3bd4..69aaad210a4 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresherTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/certificate/ConfigServerKeyStoreRefresherTest.java
@@ -2,24 +2,19 @@
package com.yahoo.vespa.hosted.node.admin.configserver.certificate;
import com.yahoo.test.ManualClock;
+import com.yahoo.vespa.athenz.tls.X509CertificateBuilder;
import com.yahoo.vespa.hosted.node.admin.configserver.ConfigServerApi;
import com.yahoo.vespa.hosted.node.admin.util.KeyStoreOptions;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
-import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.bouncycastle.operator.ContentSigner;
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import java.math.BigInteger;
+import javax.security.auth.x500.X500Principal;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import java.time.Duration;
-import java.util.Date;
+import java.time.Instant;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -141,22 +136,13 @@ public class ConfigServerKeyStoreRefresherTest {
.thenThrow(exception);
}
- private X509Certificate makeCertificate(int serial) throws Exception {
- try {
- KeyPair keyPair = ConfigServerKeyStoreRefresher.generateKeyPair();
- X500Name subject = new X500Name("CN=" + commonName);
- Date notBefore = Date.from(clock.instant());
- Date notAfter = Date.from(clock.instant().plus(certificateExpiration));
-
- JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(subject,
- BigInteger.valueOf(serial), notBefore, notAfter, subject, keyPair.getPublic());
- ContentSigner sigGen = new JcaContentSignerBuilder(ConfigServerKeyStoreRefresher.SIGNER_ALGORITHM)
- .build(keyPair.getPrivate());
- return new JcaX509CertificateConverter()
- .setProvider(new BouncyCastleProvider())
- .getCertificate(certGen.build(sigGen));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ private X509Certificate makeCertificate(int serial) {
+ KeyPair keyPair = ConfigServerKeyStoreRefresher.generateKeyPair();
+ X500Principal subject = new X500Principal("CN=" + commonName);
+ Instant notBefore = clock.instant();
+ Instant notAfter = clock.instant().plus(certificateExpiration);
+
+ return X509CertificateBuilder.fromKeypair(keyPair, subject, notBefore, notAfter, ConfigServerKeyStoreRefresher.SIGNER_ALGORITHM, serial)
+ .build();
}
} \ No newline at end of file