Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
SSL Config Example For Vert.x 3.0.0
package com.zanclus.socialshell;
import com.zanclus.socialshell.utils.AbstractLoggingVerticle;
import static io.vertx.ext.auth.shiro.LDAPAuthRealmConstants.*;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Verticle;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.JksOptions;
import io.vertx.core.net.PemKeyCertOptions;
import io.vertx.core.net.PfxOptions;
import io.vertx.ext.apex.Router;
import io.vertx.ext.apex.handler.StaticHandler;
import io.vertx.ext.apex.handler.sockjs.BridgeOptions;
import io.vertx.ext.apex.handler.sockjs.PermittedOptions;
import io.vertx.ext.apex.handler.sockjs.SockJSHandler;
import io.vertx.ext.auth.AuthProvider;
import io.vertx.ext.auth.shiro.ShiroAuthProvider;
import io.vertx.ext.auth.shiro.ShiroAuthRealmType;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;
/**
* A {@link Verticle} which starts up the HTTP server for the web application UI. Based on the given
* configuration, the web server may be configured for SSL using a self-generated SSL cert or a provided SSL certificate
* file. The application accepts P12, PEM, and JKS files.
*
* The web server also configures handlers for the Auth Service and the {@link SockJSHandler} event bus bridge.
*
* @author <a href="https://github.com/InfoSec812">Deven Phillips</a>
*/
public class WebServerVerticle extends AbstractLoggingVerticle {
/**
* Start this {@link Verticle} asynchronously and notify the deploying verticle on success or failure
* @param startFuture A {@link Future} with which to notify the deploying {@link Verticle} about success or failure
* @throws Exception If there is an uncaught error.
*/
@Override
public void start(final Future<Void> startFuture) throws Exception {
final JsonObject config = context.config().getJsonObject("webserver");
final JsonObject authCfg = context.config().getJsonObject("authentication");
final String bindAddress;
final int bindPort;
final String webRoot;
if (config.containsKey("bind-address")) {
bindAddress = config.getString("bind-address");
} else {
bindAddress = "0.0.0.0";
}
if (config.containsKey("bind-port")) {
bindPort = config.getInteger("bind-port");
} else {
bindPort = 8080;
}
if (config.containsKey("webroot")) {
webRoot = config.getString("webroot");
} else {
webRoot = "webroot/";
}
Router router = Router.router(vertx);
SockJSHandler sockjs = SockJSHandler.create(vertx);
BridgeOptions opts;
opts = new BridgeOptions()
// Allow inbound events going to the terminal session
.addInboundPermitted(new PermittedOptions()
.setAddressRegex("^terminal\\.to\\.server\\..*$")
.setRequiredRole("session"))
// Allow inbound events giving control of the terminal to an invited collaborator
.addInboundPermitted(new PermittedOptions()
.setAddressRegex("^delegate\\.control\\..*$")
.setRequiredRole("session"))
// Allow inbound events revoking control from invited collaborator
.addInboundPermitted(new PermittedOptions()
.setAddressRegex("^revoke\\.control\\..*$")
.setRequiredRole("session"))
// Allow inbound events for chat messages coming from the client for a given session
.addInboundPermitted(new PermittedOptions()
.setAddressRegex("^chat\\.to\\.server\\..*$")
.setRequiredRole("session"))
// Allow inbound events requesting control of a shared terminal
.addInboundPermitted(new PermittedOptions()
.setAddressRegex("^request\\.control\\..*$")
.setRequiredRole("session"))
// Allow inbound events releasing control of a shared terminal
.addInboundPermitted(new PermittedOptions()
.setAddressRegex("^release\\.control\\..*$")
.setRequiredRole("session"))
// Allow outbound events from the terminal session to the UI
.addOutboundPermitted(new PermittedOptions()
.setAddressRegex("^server\\.to\\.terminal\\..*$")
.setRequiredRole("session"))
// Allow outbound events from the server to participants in a session's chat
.addOutboundPermitted(new PermittedOptions()
.setAddressRegex("^server\\.to\\.chat\\..*$")
.setRequiredRole("session"))
// Allow outbound events to the UI indicating that control was granted
.addOutboundPermitted(new PermittedOptions()
.setAddressRegex("^control\\.granted\\..*$")
.setRequiredRole("session"))
// Allow outbound events to the UI indicating that control was revoked
.addOutboundPermitted(new PermittedOptions()
.setAddressRegex("^control\\.revoked\\..*$")
.setRequiredRole("session"));
sockjs.bridge(opts);
AuthProvider authProvider;
if (authCfg.containsKey("auth-provider")) {
switch(authCfg.getString("auth-provider")) {
case "ldap":
authProvider = ShiroAuthProvider.create(vertx, ShiroAuthRealmType.LDAP, authCfg);
break;
case "jdbc":
break;
default: {};
}
}
router.route("/eventbus/*").handler(sockjs);
router.route().handler(StaticHandler.create(webRoot).setIndexPage("index.html"));
// If SSL is requested, prepare the SSL configuration off of the event bus to prevent blocking.
if (config.containsKey("ssl") && config.getBoolean("ssl")) {
vertx.executeBlocking(future -> {
HttpServerOptions httpOpts = new HttpServerOptions();
if (config.containsKey("certificate-path")) {
String certPath = config.getString("certificate-path");
// Use a Java Keystore File
if (certPath.toLowerCase().endsWith("jks") && config.getString("certificate-password")!=null) {
httpOpts.setKeyStoreOptions(new JksOptions()
.setPassword(config.getString("certificate-password"))
.setPath(certPath));
httpOpts.setSsl(true);
// Use a PKCS12 keystore
} else if ( config.getString("certificate-password")!=null &&
certPath.matches("^.*\\.(pfx|p12|PFX|P12)$")) {
httpOpts.setPfxKeyCertOptions(new PfxOptions()
.setPassword(config.getString("certificate-password"))
.setPath(certPath));
httpOpts.setSsl(true);
// Use a PEM key/cert pair
} else if (certPath.matches("^.*\\.(pem|PEM)$")) {
httpOpts.setPemKeyCertOptions(new PemKeyCertOptions()
.setCertPath(certPath)
.setKeyPath(certPath));
httpOpts.setSsl(true);
} else {
startFuture.fail("A certificate file was provided, but a password for that file was not.");
}
} else {
try {
// Generate a self-signed key pair and certificate.
KeyStore store = KeyStore.getInstance("JKS");
store.load(null, null);
CertAndKeyGen keypair = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
X500Name x500Name = new X500Name("localhost", "IT", "unknown", "unknown", "unknown", "unknown");
keypair.generate(1024);
PrivateKey privKey = keypair.getPrivateKey();
X509Certificate[] chain = new X509Certificate[1];
chain[0] = keypair.getSelfCertificate(x500Name, new Date(), (long) 365 * 24 * 60 * 60);
store.setKeyEntry("selfsigned", privKey, "changeit".toCharArray(), chain);
store.store(new FileOutputStream(".keystore"), "changeit".toCharArray());
httpOpts.setKeyStoreOptions(new JksOptions().setPath(".keystore").setPassword("changeit"));
httpOpts.setSsl(true);
} catch (KeyStoreException|IOException|NoSuchAlgorithmException|CertificateException|NoSuchProviderException|InvalidKeyException|SignatureException ex) {
Logger.getLogger(WebServerVerticle.class.getName()).log(Level.SEVERE, "Failed to generate a self-signed cert and other SSL configuration methods failed.", ex);
startFuture.fail(ex);
}
}
future.complete(httpOpts);
}, (AsyncResult<HttpServerOptions> result) -> {
if (!result.failed()) {
vertx.createHttpServer(result.result()).requestHandler(router::accept).listen(bindPort, bindAddress);
log.info("SSL Web server now listening");
startFuture.complete();
}
});
} else {
// No SSL requested, start a non-SSL HTTP server.
vertx.createHttpServer().requestHandler(router::accept).listen(bindPort, bindAddress);
log.info("Web server now listening");
startFuture.complete();
}
}
}
@WEBOWNIA

This comment has been minimized.

Copy link

WEBOWNIA commented Jul 3, 2015

In version 3.0.0... setRequiredRole is the same setRequiredAuthority.... ?

@kamaljeetrathi

This comment has been minimized.

Copy link

kamaljeetrathi commented Oct 16, 2015

I am setting
httpClientOptions.setSsl(true).setPemKeyCertOptions(new PemKeyCertOptions().setKeyPath(keyCrtFile).setCertPath(certCrtFile).setCertPath(caCrtFile));

as path and I have three certificate file which need to be authenticate ca.pem,cert.pem,key.pem
its giving me error
SEVERE: java.lang.RuntimeException: Missing -----BEGIN PRIVATE KEY----- delimiter

@datagenn

This comment has been minimized.

Copy link

datagenn commented Feb 17, 2016

@kamaljeetrathi

You need to convert PKCS8 to PK8
openssl pkcs8 -topk8 -inform PEM -outform PEM -in ca.key -out ca-new.pem -nocrypt

@datagenn

This comment has been minimized.

Copy link

datagenn commented Feb 17, 2016

Also, if using this code in Production, don't use 'SHA1WithRSA' as it is insecure and not even supported by Google Chrome any longer; use 'SHA256WithRSA' instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.