Reputation: 691
While trying to make the HTTPS GET request from the web browser:
Browser warning connection not secure
While trying to make a cURL request to the service on the server:
docker ps
PORTS
0.0.0.0:443->443/tcp
curl -v https://localhost
How to configure properly the Akka HTTP's server to use HTTPS, for a given:
package de.htw_berlin.http
import java.security.SecureRandom
import akka.http.scaladsl.{ConnectionContext, HttpsConnectionContext}
import de.htw_berlin.security.{PKCS12KeyStoreFactory, X509KeyManagersFactory}
import java.io.FileInputStream
import javax.net.ssl.SSLContext
object HttpsConnectionContextFactory {
// TODO refactor
def apply(keyStoreFilename: String, keyStorePassword: String): HttpsConnectionContext = {
val p12KeyStore = PKCS12KeyStoreFactory(new FileInputStream(keyStoreFilename), keyStorePassword)
val sslContext: SSLContext = SSLContext.getInstance("TLS")
sslContext.init(X509KeyManagersFactory(p12KeyStore, keyStorePassword), null, new SecureRandom)
ConnectionContext.httpsServer(sslContext)
}
}
package de.htw_berlin.security
import java.security.KeyStore
import javax.net.ssl.{KeyManager, KeyManagerFactory}
object X509KeyManagersFactory {
def apply(keyStore: KeyStore, keyStorePassword: String): Array[KeyManager] = {
val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray)
keyManagerFactory.getKeyManagers
}
}
package de.htw_berlin.security
import java.io.InputStream
import java.security.KeyStore
object PKCS12KeyStoreFactory {
def apply(keyStoreAsInputStream: InputStream, keyStorePassword: String): KeyStore = {
val p12KeyStore = KeyStore.getInstance("PKCS12")
p12KeyStore.load(keyStoreAsInputStream, keyStorePassword.toCharArray)
p12KeyStore
}
}
package de.htw_berlin.http
import akka.actor.typed.ActorSystem
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.{Http, HttpsConnectionContext}
import de.htw_berlin.http.dip.RequestHandler
import scala.concurrent.Future
// TODO test.
/** Represents a HTTPS server which can be bind to a host and port.
* The server needs a request handler for processing incoming requests.
*
* @param host the optional host of the server. The default value is Constants.DefaultServerIpv4Address.
* @param port the optional port number of the server. The default value is Constants.DefaultHttpsPort.
* @param httpsContext the https connection context for the https connection.
* @param actorSystem an implicit actor system.
* @see de.htw_berlin.http.dip.RequestHandler
*/
class Server(val host: String = Constants.DefaultServerIpv4Address,
val port: Int = Constants.DefaultHttpsPort,
val httpsContext: HttpsConnectionContext)(implicit val actorSystem: ActorSystem[Nothing]) {
/** Binds the current server to the endpoint parameters (host and port) and uses the passed
* handler for processing incoming connections.
*
* @param handler the handler to be used for processing incoming requests.
* @return a server binding future.
*/
def bindAndHandleWith(handler: RequestHandler): Future[ServerBinding] =
Http().newServerAt(host, port).enableHttps(httpsContext).bind(handler.getRoute)
}
package de.htw_berlin.http
/** This object contains constants related with the current module http. */
object Constants {
/** The server's default IPv4 address. */
val DefaultServerIpv4Address = "0.0.0.0"
/** The default port for HTTPS connections. */
val DefaultHttpsPort = 443
}
If it's not enough, the full code is in my public repository
Beside the fact that I read a lot about x509 Standard and TLS/HTTP and searched for answers in another threads, I also checked if the port 443 is open on the server (BTW: I do everything inside a VPN connection, so the firewall should not matter??) and I asked the admin for help, he's not familiar with Akka HTTP and docker, but he said that the curl output probably has something to do with the certificate chain.
Upvotes: 2
Views: 1162
Reputation: 26
Ensure port 443 is open and running
telnet localhost 443
and see if there is anything like scape character is '^]'.
Ensure your server is talking in https protocol instead of http
curl --insecure -v https://localhost
to skip SSL certificate verification (but still establish an SSL connection) to see if you really receive response from your server
Ensure your server certificate is globally signed instead of self-signed
Your browser doesn't trust unknown certificate, please ensure you obtain an SSL certificate from global CA, e.g. Let's Encrypt. Your browser has a list of hardcoded CA certs to verify every website's certificate.
On the other hand, your curl is looking up in /etc/ssl/certs
to get a list of CA certs for verifying your website's certificate, so the flag --insecure
is to skip verifying SSL certificate.
Upvotes: 0
Reputation: 691
Embarrassingly, the problem was related to Docker and the key store created with openssl: The root user within the container was not privileged to read the key store (Permission Denied Exception).
However, the code works and I will keep this thread going as reference for the community.
Upvotes: 1
Reputation: 1760
You are passing null
for TrustManager[]
argument here:
sslContext.init(X509KeyManagersFactory(p12KeyStore, keyStorePassword), null, new SecureRandom)
Checkout the documentation on how to initialize and pass TrustManager: https://doc.akka.io/docs/akka-http/current/server-side/server-https-support.html#using-https
Upvotes: 0