Akka HTTPS (SSL) Server with ssl-conf

后端 未结 3 1539
自闭症患者
自闭症患者 2021-02-10 12:48

Akka Version:

  • Akka 2.4.7

Akka Features:

  • HTTPS Server Support

  • Typesafe\'s ssl-config

3条回答
  •  攒了一身酷
    2021-02-10 13:31

    As posted in the other comment, there is a git hub issue that states that "automatically" using the configuration isn't supported yet. However, this issue is closed now; not completed just moved. I went through the release notes for future versions but I didn't see anything relating to this. With so much emphasis on security now, I'm surprised the setup for SSL/TSL isn't something that works out of the box.

    I'm using v2.4.4 (current is 2.4.16) and similar to questioner, I found out the hard way that although the akk-http documentation tells you to use the config, and indeed from debugging you can see that the config gets read in, the implementation to actually use it, isn't completed. I got this message in my logs:

    akka.actor.ActorSystemImpl(OtisRestActorSystem)] Automatic server-side configuration is not supported yet, will attempt to use client-side settings. Instead it is recommended to construct the Servers HttpsConnectionContext manually (via SSLContext)
    

    I tried to "construct the Servers HttpsConnectionContext manually" using the their ssl config, but I couldn't get it to work.

    There were other messages as well, when I was initially troubleshooting that showed it read in the configured key store (which doesn't use the class path to look for it so it couldn't find it at first). So I'm not sure which parts are working and which are missing. So I ended up abandoning the akka-http ssl config completely and set it up myself as my use case is pretty simple. I just want to enable server side SSL/TSL.

    In my configuration I have:

      ssl {
        keyStoreFileName = "myKeyFile.p12"
        keyStorePassword = "myPassword"
      }
    

    For reading my settings I have:

    class Settings(config: Config) extends Extension {
      object Ssl {
        var KeyStoreFileName = config.getString("ssl.keyStoreFileName")
        var KeyStorePassword = config.getString("ssl.keyStorePassword")
      }
    }
    

    And for the "App" I have:

    object RestWebServiceApp extends App with RouteConcatenation {
      import akka.event.{Logging, LoggingAdapter}
      import akka.http.scaladsl.{ ConnectionContext, HttpsConnectionContext, Http }
      import akka.http.scaladsl.server.Directives._
      import akka.http.scaladsl.model.MediaTypes._
      import akka.stream.{ActorMaterializer, ActorMaterializerSettings}
      import java.io.InputStream
      import java.security.{ SecureRandom, KeyStore }
      import javax.net.ssl.{ SSLContext, TrustManagerFactory, KeyManagerFactory }
      import JsonSupport._
    
      implicit val system = ActorSystem("OtisRestActorSystem")
      implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(system))
      implicit val ec = system.dispatcher
    
      ...  //setting up all the routes, etc.
    
      val settings = Settings(system)
      val fileName = settings.Ssl.KeyStoreFileName
      val keyFile: InputStream = getClass.getClassLoader.getResourceAsStream(fileName)
      require(keyFile != null, s"Failed to load key file: ${settings.Ssl.KeyStoreFileName}")
      val extension = if(fileName.lastIndexOf('.')>0) fileName.substring(fileName.lastIndexOf('.')+1) else ""
      val keyStore: KeyStore = extension.toLowerCase match {
        case "jks" =>  KeyStore.getInstance("jks") //Java Key Store; Java default and only works with Java; tested
        case "jcek" =>  KeyStore.getInstance("JCEKS") //Java Cryptography Extension KeyStore; Java 1.4+; not tested
        case "pfx" | "p12" =>  KeyStore.getInstance("PKCS12") // PKCS #12, Common and supported by many languages/frameworks; tested
        case _ => throw new IllegalArgumentException(s"Key has an unknown type extension $extension. Support types are jks, jcek, pfx, p12.")
      }
      val password: Array[Char] = (if(settings.Ssl.KeyStorePassword==null) "" else settings.Ssl.KeyStorePassword).toCharArray
      keyStore.load(keyFile, password)
    
      //TODO: looks like the "SunX509", "TLS", are defined in the keystore, should we pull them out rather than hard coding?
      val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509")
      keyManagerFactory.init(keyStore, password)
    
      val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509")
      tmf.init(keyStore)
    
      val sslContext: SSLContext = SSLContext.getInstance("TLS")
      sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, new SecureRandom)
      val https: HttpsConnectionContext = ConnectionContext.https(sslContext)
      Http().setDefaultServerHttpContext(https)
      Http().bindAndHandle(routes, "localhost", 433, connectionContext = https)
    }
    

提交回复
热议问题