Skip to content

Instantly share code, notes, and snippets.

@lbroudoux
Last active November 23, 2021 13:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lbroudoux/1dd585c17c3303026fea9ddbedb39fea to your computer and use it in GitHub Desktop.
Save lbroudoux/1dd585c17c3303026fea9ddbedb39fea to your computer and use it in GitHub Desktop.
Self-signed #certificate with bouncycastle #java
[...]
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretBuilder;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* Holds utility methods to manage Ingress params from specification.
* @author laurent.broudoux@gmail.com
*/
public class IngressSpecUtil {
/**
* Generate a Secret holding a self-signed certificate and key for Ingress tests purposes.
* @param name The name of secret to generate
* @param labels The labels to add to Secret
* @param host The host name to generate a cert and key for.
* @return The created Secret to persist using Kube apis.
*/
public static Secret generateSelfSignedCertificateSecret(String name, Map<String, String> labels, String host) {
Security.addProvider(new BouncyCastleProvider());
X500Principal subject = new X500Principal("CN=" + host);
X500Principal signedByPrincipal = subject;
KeyPair keyPair = generateKeyPair();
KeyPair signedByKeyPair = keyPair;
long notBefore = System.currentTimeMillis();
long notAfter = notBefore + (1000L * 3600L * 24 * 365);
ASN1Encodable[] encodableAltNames = new ASN1Encodable[]{new GeneralName(GeneralName.dNSName, host)};
KeyPurposeId[] purposes = new KeyPurposeId[]{KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth};
X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(signedByPrincipal,
BigInteger.ONE, new Date(notBefore), new Date(notAfter), subject, keyPair.getPublic());
try {
certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
certBuilder.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature + KeyUsage.keyEncipherment));
certBuilder.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(purposes));
certBuilder.addExtension(Extension.subjectAlternativeName, false, new DERSequence(encodableAltNames));
final ContentSigner signer = new JcaContentSignerBuilder(("SHA256withRSA")).build(signedByKeyPair.getPrivate());
X509CertificateHolder certHolder = certBuilder.build(signer);
return new SecretBuilder()
.withNewMetadata()
.withName(name)
.addToLabels(labels)
.endMetadata()
.withType("kubernetes.io/tls")
.addToStringData("tls.key", getPrivateKeyPkcs1Pem(keyPair))
.addToStringData("tls.crt", getCertificatePem(certHolder))
.build();
} catch (Exception e) {
Logger.getLogger(IngressSpecUtil.class).error(e.getMessage());
throw new AssertionError(e.getMessage());
}
}
private static KeyPair generateKeyPair() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048, new SecureRandom());
return keyPairGenerator.generateKeyPair();
} catch (GeneralSecurityException var2) {
throw new AssertionError(var2);
}
}
[...]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment