Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -756,12 +756,12 @@ public String getUsage() {

public class CertExportCommand extends Command {

public static final String USAGE = "export-cert [--type PEM|JKS|JCEKS|PKCS12]";
public static final String USAGE = "export-cert [--type PEM|JKS|JCEKS|PKCS12|BCFKS]";
public static final String DESC = "The export-cert command exports the public certificate\n" +
"from the a gateway.jks keystore with the alias of gateway-identity.\n" +
"It will be exported to `{GATEWAY_HOME}/data/security/keystores/` with a name of `gateway-client-trust.<type>`" +
"Using the --type option you can specify which keystore type you need (default: PEM)\n" +
"NOTE: The password for the JKS, JCEKS and PKCS12 types is `changeit`.\n" +
"NOTE: The password for the JKS, JCEKS, PKCS12 and BCFKS types is `changeit`.\n" +
"It can be changed using: `keytool -storepasswd -storetype <type> -keystore gateway-client-trust.<type>`";

private GatewayConfig getGatewayConfig() {
Expand Down Expand Up @@ -808,6 +808,9 @@ public void execute() throws Exception {
} else if ("PKCS12".equalsIgnoreCase(type)) {
X509CertificateUtil.writeCertificateToPkcs12(cert, new File(keyStoreDir + "gateway-client-trust.pkcs12"));
out.println("Certificate gateway-identity has been successfully exported to: " + keyStoreDir + "gateway-client-trust.pkcs12");
} else if ("BCFKS".equalsIgnoreCase(type)) {
X509CertificateUtil.writeCertificateToBcfks(cert, new File(keyStoreDir + "gateway-client-trust.bcfks"));
out.println("Certificate gateway-identity has been successfully exported to: " + keyStoreDir + "gateway-client-trust.bcfks");
} else {
out.println("Invalid type for export file provided. Export has not been done. Please use: [PEM|JKS|JCEKS|PKCS12] default value is PEM.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public class KnoxMetadataResource {
private Set<String> pinnedTopologies;
private java.nio.file.Path pemFilePath;
private java.nio.file.Path jksFilePath;
private java.nio.file.Path bcfksFilePath;

@Context
private HttpServletRequest request;
Expand Down Expand Up @@ -147,6 +148,9 @@ public Response getPublicCertification(@QueryParam("type") @DefaultValue("pem")
} else if ("jks".equals(certType)) {
generateCertificateJks(certificateChain, config);
return generateSuccessFileDownloadResponse(jksFilePath);
} else if ("bcfks".equals(certType)) {
generateCertificateBcfks(certificateChain, config);
return generateSuccessFileDownloadResponse(bcfksFilePath);
} else {
return generateFailureFileDownloadResponse(Status.BAD_REQUEST, "Invalid certification type provided!");
}
Expand Down Expand Up @@ -208,6 +212,17 @@ private void generateCertificateJks(Certificate[] certificateChain, GatewayConfi
}
}

private void generateCertificateBcfks(Certificate[] certificateChain, GatewayConfig gatewayConfig) {
try {
if (bcfksFilePath == null || !bcfksFilePath.toFile().exists()) {
bcfksFilePath = Paths.get(gatewayConfig.getGatewaySecurityDir(), "gateway-client-trust.bcfks");
X509CertificateUtil.writeCertificatesToBcfks(certificateChain, bcfksFilePath.toFile(), null);
}
} catch (IOException | KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
LOG.failedToGeneratePublicCert("BCFKS", e.getMessage(), e);
}
}

private String getBaseGatewayUrl(GatewayConfig config) {
return request.getRequestURL().substring(0, request.getRequestURL().length() - request.getRequestURI().length()) + "/" + config.getGatewayPath();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ public static void writeCertificateToPkcs12(Certificate cert, final File file)
writeCertificateToKeyStore(cert, file, "pkcs12");
}

public static void writeCertificateToBcfks(Certificate cert, final File file)
throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
writeCertificateToKeyStore(cert, file, "bcfks");
}

public static void writeCertificatesToBcfks(Certificate[] certs, final File file, String keystorePassword)
throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
writeCertificatesToKeyStore(certs, file, "bcfks", keystorePassword);
}

/**
* Tests the X509 certificate to see if it was self-signed.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@
*/
package org.apache.knox.gateway.util;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import java.io.File;
import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
Expand All @@ -39,6 +45,35 @@

public class X509CertificateUtilTest {

@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Test
public void testWriteCertificatesToKeyStoreBCFKS() throws Exception {
Security.addProvider(new BouncyCastleProvider());
try {
// 1. Generate a self-signed certificate
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
X509Certificate cert = X509CertificateUtil.generateCertificate("CN=localhost", keyPair, 30, "SHA256withRSA");

// 2. Write it to a BCFKS keystore
File bcfksFile = temporaryFolder.newFile("test.bcfks");
X509CertificateUtil.writeCertificatesToBcfks(new Certificate[]{cert}, bcfksFile, "password");

// 3. Verify the keystore
KeyStore keyStore = KeyStore.getInstance("BCFKS");
keyStore.load(java.nio.file.Files.newInputStream(bcfksFile.toPath()), "password".toCharArray());
Assert.assertTrue(keyStore.containsAlias("gateway-identity1"));
Certificate loadedCert = keyStore.getCertificate("gateway-identity1");
Assert.assertNotNull(loadedCert);
Assert.assertEquals(cert, loadedCert);
} finally {
Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);
}
}

@Test
public void testFetchPublicCertsFromServer() throws Exception {
// 1. Generate a self-signed certificate
Expand Down
Loading