All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gatling.http.util.SslContexts.scala Maven / Gradle / Ivy

There is a newer version: 3.13.1
Show newest version
/*
 * Copyright 2011-2019 GatlingCorp (https://gatling.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.gatling.http.util

import java.security.SecureRandom

import scala.collection.JavaConverters._
import scala.concurrent.duration.Duration

import io.gatling.core.config.HttpConfiguration

import com.typesafe.scalalogging.StrictLogging
import io.netty.handler.ssl._
import io.netty.handler.ssl.util.InsecureTrustManagerFactory
import javax.net.ssl._

private[http] object SslContextsFactory {
  private val DefaultSslSecureRandom = new SecureRandom
  private val Apn = new ApplicationProtocolConfig(
    ApplicationProtocolConfig.Protocol.ALPN,
    // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
    ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE,
    // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
    ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT,
    ApplicationProtocolNames.HTTP_2,
    ApplicationProtocolNames.HTTP_1_1
  )
}

private[gatling] class SslContextsFactory(httpConfig: HttpConfiguration) extends StrictLogging {

  import SslContextsFactory._

  private val sslSessionTimeoutSeconds = httpConfig.advanced.sslSessionTimeout.toSeconds
  private val enabledProtocols: Array[String] = httpConfig.advanced.sslEnabledProtocols.toArray
  private val enabledCipherSuites = httpConfig.advanced.sslEnabledCipherSuites.asJava
  private val useOpenSsl =
    if (httpConfig.advanced.useOpenSsl) {
      val available = OpenSsl.isAvailable
      if (!available) {
        logger.error("OpenSSL is enabled in the Gatling configuration but it's not available on your architecture.")
      }
      available
    } else {
      false
    }

  def newSslContexts(http2Enabled: Boolean, perUserKeyManagerFactory: Option[KeyManagerFactory]): SslContexts = {

    val kmf = perUserKeyManagerFactory.orElse(httpConfig.ssl.keyManagerFactory)
    val tmf = httpConfig.ssl.trustManagerFactory.orElse {
      if (httpConfig.advanced.useInsecureTrustManager) {
        Some(InsecureTrustManagerFactory.INSTANCE)
      } else {
        None
      }
    }

    if (useOpenSsl) {
      val sslContextBuilder = SslContextBuilder.forClient.sslProvider(SslProvider.OPENSSL)

      if (httpConfig.advanced.sslSessionCacheSize > 0) {
        sslContextBuilder.sessionCacheSize(httpConfig.advanced.sslSessionCacheSize)
      }

      if (httpConfig.advanced.sslSessionTimeout > Duration.Zero) {
        sslContextBuilder.sessionTimeout(sslSessionTimeoutSeconds)
      }

      if (enabledProtocols.nonEmpty) {
        sslContextBuilder.protocols(enabledProtocols: _*)
      }

      if (httpConfig.advanced.sslEnabledCipherSuites.nonEmpty) {
        sslContextBuilder.ciphers(enabledCipherSuites)
      } else {
        sslContextBuilder.ciphers(null, IdentityCipherSuiteFilter.INSTANCE_DEFAULTING_TO_SUPPORTED_CIPHERS)
      }

      kmf.foreach(sslContextBuilder.keyManager)
      tmf.foreach(sslContextBuilder.trustManager)

      val sslContext = sslContextBuilder.build
      val alpnSslContext =
        if (http2Enabled) {
          Some(sslContextBuilder.applicationProtocolConfig(Apn).build)
        } else {
          None
        }
      SslContexts(sslContext, alpnSslContext)

    } else {
      val jdkSslContext = SSLContext.getInstance("TLS")
      jdkSslContext.init(kmf.map(_.getKeyManagers).orNull, tmf.map(_.getTrustManagers).orNull, DefaultSslSecureRandom)

      val sslContext = newSslContext(jdkSslContext, null)
      val alpnSslContext =
        if (http2Enabled) {
          Some(newSslContext(jdkSslContext, Apn))
        } else {
          None
        }
      SslContexts(sslContext, alpnSslContext)
    }
  }

  private def newSslContext(jdkSslContext: SSLContext, apn: ApplicationProtocolConfig): SslContext =
    new JdkSslContext(
      jdkSslContext,
      true,
      if (enabledCipherSuites.isEmpty) null else enabledCipherSuites,
      IdentityCipherSuiteFilter.INSTANCE_DEFAULTING_TO_SUPPORTED_CIPHERS,
      apn,
      ClientAuth.NONE,
      if (enabledProtocols.nonEmpty) enabledProtocols else null,
      false
    )
}

private[http] final case class SslContexts(sslContext: SslContext, alplnSslContext: Option[SslContext])




© 2015 - 2025 Weber Informatics LLC | Privacy Policy