From c3e8a968d9e155eab2efea18d8ac3d84e01a6314 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Tue, 16 Jul 2019 15:32:50 +0200 Subject: [PATCH] Test hostname verification (#27355) --- .gitignore | 1 - akka-remote/src/test/resources/Makefile | 17 ++++++ akka-remote/src/test/resources/keystore | Bin 1342 -> 1573 bytes akka-remote/src/test/resources/truststore | Bin 637 -> 621 bytes .../remote/artery/ArterySpecSupport.scala | 2 +- .../akka/remote/artery/tcp/TlsTcpSpec.scala | 57 ++++++++++++++++-- 6 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 akka-remote/src/test/resources/Makefile diff --git a/.gitignore b/.gitignore index 7dbbb248f7..1e73160fe9 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,6 @@ .tags_sorted_by_file .target .worksheet -Makefile TAGS _akka_cluster/ _dump diff --git a/akka-remote/src/test/resources/Makefile b/akka-remote/src/test/resources/Makefile new file mode 100644 index 0000000000..5343762ec5 --- /dev/null +++ b/akka-remote/src/test/resources/Makefile @@ -0,0 +1,17 @@ +all: truststore keystore + +truststore: domain.crt + keytool -importcert -file domain.crt -keystore truststore -deststorepass changeme + +keystore: domain.crt domain.key + openssl pkcs12 -export -inkey domain.key -passin pass:changeme -in domain.crt -out keystore -passout pass:changeme + +domain.crt: domain.csr domain.key + openssl x509 -req -in domain.csr -sha256 -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:localhost")) -out domain.crt -extensions SAN -signkey domain.key + +domain.csr: + openssl req -new -sha256 -key domain.key -subj "/C=ZA/ST=web/O=Lightbend/CN=akka-remote" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:localhost")) -out domain.csr -passout pass:changeme + +.PHONY: clean +clean: + rm domain.crt domain.csr keystore truststore diff --git a/akka-remote/src/test/resources/keystore b/akka-remote/src/test/resources/keystore index ee5581d930a1cb38981f2a547aab3acf24861e71..a76d66d7ab4dcc60e5d8baf937df526e002e09ce 100644 GIT binary patch literal 1573 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 DEz%@Z diff --git a/akka-remote/src/test/resources/truststore b/akka-remote/src/test/resources/truststore index cc07616dad6cd4bb2833468ee5b4e6bf79b62b97..f70de5dde24b3f1c2fab5ce43c7396fabf965389 100644 GIT binary patch delta 398 zcmey%@|I}0u$Zl7S-b1v+wLW9HI_JhXnC$9PAvgG5U=G{k&s-4BOr{+C=xIg~;cav2) z3KqNvW^PT`XMA1Cduh0&ho?Tz%QB}q&-!C`>a^Ofs+7(b|M+`hz{arkvy4u!+j+S^ tr^d@}U4YCwdH3qbJ%6@a9lvd~vv^a1uu8(*po-80u?1?k{~EPO0|2<0hv)zR delta 429 zcmaFM@|R_Tl!^K2<~|Ju)(AaQ14{-5CVPV>CToKx#w81wnHZUvSo|-Zx?sS|#;Mij z(e|B}k&%^^!60#BoLIdub9ri#A&&tU8*?ZNJA@}_zz^ba33G&07Niy@rllJ48gPSz zxP@5~v$GQoMGS;MTxMZz5LdS-H8;N`)j&a<*U-qo%)r9H($v7fB1(ea$k4#j(9p;n zDqxUk$Zfz0(#a;w6y<2hV=ys~%^qSY*-n`FZ(Ti_*O(g{8A9T}{hG)8D5-6W`@hW` z&nIX%dE4C-IPUu7a$4f~r8n;I=t=0UyQ#CCsZH zYqpUl;_t(1_C=iJ*(zF+zBYG}>RRIo{}-N>;M}jr%DK>Sl374?y|<{hyuf@7#=}$C qRf8W({lDhq)ZP~UX6oDhwMFiqr!aRsZkg}(-S>0dM&D}26Y~JfJ%nQb diff --git a/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala b/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala index 560a96b9ba..3acb3f7ed6 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/ArterySpecSupport.scala @@ -22,7 +22,7 @@ object ArterySpecSupport { provider = remote serialize-creators = off } - akka.remote.warn-about-direct-use = off + remote.warn-about-direct-use = off remote.artery { enabled = on canonical { diff --git a/akka-remote/src/test/scala/akka/remote/artery/tcp/TlsTcpSpec.scala b/akka-remote/src/test/scala/akka/remote/artery/tcp/TlsTcpSpec.scala index 7b369cce26..d48f39932b 100644 --- a/akka-remote/src/test/scala/akka/remote/artery/tcp/TlsTcpSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/artery/tcp/TlsTcpSpec.scala @@ -25,6 +25,8 @@ import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import javax.net.ssl.SSLEngine +import akka.testkit.EventFilter + class TlsTcpWithDefaultConfigSpec extends TlsTcpSpec(ConfigFactory.empty()) class TlsTcpWithSHA1PRNGSpec @@ -183,22 +185,65 @@ class TlsTcpWithHostnameVerificationSpec akka.remote.artery.ssl.config-ssl-engine { hostname-verification = on } + akka.remote.use-unsafe-remote-features-without-cluster = on + + akka.loggers = ["akka.testkit.TestEventListener"] """).withFallback(TlsTcpSpec.config)) with ImplicitSender { - val systemB = newRemoteSystem(name = Some("systemB")) - val addressB = address(systemB) - val rootB = RootActorPath(addressB) - "Artery with TLS/TCP and hostname-verification=on" must { - "reject invalid" in { + "fail when the name in the server certificate does not match" in { // this test only makes sense with tls-tcp transport if (!arteryTcpTlsEnabled()) pending + val systemB = newRemoteSystem( + // The subjectAltName is 'localhost', so connecting to '127.0.0.1' should not + // work when using hostname verification: + extraConfig = Some("""akka.remote.artery.canonical.hostname = "127.0.0.1""""), + name = Some("systemB")) + + val addressB = address(systemB) + val rootB = RootActorPath(addressB) + + systemB.actorOf(TestActors.echoActorProps, "echo") + EventFilter + .warning( + pattern = + "outbound connection to \\[akka://systemB@127.0.0.1:.*" + + "Upstream failed, cause: SSLHandshakeException: General SSLEngine problem", + occurrences = 3) + .intercept { + system.actorSelection(rootB / "user" / "echo") ! Identify("echo") + } + expectNoMessage(2.seconds) + systemB.terminate() + } + "succeed when the name in the server certificate matches" in { + if (!arteryTcpTlsEnabled()) + pending + + val systemB = newRemoteSystem( + extraConfig = Some(""" + // The subjectAltName is 'localhost', so this is how we want to be known: + akka.remote.artery.canonical.hostname = "localhost" + + // Though we will still bind to 127.0.0.1 (make sure it's not ipv6) + akka.remote.artery.bind.hostname = "127.0.0.1" + """), + name = Some("systemB")) + + val addressB = address(systemB) + val rootB = RootActorPath(addressB) + systemB.actorOf(TestActors.echoActorProps, "echo") system.actorSelection(rootB / "user" / "echo") ! Identify("echo") - expectNoMessage(2.seconds) + val id = expectMsgType[ActorIdentity] + + id.ref.get ! "42" + expectMsg("42") + + systemB.terminate() } } }