Skip to content
This repository was archived by the owner on Oct 23, 2024. It is now read-only.

Commit 359a2dc

Browse files
authored
Fix of http marathon healthchecks (#6115)
Reused some of smart akka-http code related to setting headers and filtering URIs JIRA issues: MARATHON-8136 (cherry picked from commit 276ce1a)
1 parent eb63ae4 commit 359a2dc

File tree

2 files changed

+53
-32
lines changed

2 files changed

+53
-32
lines changed

src/main/scala/mesosphere/marathon/core/health/impl/HealthCheckWorkerActor.scala

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package core.health.impl
33

44
import java.net.{ InetSocketAddress, Socket }
55
import java.security.cert.X509Certificate
6-
import javax.net.ssl.{ KeyManager, SSLContext, X509TrustManager }
76

7+
import javax.net.ssl.{ KeyManager, SSLContext, X509TrustManager }
88
import akka.actor.{ Actor, PoisonPill }
99
import akka.http.scaladsl.settings.ClientConnectionSettings
1010
import akka.http.scaladsl.client.RequestBuilding
11-
import akka.http.scaladsl.model.{ HttpRequest, HttpResponse }
11+
import akka.http.scaladsl.model.{ HttpRequest, HttpResponse, headers }
1212
import akka.http.scaladsl.{ ConnectionContext, Http }
1313
import akka.stream.{ ActorMaterializer, ActorMaterializerSettings, Materializer }
1414
import akka.stream.scaladsl.{ Sink, Source }
@@ -150,7 +150,7 @@ class HealthCheckWorkerActor(implicit mat: Materializer) extends Actor with Stri
150150
val url = s"https://$host:$port$absolutePath"
151151
logger.debug(s"Checking the health of [$url] for instance=${instance.instanceId} via HTTPS")
152152

153-
singleRequest(
153+
singleRequestHttps(
154154
RequestBuilding.Get(url),
155155
check.timeout
156156
).map { response =>
@@ -169,34 +169,45 @@ class HealthCheckWorkerActor(implicit mat: Materializer) extends Actor with Stri
169169
}
170170

171171
def singleRequest(httpRequest: HttpRequest, timeout: FiniteDuration)(implicit mat: Materializer): Future[HttpResponse] = {
172-
if (httpRequest.uri.scheme.equalsIgnoreCase("https")) {
173-
// This is only a health check, so we are going to allow _very_ bad SSL configuration.
174-
val disabledSslConfig = AkkaSSLConfig().mapSettings(s => s.withLoose {
175-
s.loose.withAcceptAnyCertificate(true)
176-
.withAllowLegacyHelloMessages(Some(true))
177-
.withAllowUnsafeRenegotiation(Some(true))
178-
.withAllowWeakCiphers(true)
179-
.withAllowWeakProtocols(true)
180-
.withDisableHostnameVerification(true)
181-
.withDisableSNI(true)
182-
})
183-
val authority = httpRequest.uri.authority
184-
val connectionFlow = Http().outgoingConnectionHttps(
185-
authority.host.toString(),
186-
authority.port,
187-
ConnectionContext.https(disabledSslContext, sslConfig = Some(disabledSslConfig)),
188-
settings = ClientConnectionSettings(system).withIdleTimeout(timeout)
189-
)
190-
Source.single(httpRequest).via(connectionFlow).runWith(Sink.head)
191-
} else {
192-
val authority = httpRequest.uri.authority
193-
val connectionFlow = Http().outgoingConnection(
194-
authority.host.toString(),
195-
authority.port,
196-
settings = ClientConnectionSettings(system).withIdleTimeout(timeout)
197-
)
198-
Source.single(httpRequest).via(connectionFlow).runWith(Sink.head)
199-
}
172+
val host = httpRequest.uri.authority.host.toString()
173+
val port = httpRequest.uri.effectivePort
174+
val hostHeader = headers.Host(host, port)
175+
val effectiveRequest = httpRequest
176+
.withUri(httpRequest.uri.toHttpRequestTargetOriginForm)
177+
.withDefaultHeaders(hostHeader)
178+
179+
val connectionFlow = Http().outgoingConnection(
180+
host,
181+
port,
182+
settings = ClientConnectionSettings(system).withIdleTimeout(timeout)
183+
)
184+
Source.single(effectiveRequest).via(connectionFlow).runWith(Sink.head)
185+
}
186+
187+
def singleRequestHttps(httpRequest: HttpRequest, timeout: FiniteDuration)(implicit mat: Materializer): Future[HttpResponse] = {
188+
val host = httpRequest.uri.authority.host.toString()
189+
val port = httpRequest.uri.effectivePort
190+
val hostHeader = headers.Host(host, port)
191+
val effectiveRequest = httpRequest
192+
.withUri(httpRequest.uri.toHttpRequestTargetOriginForm)
193+
.withDefaultHeaders(hostHeader)
194+
// This is only a health check, so we are going to allow _very_ bad SSL configuration.
195+
val disabledSslConfig = AkkaSSLConfig().mapSettings(s => s.withLoose {
196+
s.loose.withAcceptAnyCertificate(true)
197+
.withAllowLegacyHelloMessages(Some(true))
198+
.withAllowUnsafeRenegotiation(Some(true))
199+
.withAllowWeakCiphers(true)
200+
.withAllowWeakProtocols(true)
201+
.withDisableHostnameVerification(true)
202+
.withDisableSNI(true)
203+
})
204+
val connectionFlow = Http().outgoingConnectionHttps(
205+
host,
206+
port,
207+
ConnectionContext.https(disabledSslContext, sslConfig = Some(disabledSslConfig)),
208+
settings = ClientConnectionSettings(system).withIdleTimeout(timeout)
209+
)
210+
Source.single(effectiveRequest).via(connectionFlow).runWith(Sink.head)
200211
}
201212
}
202213

src/test/scala/mesosphere/marathon/core/health/impl/HealthCheckWorkerActorTest.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ class HealthCheckWorkerActorTest extends AkkaUnitTest with ImplicitSender {
100100
promise.success("success")
101101
complete(StatusCodes.OK)
102102
}
103-
}
103+
} ~
104+
path("unhealthy"){
105+
get {
106+
complete(StatusCodes.InternalServerError)
107+
}
108+
}
104109

105110
val binding = Http().bindAndHandle(route, "localhost", 0).futureValue
106111

@@ -124,9 +129,14 @@ class HealthCheckWorkerActorTest extends AkkaUnitTest with ImplicitSender {
124129

125130
val ref = system.actorOf(Props(classOf[HealthCheckWorkerActor], mat))
126131
ref ! HealthCheckJob(app, instance, MarathonHttpHealthCheck(port = Some(port), path = Some("/health")))
132+
expectMsgClass(classOf[Healthy])
127133

128134
promise.future.futureValue shouldEqual "success"
129135

136+
val unhealthy = system.actorOf(Props(classOf[HealthCheckWorkerActor], mat))
137+
unhealthy ! HealthCheckJob(app, instance, MarathonHttpHealthCheck(port = Some(port), path = Some("/unhealthy")))
138+
expectMsgClass(classOf[Unhealthy])
139+
130140
}
131141
}
132142
}

0 commit comments

Comments
 (0)