Ktor ServerにおけるSSLと証明書
必要な依存関係: io.ktor:ktor-network-tls-certificates
多くの場合、KtorサービスはNginxやApacheなどのリバースプロキシの背後に配置されます。 これは、リバースプロキシサーバーがSSLを含むセキュリティに関する事項を処理することを意味します。
必要に応じて、証明書へのパスを指定することで、Ktorが直接SSLを提供できるように設定することも可能です。 Ktorは、証明書の保存機能として Java KeyStore (JKS) を使用します。 KeyStoreに保存された証明書の管理や変換には、keytool を使用できます。 これは、認証局から発行されたPEM証明書を、KtorがサポートするJKS形式に変換する必要がある場合に便利です。
_Let's Encrypt_を使用して、Ktorで
https://およびwss://リクエストを処理するための無料の証明書を取得できます。
自己署名証明書の生成
コード内での証明書の生成
Ktorは、buildKeyStore 関数を呼び出すことで、テスト目的の自己署名証明書を生成する機能を提供しています。この関数は KeyStore インスタンスを返します。 この関数を使用するには、ビルドスクリプトに ktor-network-tls-certificates アーティファクトを追加する必要があります。
以下のコードスニペットは、証明書を生成してキーストアファイルに保存する方法を示しています。
private fun ApplicationEngine.Configuration.envConfig() {
val keyStoreFile = File("build/keystore.jks")
val keyStore = buildKeyStore {
certificate("sampleAlias") {
password = "foobar"
domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
}
}
keyStore.saveToFile(keyStoreFile, "123456")
}Ktorは起動時に証明書を必要とするため、サーバーを起動する前に証明書を作成する必要があります。 完全な例はこちらで確認できます: ssl-embedded-server
keytoolを使用した証明書の生成
keytool を使用して自己署名証明書を生成できます。
keytool -keystore keystore.jks -alias sampleAlias -genkeypair -keyalg RSA -keysize 4096 -validity 3 -dname 'CN=localhost, OU=ktor, O=ktor, L=Unspecified, ST=Unspecified, C=US'このコマンドを実行すると、keytool はキーストアのパスワードを指定するよう求め、その後JKSファイルを生成します。
PEM証明書からJKSへの変換
認証局がPEM形式で証明書を発行している場合、KtorでSSLを設定する前にJKS形式に変換する必要があります。 これを行うには、openssl および keytool ユーティリティを使用できます。 例えば、key.pem ファイルに秘密鍵があり、cert.pem に公開証明書がある場合、変換プロセスは次のようになります。
次のコマンドを使用して、
opensslでPEMをPKCS12形式に変換します。Bashopenssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name "sampleAlias"key.pemのパスフレーズと、keystore.p12の新しいパスワードの入力を求められます。keytoolを使用してPKCS12をJKS形式に変換します。Bashkeytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore keystore.jkskeystore.p12ファイルのパスワードと、keystore.jksの新しいパスワードの入力を求められます。 これでkeystore.jksが生成されます。
KtorでのSSL設定
KtorでのSSL設定の指定は、Ktorサーバーの設定方法(設定ファイルを使用するか、embeddedServer 関数を使用してコード内で行うか)によって異なります。
設定ファイル
サーバーが application.conf または application.yaml 設定ファイルで設定されている場合、以下の プロパティ を使用してSSLを有効にできます。
ktor.deployment.sslPortプロパティを使用してSSLポートを指定します。shellktor { deployment { sslPort = 8443 } }yamlktor: deployment: sslPort: 8443別の
securityグループでキーストアの設定を提供します。shellktor { security { ssl { keyStore = keystore.jks keyAlias = sampleAlias keyStorePassword = foobar privateKeyPassword = foobar trustStore = truststore.jks trustStorePassword = foobar enabledProtocols = ["TLSv1.2", "TLSv1.3"] } } }yamlktor: security: ssl: keyStore: keystore.jks keyAlias: sampleAlias keyStorePassword: foobar privateKeyPassword: foobar trustStore: truststore.jks trustStorePassword: foobar enabledProtocols: ["TLSv1.2", "TLSv1.3"]
完全な例については、ssl-engine-main を参照してください。
embeddedServer
サーバーの実行に embeddedServer 関数を使用する場合、ApplicationEngine.Configuration で カスタム環境 を設定し、sslConnector を使用してそこでSSL設定を提供する必要があります。
import io.ktor.network.tls.certificates.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import org.slf4j.*
import java.io.*
import java.security.KeyStore
fun main() {
embeddedServer(Netty, applicationEnvironment { log = LoggerFactory.getLogger("ktor.application") }, {
envConfig()
}, module = Application::module).start(wait = true)
}
private fun ApplicationEngine.Configuration.envConfig() {
val keyStoreFile = File("build/keystore.jks")
val keyStore = buildKeyStore {
certificate("sampleAlias") {
password = "foobar"
domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
}
}
keyStore.saveToFile(keyStoreFile, "123456")
connector {
port = 8080
}
sslConnector(
keyStore = keyStore,
keyAlias = "sampleAlias",
keyStorePassword = { "123456".toCharArray() },
privateKeyPassword = { "foobar".toCharArray() }) {
port = 8443
keyStorePath = keyStoreFile
}
}完全な例については、ssl-embedded-server を参照してください。
