Skip to content
This repository was archived by the owner on Apr 10, 2024. It is now read-only.

Commit 57859ec

Browse files
authored
feat: certs are generate from java (#11)
1 parent 88acf44 commit 57859ec

File tree

4 files changed

+80
-18
lines changed

4 files changed

+80
-18
lines changed

pom.xml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<commons-compress.version>1.22</commons-compress.version>
2828
<google.cloud.libraries.version>26.9.0</google.cloud.libraries.version>
2929
<commons-io.version>2.11.0</commons-io.version>
30+
<bouncycastle.version>1.72</bouncycastle.version>
3031
</properties>
3132

3233
<dependencyManagement>
@@ -102,10 +103,13 @@
102103
<version>${assertj.version}</version>
103104
<scope>test</scope>
104105
</dependency>
106+
<dependency>
107+
<groupId>org.bouncycastle</groupId>
108+
<artifactId>bcpkix-jdk18on</artifactId>
109+
<version>${bouncycastle.version}</version>
110+
</dependency>
105111
</dependencies>
106-
107-
108-
112+
109113
<build>
110114
<plugins>
111115
<plugin>

src/main/java/com/csviri/jenvtest/APIServer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public APIServer(APIServerConfig config) {
3535
public void start() {
3636
log.debug("Stating API Server. Using jenvtest dir: {}", config.getJenvtestDirectory());
3737
binaryManager.initAndDownloadIfRequired();
38+
certManager.createCertificatesIfNeeded();
3839
prepareLogDirectory();
3940
etcdProcessManager.cleanEtcdData();
4041
etcdProcessManager.startEtcd();

src/main/java/com/csviri/jenvtest/APIServerProcessManager.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ public APIServerProcessManager(CertManager certManager, BinaryManager binaryMana
2626

2727

2828
public void startApiServer() {
29-
certManager.ensureAPIServerCertificates();
3029
var apiServerBinary = binaryManager.binaries().getApiServer();
3130
try {
3231
if (!apiServerBinary.exists()) {

src/main/java/com/csviri/jenvtest/CertManager.java

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
11
package com.csviri.jenvtest;
22

3+
import org.bouncycastle.asn1.x500.X500Name;
4+
import org.bouncycastle.asn1.x509.Extension;
5+
import org.bouncycastle.asn1.x509.GeneralName;
6+
import org.bouncycastle.asn1.x509.GeneralNames;
7+
import org.bouncycastle.cert.X509CertificateHolder;
8+
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
9+
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
10+
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
11+
import org.bouncycastle.operator.ContentSigner;
12+
import org.bouncycastle.operator.OperatorCreationException;
13+
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
314
import org.slf4j.Logger;
415
import org.slf4j.LoggerFactory;
516

617
import java.io.File;
18+
import java.io.FileWriter;
719
import java.io.IOException;
20+
import java.math.BigInteger;
21+
import java.security.KeyPair;
22+
import java.security.KeyPairGenerator;
23+
import java.security.NoSuchAlgorithmException;
24+
import java.security.cert.CertificateException;
25+
import java.security.cert.X509Certificate;
26+
import java.time.Instant;
27+
import java.time.temporal.ChronoUnit;
28+
import java.util.Date;
829

9-
// todo impl in java
1030
public class CertManager {
1131

1232
private static final Logger log = LoggerFactory.getLogger(CertManager.class);
@@ -23,7 +43,7 @@ public CertManager(String jenvtestDir) {
2343
this.jenvtestDir = jenvtestDir;
2444
}
2545

26-
public void ensureAPIServerCertificates() {
46+
public void createCertificatesIfNeeded() {
2747
try {
2848
generateAPIServerCertificates();
2949
generateUserCertificates();
@@ -40,13 +60,16 @@ private void generateAPIServerCertificates() throws IOException, InterruptedExce
4060
return;
4161
}
4262
log.debug("Generating API Server certificates");
43-
Process process = new ProcessBuilder("openssl", "req", "-nodes", "-x509", "-sha256", "-newkey", "rsa:4096", "-keyout", key.getPath(), "-out",
44-
cert.getPath(),
45-
"-days", "356", "-subj", "/CN=example.org",
46-
"-addext", "subjectAltName = IP:127.0.0.1,DNS:kubernetes," +
47-
"DNS:kubernetes.default,DNS:kubernetes.default.svc,DNS:kubernetes.default.svc.cluster,DNS:kubernetes.default.svc.cluster.local")
48-
.start();
49-
process.waitFor();
63+
generateKeyAndCertificate("CN=example.org", new File(jenvtestDir, API_SERVER_KEY_NAME),
64+
new File(jenvtestDir, API_SERVER_CERT_NAME),
65+
new GeneralName(GeneralName.iPAddress, "127.0.0.1"),
66+
dns("kubernetes"), dns("kubernetes.default"),
67+
dns("kubernetes.default.svc"), dns("kubernetes.default.svc.cluster"),
68+
dns("kubernetes.default.svc.cluster.local"));
69+
}
70+
71+
private GeneralName dns(String dns) {
72+
return new GeneralName(GeneralName.dNSName, dns);
5073
}
5174

5275
private void generateUserCertificates() throws IOException, InterruptedException {
@@ -56,11 +79,46 @@ private void generateUserCertificates() throws IOException, InterruptedException
5679
return;
5780
}
5881
log.debug("Generating Client certificates");
59-
var process = new ProcessBuilder("openssl", "req", "-nodes", "-x509", "-sha256", "-newkey",
60-
"rsa:4096", "-keyout", key.getPath(), "-out", cert.getPath(), "-days", "356", "-subj",
61-
"/O=system:masters/CN=jenvtest")
62-
.start();
63-
process.waitFor();
82+
generateKeyAndCertificate("O=system:masters,CN=jenvtest", new File(jenvtestDir, CLIENT_KEY_NAME),
83+
new File(jenvtestDir, CLIENT_CERT_NAME));
84+
}
85+
86+
87+
private static void generateKeyAndCertificate(String dirName, File keyFile, File certFile, GeneralName... generalNames) {
88+
try {
89+
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
90+
91+
KeyPair certKeyPair = keyGen.generateKeyPair();
92+
X500Name name = new X500Name(dirName);
93+
// If you issue more than just test certificates, you might want a decent serial number schema ^.^
94+
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
95+
Instant validFrom = Instant.now();
96+
Instant validUntil = validFrom.plus(365, ChronoUnit.DAYS);
97+
98+
JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
99+
name,
100+
serialNumber,
101+
Date.from(validFrom), Date.from(validUntil),
102+
name, certKeyPair.getPublic());
103+
104+
if (generalNames.length > 0) {
105+
builder.addExtension(Extension.subjectAlternativeName, false,
106+
new GeneralNames(generalNames));
107+
}
108+
109+
// Finally, sign the certificate:
110+
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").build(certKeyPair.getPrivate());
111+
X509CertificateHolder certHolder = builder.build(signer);
112+
X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);
113+
114+
try (FileWriter certWriter = new FileWriter(certFile); JcaPEMWriter certPemWriter = new JcaPEMWriter(certWriter);
115+
FileWriter keyWriter = new FileWriter(keyFile); JcaPEMWriter keyPemWriter = new JcaPEMWriter(keyWriter)) {
116+
certPemWriter.writeObject(cert);
117+
keyPemWriter.writeObject(certKeyPair.getPrivate());
118+
}
119+
} catch (NoSuchAlgorithmException | CertificateException | IOException | OperatorCreationException e) {
120+
throw new JenvtestException(e);
121+
}
64122
}
65123

66124
public String getClientCertPath() {

0 commit comments

Comments
 (0)