001package com.exoreaction.xorcery.neo4j.browser;
002
003import com.exoreaction.xorcery.configuration.Configuration;
004import com.exoreaction.xorcery.keystores.KeyStoreConfiguration;
005import com.exoreaction.xorcery.keystores.KeyStores;
006import com.exoreaction.xorcery.keystores.KeyStoresConfiguration;
007import com.exoreaction.xorcery.secrets.Secrets;
008import jakarta.inject.Inject;
009import org.bouncycastle.openssl.PEMParser;
010import org.bouncycastle.util.io.pem.PemObject;
011import org.bouncycastle.util.io.pem.PemWriter;
012import org.glassfish.hk2.runlevel.RunLevel;
013import org.jvnet.hk2.annotations.Service;
014
015import java.io.File;
016import java.io.FileWriter;
017import java.io.IOException;
018import java.nio.charset.StandardCharsets;
019import java.security.*;
020import java.security.cert.Certificate;
021import java.security.cert.CertificateEncodingException;
022
023@Service(name = "neo4jbrowser.ssl")
024@RunLevel(3)
025public class Neo4jBoltSSL {
026
027    @Inject
028    public Neo4jBoltSSL(Configuration configuration,
029                        KeyStores keyStores,
030                        Secrets secrets) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, IOException, CertificateEncodingException {
031
032        // Save SSL cert files for Bolt to use
033        KeyStoresConfiguration keyStoresConfiguration = new KeyStoresConfiguration(configuration.getConfiguration("keystores"));
034        KeyStoreConfiguration sslKeyStoreConfiguration = keyStoresConfiguration.getKeyStoreConfiguration("ssl");
035
036        KeyStore sslKeyStore = keyStores.getKeyStore("ssl");
037        String alias = configuration.getString("jetty.server.ssl.alias").orElse("self");
038
039        Key privateKey = sslKeyStore.getKey(alias, sslKeyStoreConfiguration.getPassword().map(secrets::getSecretString).map(String::toCharArray).orElseThrow());
040        File neo4jDatabasePath = configuration.getString("neo4jdatabase.path").map(File::new).orElseThrow();
041        File boltCertificates = new File(neo4jDatabasePath, "certificates/bolt");
042        boltCertificates.mkdirs();
043
044        File privateKeyFile = new File(boltCertificates, "private.key");
045        try (FileWriter privateOut = new FileWriter(privateKeyFile, StandardCharsets.UTF_8)) {
046            PemWriter pWrt = new PemWriter(privateOut);
047            pWrt.writeObject(new PemObject(PEMParser.TYPE_PRIVATE_KEY, privateKey.getEncoded()));
048            pWrt.close();
049        }
050
051        Certificate[] certificates = sslKeyStore.getCertificateChain(alias);
052        File certFile = new File(boltCertificates, "public.crt");
053        try (FileWriter certOut = new FileWriter(certFile, StandardCharsets.UTF_8)) {
054            PemWriter pWrt = new PemWriter(certOut);
055            for (Certificate certificate : certificates) {
056                pWrt.writeObject(new PemObject(PEMParser.TYPE_CERTIFICATE, certificate.getEncoded()));
057            }
058            pWrt.close();
059        }
060    }
061}