Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIO server HTTPS support on Native #2942

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -9,28 +9,36 @@ import io.ktor.server.engine.*
import java.io.*
import java.security.*

internal actual fun HttpServerSettings(
connectionIdleTimeoutSeconds: Long,
connectorConfig: EngineConnectorConfig
): HttpServerSettings = HttpServerSettings(
host = connectorConfig.host,
port = connectorConfig.port,
connectionIdleTimeoutSeconds = connectionIdleTimeoutSeconds,
tlsConfig = when (connectorConfig) {
is EngineSSLConnectorConfig -> TLSConfig(isClient = false) {
// serverName = connectorConfig.host //TODO?
authentication(connectorConfig.privateKeyPassword) {
keyStore(connectorConfig.resolveKeyStore())
}
connectorConfig.resolveTrustStore()?.let {
verification {
trustStore(it)
}
internal actual fun TLSConfigBuilder.takeFromConnector(connectorConfig: EngineSSLConnectorConfig) {
authentication(connectorConfig)
verification(connectorConfig)
}

private fun TLSConfigBuilder.authentication(connectorConfig: EngineSSLConnectorConfig) {
connectorConfig.authentication?.let { config ->
config.keyStoreProvider?.resolveKeyStore()?.let { keyStore ->
authentication(config.privateKeyPassword) {
keyStore(keyStore)
}
return
}
else -> null
}
)

//old configuration
authentication(connectorConfig.privateKeyPassword) {
keyStore(connectorConfig.resolveKeyStore())
}
}

private fun TLSConfigBuilder.verification(connectorConfig: EngineSSLConnectorConfig) {
val trustStore =
connectorConfig.verification?.trustStoreProvider?.resolveKeyStore()
?: connectorConfig.resolveTrustStore() //old configuration
?: return
verification {
trustStore(trustStore)
}
}

//TODO: make it public and move to core
private fun EngineSSLConnectorConfig.resolveKeyStore(): KeyStore = keyStorePath?.let { file ->
Expand Down
Expand Up @@ -5,6 +5,7 @@
package io.ktor.server.cio

import io.ktor.http.cio.*
import io.ktor.network.tls.*
import io.ktor.server.application.*
import io.ktor.server.cio.backend.*
import io.ktor.server.cio.internal.*
Expand Down Expand Up @@ -145,10 +146,10 @@ public class CIOApplicationEngine(

try {
environment.connectors.forEach { connectorSpec ->
if (connectorSpec.type == ConnectorType.HTTPS && !PlatformUtils.IS_JVM) {
if (connectorSpec.type == ConnectorType.HTTPS && PlatformUtils.IS_DARWIN) {
throw UnsupportedOperationException(
"CIO Engine does not currently support HTTPS. Please " +
"consider using a different engine if you require HTTPS"
"CIO Engine does not currently support HTTPS on darwin. " +
"Please consider using a different engine if you require HTTPS"
)
}
}
Expand Down Expand Up @@ -186,7 +187,17 @@ public class CIOApplicationEngine(
}
}

internal expect fun HttpServerSettings(
internal fun HttpServerSettings(
connectionIdleTimeoutSeconds: Long,
connectorConfig: EngineConnectorConfig
): HttpServerSettings
): HttpServerSettings = HttpServerSettings(
host = connectorConfig.host,
port = connectorConfig.port,
connectionIdleTimeoutSeconds = connectionIdleTimeoutSeconds,
tlsConfig = when (connectorConfig) {
is EngineSSLConnectorConfig -> TLSConfig(isClient = false) { takeFromConnector(connectorConfig) }
else -> null
}
)

internal expect fun TLSConfigBuilder.takeFromConnector(connectorConfig: EngineSSLConnectorConfig)
Binary file not shown.
Binary file not shown.
Expand Up @@ -20,7 +20,7 @@ import kotlin.test.*
class CIOHttpServerTest : HttpServerCommonTestSuite<CIOApplicationEngine, CIOApplicationEngine.Configuration>(CIO) {
init {
enableHttp2 = false
enableSsl = PlatformUtils.IS_JVM
enableSsl = !PlatformUtils.IS_DARWIN
}

@Test
Expand Down
Expand Up @@ -4,13 +4,22 @@

package io.ktor.server.cio

import io.ktor.network.tls.*
import io.ktor.server.engine.*

internal actual fun HttpServerSettings(
connectionIdleTimeoutSeconds: Long,
connectorConfig: EngineConnectorConfig
): HttpServerSettings = HttpServerSettings(
host = connectorConfig.host,
port = connectorConfig.port,
connectionIdleTimeoutSeconds = connectionIdleTimeoutSeconds
)
internal actual fun TLSConfigBuilder.takeFromConnector(connectorConfig: EngineSSLConnectorConfig) {
connectorConfig.authentication?.let { config ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a?b.let { b -> b?.clet { c -> ... }

is hard to read. Could be replaced with:

val c = a?.b?.c

instead

config.pkcs12Certificate?.let { certificate ->
authentication(config.privateKeyPassword) {
pkcs12Certificate(certificate.path, certificate.passwordProvider)
}
}
}
connectorConfig.verification?.let { config ->
config.pkcs12Certificate?.let { certificate ->
verification {
pkcs12Certificate(certificate.path, certificate.passwordProvider)
}
}
}
}
108 changes: 107 additions & 1 deletion ktor-server/ktor-server-host-common/api/ktor-server-host-common.api
Expand Up @@ -246,12 +246,14 @@ public abstract interface class io/ktor/server/engine/EngineConnectorConfig {
}

public final class io/ktor/server/engine/EngineConnectorConfigJvmKt {
public static final fun resolveKeyStore (Lio/ktor/server/engine/KeyStoreProvider;)Ljava/security/KeyStore;
public static final fun sslConnector (Lio/ktor/server/engine/ApplicationEngineEnvironmentBuilder;Ljava/security/KeyStore;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)V
public static final fun withPort (Lio/ktor/server/engine/EngineConnectorConfig;I)Lio/ktor/server/engine/EngineConnectorConfig;
}

public final class io/ktor/server/engine/EngineConnectorConfigKt {
public static final fun connector (Lio/ktor/server/engine/ApplicationEngineEnvironmentBuilder;Lkotlin/jvm/functions/Function1;)V
public static final fun sslConnector (Lio/ktor/server/engine/ApplicationEngineEnvironmentBuilder;Lkotlin/jvm/functions/Function1;)V
public static final fun withPort (Lio/ktor/server/engine/EngineConnectorConfig;I)Lio/ktor/server/engine/EngineConnectorConfig;
}

public final class io/ktor/server/engine/EngineContextCancellationHelperKt {
Expand All @@ -275,7 +277,11 @@ public final class io/ktor/server/engine/EnginePipeline$Companion {
}

public final class io/ktor/server/engine/EngineSSLConnectorBuilder : io/ktor/server/engine/EngineConnectorBuilder, io/ktor/server/engine/EngineSSLConnectorConfig {
public fun <init> ()V
public fun <init> (Ljava/security/KeyStore;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V
public final fun authentication (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)V
public fun getAuthentication ()Lio/ktor/server/engine/EngineSSLConnectorBuilder$AuthenticationConfigBuilder;
public synthetic fun getAuthentication ()Lio/ktor/server/engine/EngineSSLConnectorConfig$AuthenticationConfig;
public fun getKeyAlias ()Ljava/lang/String;
public fun getKeyStore ()Ljava/security/KeyStore;
public fun getKeyStorePassword ()Lkotlin/jvm/functions/Function0;
Expand All @@ -284,6 +290,9 @@ public final class io/ktor/server/engine/EngineSSLConnectorBuilder : io/ktor/ser
public fun getPrivateKeyPassword ()Lkotlin/jvm/functions/Function0;
public fun getTrustStore ()Ljava/security/KeyStore;
public fun getTrustStorePath ()Ljava/io/File;
public fun getVerification ()Lio/ktor/server/engine/EngineSSLConnectorBuilder$VerificationConfigBuilder;
public synthetic fun getVerification ()Lio/ktor/server/engine/EngineSSLConnectorConfig$VerificationConfig;
public fun setAuthentication (Lio/ktor/server/engine/EngineSSLConnectorBuilder$AuthenticationConfigBuilder;)V
public fun setKeyAlias (Ljava/lang/String;)V
public fun setKeyStore (Ljava/security/KeyStore;)V
public fun setKeyStorePassword (Lkotlin/jvm/functions/Function0;)V
Expand All @@ -292,16 +301,113 @@ public final class io/ktor/server/engine/EngineSSLConnectorBuilder : io/ktor/ser
public fun setPrivateKeyPassword (Lkotlin/jvm/functions/Function0;)V
public fun setTrustStore (Ljava/security/KeyStore;)V
public fun setTrustStorePath (Ljava/io/File;)V
public fun setVerification (Lio/ktor/server/engine/EngineSSLConnectorBuilder$VerificationConfigBuilder;)V
public final fun verification (Lkotlin/jvm/functions/Function1;)V
}

public final class io/ktor/server/engine/EngineSSLConnectorBuilder$AuthenticationConfig : io/ktor/server/engine/EngineSSLConnectorConfig$AuthenticationConfig {
public fun <init> (Lkotlin/jvm/functions/Function0;)V
public fun getKeyAlias ()Ljava/lang/String;
public fun getKeyStore ()Ljava/security/KeyStore;
public fun getKeyStorePassword ()Lkotlin/jvm/functions/Function0;
public fun getKeyStorePath ()Ljava/io/File;
public fun getPrivateKeyPassword ()Lkotlin/jvm/functions/Function0;
public final fun pkcs12Certificate (Ljava/io/File;Lkotlin/jvm/functions/Function0;)V
public final fun pkcs12Certificate (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public fun setKeyAlias (Ljava/lang/String;)V
public fun setKeyStore (Ljava/security/KeyStore;)V
public fun setKeyStorePassword (Lkotlin/jvm/functions/Function0;)V
public fun setKeyStorePath (Ljava/io/File;)V
}

public final class io/ktor/server/engine/EngineSSLConnectorBuilder$AuthenticationConfigBuilder : io/ktor/server/engine/EngineSSLConnectorConfig$AuthenticationConfig {
public fun <init> (Lkotlin/jvm/functions/Function0;)V
public fun getKeyAlias ()Ljava/lang/String;
public fun getKeyStoreProvider ()Lio/ktor/server/engine/KeyStoreProvider;
public fun getPrivateKeyPassword ()Lkotlin/jvm/functions/Function0;
public final fun keyStore (Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public final fun keyStore (Ljava/security/KeyStore;)V
public static synthetic fun keyStore$default (Lio/ktor/server/engine/EngineSSLConnectorBuilder$AuthenticationConfigBuilder;Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
public final fun pkcs12Certificate (Ljava/io/File;Lkotlin/jvm/functions/Function0;)V
public final fun pkcs12Certificate (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public fun setKeyAlias (Ljava/lang/String;)V
public fun setKeyStoreProvider (Lio/ktor/server/engine/KeyStoreProvider;)V
}

public final class io/ktor/server/engine/EngineSSLConnectorBuilder$VerificationConfig : io/ktor/server/engine/EngineSSLConnectorConfig$VerificationConfig {
public fun <init> ()V
public fun getTrustStore ()Ljava/security/KeyStore;
public fun getTrustStorePath ()Ljava/io/File;
public final fun pkcs12Certificate (Ljava/io/File;Lkotlin/jvm/functions/Function0;)V
public final fun pkcs12Certificate (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public fun setTrustStore (Ljava/security/KeyStore;)V
public fun setTrustStorePath (Ljava/io/File;)V
}

public final class io/ktor/server/engine/EngineSSLConnectorBuilder$VerificationConfigBuilder : io/ktor/server/engine/EngineSSLConnectorConfig$VerificationConfig {
public fun <init> ()V
public fun getTrustStoreProvider ()Lio/ktor/server/engine/KeyStoreProvider;
public final fun pkcs12Certificate (Ljava/io/File;Lkotlin/jvm/functions/Function0;)V
public final fun pkcs12Certificate (Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public fun setTrustStoreProvider (Lio/ktor/server/engine/KeyStoreProvider;)V
public final fun trustStore (Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public final fun trustStore (Ljava/security/KeyStore;)V
public static synthetic fun trustStore$default (Lio/ktor/server/engine/EngineSSLConnectorBuilder$VerificationConfigBuilder;Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)V
}

public abstract interface class io/ktor/server/engine/EngineSSLConnectorConfig : io/ktor/server/engine/EngineConnectorConfig {
public abstract fun getAuthentication ()Lio/ktor/server/engine/EngineSSLConnectorConfig$AuthenticationConfig;
public abstract fun getKeyAlias ()Ljava/lang/String;
public abstract fun getKeyStore ()Ljava/security/KeyStore;
public abstract fun getKeyStorePassword ()Lkotlin/jvm/functions/Function0;
public abstract fun getKeyStorePath ()Ljava/io/File;
public abstract fun getPrivateKeyPassword ()Lkotlin/jvm/functions/Function0;
public abstract fun getTrustStore ()Ljava/security/KeyStore;
public abstract fun getTrustStorePath ()Ljava/io/File;
public abstract fun getVerification ()Lio/ktor/server/engine/EngineSSLConnectorConfig$VerificationConfig;
}

public abstract interface class io/ktor/server/engine/EngineSSLConnectorConfig$AuthenticationConfig {
public abstract fun getKeyAlias ()Ljava/lang/String;
public abstract fun getKeyStoreProvider ()Lio/ktor/server/engine/KeyStoreProvider;
public abstract fun getPrivateKeyPassword ()Lkotlin/jvm/functions/Function0;
}

public abstract interface class io/ktor/server/engine/EngineSSLConnectorConfig$VerificationConfig {
public abstract fun getTrustStoreProvider ()Lio/ktor/server/engine/KeyStoreProvider;
}

public final class io/ktor/server/engine/EngineSSLConnectorConfigKt {
public static final fun sslConnector (Lio/ktor/server/engine/ApplicationEngineEnvironmentBuilder;Lkotlin/jvm/functions/Function1;)V
}

public abstract interface class io/ktor/server/engine/KeyStoreProvider {
}

public final class io/ktor/server/engine/KeyStoreProvider$File : io/ktor/server/engine/KeyStoreProvider {
public fun <init> (Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
public final fun component1 ()Ljava/io/File;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Lkotlin/jvm/functions/Function0;
public final fun copy (Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;)Lio/ktor/server/engine/KeyStoreProvider$File;
public static synthetic fun copy$default (Lio/ktor/server/engine/KeyStoreProvider$File;Ljava/io/File;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lio/ktor/server/engine/KeyStoreProvider$File;
public fun equals (Ljava/lang/Object;)Z
public final fun getPasswordProvider ()Lkotlin/jvm/functions/Function0;
public final fun getPath ()Ljava/io/File;
public final fun getType ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class io/ktor/server/engine/KeyStoreProvider$Instance : io/ktor/server/engine/KeyStoreProvider {
public fun <init> (Ljava/security/KeyStore;)V
public final fun component1 ()Ljava/security/KeyStore;
public final fun copy (Ljava/security/KeyStore;)Lio/ktor/server/engine/KeyStoreProvider$Instance;
public static synthetic fun copy$default (Lio/ktor/server/engine/KeyStoreProvider$Instance;Ljava/security/KeyStore;ILjava/lang/Object;)Lio/ktor/server/engine/KeyStoreProvider$Instance;
public fun equals (Ljava/lang/Object;)Z
public final fun getKeyStore ()Ljava/security/KeyStore;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class io/ktor/server/engine/ShutDownUrl {
Expand Down